summaryrefslogtreecommitdiffstats
path: root/base/pickle_unittest.cc
blob: 307cb5134da04011b132c0a2623ae27c0254239c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <limits.h>
#include <stddef.h>
#include <stdint.h>

#include <string>

#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/pickle.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {

namespace {

const bool testbool1 = false;
const bool testbool2 = true;
const int testint = 2093847192;
const long testlong = 1093847192;
const uint16_t testuint16 = 32123;
const uint32_t testuint32 = 1593847192;
const int64_t testint64 = -0x7E8CA9253104BDFCLL;
const uint64_t testuint64 = 0xCE8CA9253104BDF7ULL;
const float testfloat = 3.1415926935f;
const double testdouble = 2.71828182845904523;
const std::string teststring("Hello world");  // note non-aligned string length
const std::wstring testwstring(L"Hello, world");
const string16 teststring16(ASCIIToUTF16("Hello, world"));
const char testrawstring[] = "Hello new world"; // Test raw string writing
// Test raw char16 writing, assumes UTF16 encoding is ANSI for alpha chars.
const char16 testrawstring16[] = {'A', 'l', 'o', 'h', 'a', 0};
const char testdata[] = "AAA\0BBB\0";
const int testdatalen = arraysize(testdata) - 1;

// checks that the results can be read correctly from the Pickle
void VerifyResult(const Pickle& pickle) {
  PickleIterator iter(pickle);

  bool outbool;
  EXPECT_TRUE(iter.ReadBool(&outbool));
  EXPECT_FALSE(outbool);
  EXPECT_TRUE(iter.ReadBool(&outbool));
  EXPECT_TRUE(outbool);

  int outint;
  EXPECT_TRUE(iter.ReadInt(&outint));
  EXPECT_EQ(testint, outint);

  long outlong;
  EXPECT_TRUE(iter.ReadLong(&outlong));
  EXPECT_EQ(testlong, outlong);

  uint16_t outuint16;
  EXPECT_TRUE(iter.ReadUInt16(&outuint16));
  EXPECT_EQ(testuint16, outuint16);

  uint32_t outuint32;
  EXPECT_TRUE(iter.ReadUInt32(&outuint32));
  EXPECT_EQ(testuint32, outuint32);

  int64_t outint64;
  EXPECT_TRUE(iter.ReadInt64(&outint64));
  EXPECT_EQ(testint64, outint64);

  uint64_t outuint64;
  EXPECT_TRUE(iter.ReadUInt64(&outuint64));
  EXPECT_EQ(testuint64, outuint64);

  float outfloat;
  EXPECT_TRUE(iter.ReadFloat(&outfloat));
  EXPECT_EQ(testfloat, outfloat);

  double outdouble;
  EXPECT_TRUE(iter.ReadDouble(&outdouble));
  EXPECT_EQ(testdouble, outdouble);

  std::string outstring;
  EXPECT_TRUE(iter.ReadString(&outstring));
  EXPECT_EQ(teststring, outstring);

  string16 outstring16;
  EXPECT_TRUE(iter.ReadString16(&outstring16));
  EXPECT_EQ(teststring16, outstring16);

  StringPiece outstringpiece;
  EXPECT_TRUE(iter.ReadStringPiece(&outstringpiece));
  EXPECT_EQ(testrawstring, outstringpiece);

  StringPiece16 outstringpiece16;
  EXPECT_TRUE(iter.ReadStringPiece16(&outstringpiece16));
  EXPECT_EQ(testrawstring16, outstringpiece16);

  const char* outdata;
  int outdatalen;
  EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
  EXPECT_EQ(testdatalen, outdatalen);
  EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0);

  // reads past the end should fail
  EXPECT_FALSE(iter.ReadInt(&outint));
}

}  // namespace

TEST(PickleTest, EncodeDecode) {
  Pickle pickle;

  EXPECT_TRUE(pickle.WriteBool(testbool1));
  EXPECT_TRUE(pickle.WriteBool(testbool2));
  EXPECT_TRUE(pickle.WriteInt(testint));
  EXPECT_TRUE(pickle.WriteLong(testlong));
  EXPECT_TRUE(pickle.WriteUInt16(testuint16));
  EXPECT_TRUE(pickle.WriteUInt32(testuint32));
  EXPECT_TRUE(pickle.WriteInt64(testint64));
  EXPECT_TRUE(pickle.WriteUInt64(testuint64));
  EXPECT_TRUE(pickle.WriteFloat(testfloat));
  EXPECT_TRUE(pickle.WriteDouble(testdouble));
  EXPECT_TRUE(pickle.WriteString(teststring));
  EXPECT_TRUE(pickle.WriteString16(teststring16));
  EXPECT_TRUE(pickle.WriteString(testrawstring));
  EXPECT_TRUE(pickle.WriteString16(testrawstring16));
  EXPECT_TRUE(pickle.WriteData(testdata, testdatalen));
  VerifyResult(pickle);

  // test copy constructor
  Pickle pickle2(pickle);
  VerifyResult(pickle2);

  // test operator=
  Pickle pickle3;
  pickle3 = pickle;
  VerifyResult(pickle3);
}

// Tests that reading/writing a long works correctly when the source process
// is 64-bit.  We rely on having both 32- and 64-bit trybots to validate both
// arms of the conditional in this test.
TEST(PickleTest, LongFrom64Bit) {
  Pickle pickle;
  // Under the hood long is always written as a 64-bit value, so simulate a
  // 64-bit long even on 32-bit architectures by explicitly writing an int64_t.
  EXPECT_TRUE(pickle.WriteInt64(testint64));

  PickleIterator iter(pickle);
  long outlong;
  if (sizeof(long) < sizeof(int64_t)) {
    // ReadLong() should return false when the original written value can't be
    // represented as a long.
#if GTEST_HAS_DEATH_TEST
    EXPECT_DEATH(ignore_result(iter.ReadLong(&outlong)), "");
#endif
  } else {
    EXPECT_TRUE(iter.ReadLong(&outlong));
    EXPECT_EQ(testint64, outlong);
  }
}

// Tests that we can handle really small buffers.
TEST(PickleTest, SmallBuffer) {
  scoped_ptr<char[]> buffer(new char[1]);

  // We should not touch the buffer.
  Pickle pickle(buffer.get(), 1);

  PickleIterator iter(pickle);
  int data;
  EXPECT_FALSE(iter.ReadInt(&data));
}

// Tests that we can handle improper headers.
TEST(PickleTest, BigSize) {
  int buffer[] = { 0x56035200, 25, 40, 50 };

  Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));

  PickleIterator iter(pickle);
  int data;
  EXPECT_FALSE(iter.ReadInt(&data));
}

TEST(PickleTest, UnalignedSize) {
  int buffer[] = { 10, 25, 40, 50 };

  Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));

  PickleIterator iter(pickle);
  int data;
  EXPECT_FALSE(iter.ReadInt(&data));
}

TEST(PickleTest, ZeroLenStr) {
  Pickle pickle;
  EXPECT_TRUE(pickle.WriteString(std::string()));

  PickleIterator iter(pickle);
  std::string outstr;
  EXPECT_TRUE(iter.ReadString(&outstr));
  EXPECT_EQ("", outstr);
}

TEST(PickleTest, ZeroLenStr16) {
  Pickle pickle;
  EXPECT_TRUE(pickle.WriteString16(string16()));

  PickleIterator iter(pickle);
  std::string outstr;
  EXPECT_TRUE(iter.ReadString(&outstr));
  EXPECT_EQ("", outstr);
}

TEST(PickleTest, BadLenStr) {
  Pickle pickle;
  EXPECT_TRUE(pickle.WriteInt(-2));

  PickleIterator iter(pickle);
  std::string outstr;
  EXPECT_FALSE(iter.ReadString(&outstr));
}

TEST(PickleTest, BadLenStr16) {
  Pickle pickle;
  EXPECT_TRUE(pickle.WriteInt(-1));

  PickleIterator iter(pickle);
  string16 outstr;
  EXPECT_FALSE(iter.ReadString16(&outstr));
}

TEST(PickleTest, PeekNext) {
  struct CustomHeader : base::Pickle::Header {
    int cookies[10];
  };

  Pickle pickle(sizeof(CustomHeader));

  EXPECT_TRUE(pickle.WriteString("Goooooooooooogle"));

  const char* pickle_data = static_cast<const char*>(pickle.data());

  size_t pickle_size;

  // Data range doesn't contain header
  EXPECT_FALSE(Pickle::PeekNext(
      sizeof(CustomHeader),
      pickle_data,
      pickle_data + sizeof(CustomHeader) - 1,
      &pickle_size));

  // Data range contains header
  EXPECT_TRUE(Pickle::PeekNext(
      sizeof(CustomHeader),
      pickle_data,
      pickle_data + sizeof(CustomHeader),
      &pickle_size));
  EXPECT_EQ(pickle_size, pickle.size());

  // Data range contains header and some other data
  EXPECT_TRUE(Pickle::PeekNext(
      sizeof(CustomHeader),
      pickle_data,
      pickle_data + sizeof(CustomHeader) + 1,
      &pickle_size));
  EXPECT_EQ(pickle_size, pickle.size());

  // Data range contains full pickle
  EXPECT_TRUE(Pickle::PeekNext(
      sizeof(CustomHeader),
      pickle_data,
      pickle_data + pickle.size(),
      &pickle_size));
  EXPECT_EQ(pickle_size, pickle.size());
}

TEST(PickleTest, PeekNextOverflow) {
  struct CustomHeader : base::Pickle::Header {
    int cookies[10];
  };

  CustomHeader header;

  // Check if we can wrap around at all
  if (sizeof(size_t) > sizeof(header.payload_size))
    return;

  const char* pickle_data = reinterpret_cast<const char*>(&header);

  size_t pickle_size;

  // Wrapping around is detected and reported as maximum size_t value
  header.payload_size = static_cast<uint32_t>(
      1 - static_cast<int32_t>(sizeof(CustomHeader)));
  EXPECT_TRUE(Pickle::PeekNext(
      sizeof(CustomHeader),
      pickle_data,
      pickle_data + sizeof(CustomHeader),
      &pickle_size));
  EXPECT_EQ(pickle_size, std::numeric_limits<size_t>::max());

  // Ridiculous pickle sizes are fine (callers are supposed to
  // verify them)
  header.payload_size =
      std::numeric_limits<uint32_t>::max() / 2 - sizeof(CustomHeader);
  EXPECT_TRUE(Pickle::PeekNext(
      sizeof(CustomHeader),
      pickle_data,
      pickle_data + sizeof(CustomHeader),
      &pickle_size));
  EXPECT_EQ(pickle_size, std::numeric_limits<uint32_t>::max() / 2);
}

TEST(PickleTest, FindNext) {
  Pickle pickle;
  EXPECT_TRUE(pickle.WriteInt(1));
  EXPECT_TRUE(pickle.WriteString("Domo"));

  const char* start = reinterpret_cast<const char*>(pickle.data());
  const char* end = start + pickle.size();

  EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end));
  EXPECT_TRUE(NULL == Pickle::FindNext(pickle.header_size_, start, end - 1));
  EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end + 1));
}

TEST(PickleTest, FindNextWithIncompleteHeader) {
  size_t header_size = sizeof(Pickle::Header);
  scoped_ptr<char[]> buffer(new char[header_size - 1]);
  memset(buffer.get(), 0x1, header_size - 1);

  const char* start = buffer.get();
  const char* end = start + header_size - 1;

  EXPECT_TRUE(NULL == Pickle::FindNext(header_size, start, end));
}

#if defined(COMPILER_MSVC)
#pragma warning(push)
#pragma warning(disable: 4146)
#endif
TEST(PickleTest, FindNextOverflow) {
  size_t header_size = sizeof(Pickle::Header);
  size_t header_size2 = 2 * header_size;
  size_t payload_received = 100;
  scoped_ptr<char[]> buffer(new char[header_size2 + payload_received]);
  const char* start = buffer.get();
  Pickle::Header* header = reinterpret_cast<Pickle::Header*>(buffer.get());
  const char* end = start + header_size2 + payload_received;
  // It is impossible to construct an overflow test otherwise.
  if (sizeof(size_t) > sizeof(header->payload_size) ||
      sizeof(uintptr_t) > sizeof(header->payload_size))
    return;

  header->payload_size = -(reinterpret_cast<uintptr_t>(start) + header_size2);
  EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));

  header->payload_size = -header_size2;
  EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));

  header->payload_size = 0;
  end = start + header_size;
  EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));
}
#if defined(COMPILER_MSVC)
#pragma warning(pop)
#endif

TEST(PickleTest, GetReadPointerAndAdvance) {
  Pickle pickle;

  PickleIterator iter(pickle);
  EXPECT_FALSE(iter.GetReadPointerAndAdvance(1));

  EXPECT_TRUE(pickle.WriteInt(1));
  EXPECT_TRUE(pickle.WriteInt(2));
  int bytes = sizeof(int) * 2;

  EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(0));
  EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(1));
  EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(-1));
  EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes));
  EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes + 1));
  EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MAX));
  EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MIN));
}

TEST(PickleTest, Resize) {
  size_t unit = Pickle::kPayloadUnit;
  scoped_ptr<char[]> data(new char[unit]);
  char* data_ptr = data.get();
  for (size_t i = 0; i < unit; i++)
    data_ptr[i] = 'G';

  // construct a message that will be exactly the size of one payload unit,
  // note that any data will have a 4-byte header indicating the size
  const size_t payload_size_after_header = unit - sizeof(uint32_t);
  Pickle pickle;
  pickle.WriteData(
      data_ptr, static_cast<int>(payload_size_after_header - sizeof(uint32_t)));
  size_t cur_payload = payload_size_after_header;

  // note: we assume 'unit' is a power of 2
  EXPECT_EQ(unit, pickle.capacity_after_header());
  EXPECT_EQ(pickle.payload_size(), payload_size_after_header);

  // fill out a full page (noting data header)
  pickle.WriteData(data_ptr, static_cast<int>(unit - sizeof(uint32_t)));
  cur_payload += unit;
  EXPECT_EQ(unit * 2, pickle.capacity_after_header());
  EXPECT_EQ(cur_payload, pickle.payload_size());

  // one more byte should double the capacity
  pickle.WriteData(data_ptr, 1);
  cur_payload += 8;
  EXPECT_EQ(unit * 4, pickle.capacity_after_header());
  EXPECT_EQ(cur_payload, pickle.payload_size());
}

namespace {

struct CustomHeader : Pickle::Header {
  int blah;
};

}  // namespace

TEST(PickleTest, HeaderPadding) {
  const uint32_t kMagic = 0x12345678;

  Pickle pickle(sizeof(CustomHeader));
  pickle.WriteInt(kMagic);

  // this should not overwrite the 'int' payload
  pickle.headerT<CustomHeader>()->blah = 10;

  PickleIterator iter(pickle);
  int result;
  ASSERT_TRUE(iter.ReadInt(&result));

  EXPECT_EQ(static_cast<uint32_t>(result), kMagic);
}

TEST(PickleTest, EqualsOperator) {
  Pickle source;
  source.WriteInt(1);

  Pickle copy_refs_source_buffer(static_cast<const char*>(source.data()),
                                 source.size());
  Pickle copy;
  copy = copy_refs_source_buffer;
  ASSERT_EQ(source.size(), copy.size());
}

TEST(PickleTest, EvilLengths) {
  Pickle source;
  std::string str(100000, 'A');
  EXPECT_TRUE(source.WriteData(str.c_str(), 100000));
  // ReadString16 used to have its read buffer length calculation wrong leading
  // to out-of-bounds reading.
  PickleIterator iter(source);
  string16 str16;
  EXPECT_FALSE(iter.ReadString16(&str16));

  // And check we didn't break ReadString16.
  str16 = (wchar_t) 'A';
  Pickle str16_pickle;
  EXPECT_TRUE(str16_pickle.WriteString16(str16));
  iter = PickleIterator(str16_pickle);
  EXPECT_TRUE(iter.ReadString16(&str16));
  EXPECT_EQ(1U, str16.length());

  // Check we don't fail in a length check with invalid String16 size.
  // (1<<31) * sizeof(char16) == 0, so this is particularly evil.
  Pickle bad_len;
  EXPECT_TRUE(bad_len.WriteInt(1 << 31));
  iter = PickleIterator(bad_len);
  EXPECT_FALSE(iter.ReadString16(&str16));
}

// Check we can write zero bytes of data and 'data' can be NULL.
TEST(PickleTest, ZeroLength) {
  Pickle pickle;
  EXPECT_TRUE(pickle.WriteData(NULL, 0));

  PickleIterator iter(pickle);
  const char* outdata;
  int outdatalen;
  EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
  EXPECT_EQ(0, outdatalen);
  // We can't assert that outdata is NULL.
}

// Check that ReadBytes works properly with an iterator initialized to NULL.
TEST(PickleTest, ReadBytes) {
  Pickle pickle;
  int data = 0x7abcd;
  EXPECT_TRUE(pickle.WriteBytes(&data, sizeof(data)));

  PickleIterator iter(pickle);
  const char* outdata_char = NULL;
  EXPECT_TRUE(iter.ReadBytes(&outdata_char, sizeof(data)));

  int outdata;
  memcpy(&outdata, outdata_char, sizeof(outdata));
  EXPECT_EQ(data, outdata);
}

// Checks that when a pickle is deep-copied, the result is not larger than
// needed.
TEST(PickleTest, DeepCopyResize) {
  Pickle pickle;
  while (pickle.capacity_after_header() != pickle.payload_size())
    pickle.WriteBool(true);

  // Make a deep copy.
  Pickle pickle2(pickle);

  // Check that there isn't any extraneous capacity.
  EXPECT_EQ(pickle.capacity_after_header(), pickle2.capacity_after_header());
}

namespace {

// Publicly exposes the ClaimBytes interface for testing.
class TestingPickle : public Pickle {
 public:
  TestingPickle() {}

  void* ClaimBytes(size_t num_bytes) { return Pickle::ClaimBytes(num_bytes); }
};

}  // namespace

// Checks that claimed bytes are zero-initialized.
TEST(PickleTest, ClaimBytesInitialization) {
  static const int kChunkSize = 64;
  TestingPickle pickle;
  const char* bytes = static_cast<const char*>(pickle.ClaimBytes(kChunkSize));
  for (size_t i = 0; i < kChunkSize; ++i) {
    EXPECT_EQ(0, bytes[i]);
  }
}

// Checks that ClaimBytes properly advances the write offset.
TEST(PickleTest, ClaimBytes) {
  std::string data("Hello, world!");

  TestingPickle pickle;
  pickle.WriteUInt32(data.size());
  void* bytes = pickle.ClaimBytes(data.size());
  pickle.WriteInt(42);
  memcpy(bytes, data.data(), data.size());

  PickleIterator iter(pickle);
  uint32_t out_data_length;
  EXPECT_TRUE(iter.ReadUInt32(&out_data_length));
  EXPECT_EQ(data.size(), out_data_length);

  const char* out_data = nullptr;
  EXPECT_TRUE(iter.ReadBytes(&out_data, out_data_length));
  EXPECT_EQ(data, std::string(out_data, out_data_length));

  int out_value;
  EXPECT_TRUE(iter.ReadInt(&out_value));
  EXPECT_EQ(42, out_value);
}

// Checks that PickleSizer and Pickle agree on the size of things.
TEST(PickleTest, PickleSizer) {
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteBool(true);
    sizer.AddBool();
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteInt(42);
    sizer.AddInt();
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteLong(42);
    sizer.AddLong();
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteUInt16(42);
    sizer.AddUInt16();
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteUInt32(42);
    sizer.AddUInt32();
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteInt64(42);
    sizer.AddInt64();
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteUInt64(42);
    sizer.AddUInt64();
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteFloat(42.0f);
    sizer.AddFloat();
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteDouble(42.0);
    sizer.AddDouble();
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteString(teststring);
    sizer.AddString(teststring);
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteString16(teststring16);
    sizer.AddString16(teststring16);
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteData(testdata, testdatalen);
    sizer.AddData(testdatalen);
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
  {
    TestingPickle pickle;
    base::PickleSizer sizer;
    pickle.WriteBytes(testdata, testdatalen);
    sizer.AddBytes(testdatalen);
    EXPECT_EQ(sizer.payload_size(), pickle.payload_size());
  }
}

}  // namespace base