Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / base / pickle_unittest.cc
blob6f9fcc7f62ad898bf4b7de91aee43faafddbda6d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <string>
7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/pickle.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 namespace base {
16 namespace {
18 const bool testbool1 = false;
19 const bool testbool2 = true;
20 const int testint = 2093847192;
21 const long testlong = 1093847192;
22 const uint16 testuint16 = 32123;
23 const uint32 testuint32 = 1593847192;
24 const int64 testint64 = -0x7E8CA9253104BDFCLL;
25 const uint64 testuint64 = 0xCE8CA9253104BDF7ULL;
26 const size_t testsizet = 0xFEDC7654;
27 const float testfloat = 3.1415926935f;
28 const double testdouble = 2.71828182845904523;
29 const std::string teststring("Hello world"); // note non-aligned string length
30 const std::wstring testwstring(L"Hello, world");
31 const string16 teststring16(ASCIIToUTF16("Hello, world"));
32 const char testrawstring[] = "Hello new world"; // Test raw string writing
33 // Test raw char16 writing, assumes UTF16 encoding is ANSI for alpha chars.
34 const char16 testrawstring16[] = {'A', 'l', 'o', 'h', 'a', 0};
35 const char testdata[] = "AAA\0BBB\0";
36 const int testdatalen = arraysize(testdata) - 1;
38 // checks that the results can be read correctly from the Pickle
39 void VerifyResult(const Pickle& pickle) {
40 PickleIterator iter(pickle);
42 bool outbool;
43 EXPECT_TRUE(iter.ReadBool(&outbool));
44 EXPECT_FALSE(outbool);
45 EXPECT_TRUE(iter.ReadBool(&outbool));
46 EXPECT_TRUE(outbool);
48 int outint;
49 EXPECT_TRUE(iter.ReadInt(&outint));
50 EXPECT_EQ(testint, outint);
52 long outlong;
53 EXPECT_TRUE(iter.ReadLong(&outlong));
54 EXPECT_EQ(testlong, outlong);
56 uint16 outuint16;
57 EXPECT_TRUE(iter.ReadUInt16(&outuint16));
58 EXPECT_EQ(testuint16, outuint16);
60 uint32 outuint32;
61 EXPECT_TRUE(iter.ReadUInt32(&outuint32));
62 EXPECT_EQ(testuint32, outuint32);
64 int64 outint64;
65 EXPECT_TRUE(iter.ReadInt64(&outint64));
66 EXPECT_EQ(testint64, outint64);
68 uint64 outuint64;
69 EXPECT_TRUE(iter.ReadUInt64(&outuint64));
70 EXPECT_EQ(testuint64, outuint64);
72 size_t outsizet;
73 EXPECT_TRUE(iter.ReadSizeT(&outsizet));
74 EXPECT_EQ(testsizet, outsizet);
76 float outfloat;
77 EXPECT_TRUE(iter.ReadFloat(&outfloat));
78 EXPECT_EQ(testfloat, outfloat);
80 double outdouble;
81 EXPECT_TRUE(iter.ReadDouble(&outdouble));
82 EXPECT_EQ(testdouble, outdouble);
84 std::string outstring;
85 EXPECT_TRUE(iter.ReadString(&outstring));
86 EXPECT_EQ(teststring, outstring);
88 string16 outstring16;
89 EXPECT_TRUE(iter.ReadString16(&outstring16));
90 EXPECT_EQ(teststring16, outstring16);
92 StringPiece outstringpiece;
93 EXPECT_TRUE(iter.ReadStringPiece(&outstringpiece));
94 EXPECT_EQ(testrawstring, outstringpiece);
96 StringPiece16 outstringpiece16;
97 EXPECT_TRUE(iter.ReadStringPiece16(&outstringpiece16));
98 EXPECT_EQ(testrawstring16, outstringpiece16);
100 const char* outdata;
101 int outdatalen;
102 EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
103 EXPECT_EQ(testdatalen, outdatalen);
104 EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0);
106 // reads past the end should fail
107 EXPECT_FALSE(iter.ReadInt(&outint));
110 } // namespace
112 TEST(PickleTest, EncodeDecode) {
113 Pickle pickle;
115 EXPECT_TRUE(pickle.WriteBool(testbool1));
116 EXPECT_TRUE(pickle.WriteBool(testbool2));
117 EXPECT_TRUE(pickle.WriteInt(testint));
118 EXPECT_TRUE(
119 pickle.WriteLongUsingDangerousNonPortableLessPersistableForm(testlong));
120 EXPECT_TRUE(pickle.WriteUInt16(testuint16));
121 EXPECT_TRUE(pickle.WriteUInt32(testuint32));
122 EXPECT_TRUE(pickle.WriteInt64(testint64));
123 EXPECT_TRUE(pickle.WriteUInt64(testuint64));
124 EXPECT_TRUE(pickle.WriteSizeT(testsizet));
125 EXPECT_TRUE(pickle.WriteFloat(testfloat));
126 EXPECT_TRUE(pickle.WriteDouble(testdouble));
127 EXPECT_TRUE(pickle.WriteString(teststring));
128 EXPECT_TRUE(pickle.WriteString16(teststring16));
129 EXPECT_TRUE(pickle.WriteString(testrawstring));
130 EXPECT_TRUE(pickle.WriteString16(testrawstring16));
131 EXPECT_TRUE(pickle.WriteData(testdata, testdatalen));
132 VerifyResult(pickle);
134 // test copy constructor
135 Pickle pickle2(pickle);
136 VerifyResult(pickle2);
138 // test operator=
139 Pickle pickle3;
140 pickle3 = pickle;
141 VerifyResult(pickle3);
144 // Tests that reading/writing a size_t works correctly when the source process
145 // is 64-bit. We rely on having both 32- and 64-bit trybots to validate both
146 // arms of the conditional in this test.
147 TEST(PickleTest, SizeTFrom64Bit) {
148 Pickle pickle;
149 // Under the hood size_t is always written as a 64-bit value, so simulate a
150 // 64-bit size_t even on 32-bit architectures by explicitly writing a uint64.
151 EXPECT_TRUE(pickle.WriteUInt64(testuint64));
153 PickleIterator iter(pickle);
154 size_t outsizet;
155 if (sizeof(size_t) < sizeof(uint64)) {
156 // ReadSizeT() should return false when the original written value can't be
157 // represented as a size_t.
158 EXPECT_FALSE(iter.ReadSizeT(&outsizet));
159 } else {
160 EXPECT_TRUE(iter.ReadSizeT(&outsizet));
161 EXPECT_EQ(testuint64, outsizet);
165 // Tests that we can handle really small buffers.
166 TEST(PickleTest, SmallBuffer) {
167 scoped_ptr<char[]> buffer(new char[1]);
169 // We should not touch the buffer.
170 Pickle pickle(buffer.get(), 1);
172 PickleIterator iter(pickle);
173 int data;
174 EXPECT_FALSE(iter.ReadInt(&data));
177 // Tests that we can handle improper headers.
178 TEST(PickleTest, BigSize) {
179 int buffer[] = { 0x56035200, 25, 40, 50 };
181 Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
183 PickleIterator iter(pickle);
184 int data;
185 EXPECT_FALSE(iter.ReadInt(&data));
188 TEST(PickleTest, UnalignedSize) {
189 int buffer[] = { 10, 25, 40, 50 };
191 Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
193 PickleIterator iter(pickle);
194 int data;
195 EXPECT_FALSE(iter.ReadInt(&data));
198 TEST(PickleTest, ZeroLenStr) {
199 Pickle pickle;
200 EXPECT_TRUE(pickle.WriteString(std::string()));
202 PickleIterator iter(pickle);
203 std::string outstr;
204 EXPECT_TRUE(iter.ReadString(&outstr));
205 EXPECT_EQ("", outstr);
208 TEST(PickleTest, ZeroLenStr16) {
209 Pickle pickle;
210 EXPECT_TRUE(pickle.WriteString16(string16()));
212 PickleIterator iter(pickle);
213 std::string outstr;
214 EXPECT_TRUE(iter.ReadString(&outstr));
215 EXPECT_EQ("", outstr);
218 TEST(PickleTest, BadLenStr) {
219 Pickle pickle;
220 EXPECT_TRUE(pickle.WriteInt(-2));
222 PickleIterator iter(pickle);
223 std::string outstr;
224 EXPECT_FALSE(iter.ReadString(&outstr));
227 TEST(PickleTest, BadLenStr16) {
228 Pickle pickle;
229 EXPECT_TRUE(pickle.WriteInt(-1));
231 PickleIterator iter(pickle);
232 string16 outstr;
233 EXPECT_FALSE(iter.ReadString16(&outstr));
236 TEST(PickleTest, FindNext) {
237 Pickle pickle;
238 EXPECT_TRUE(pickle.WriteInt(1));
239 EXPECT_TRUE(pickle.WriteString("Domo"));
241 const char* start = reinterpret_cast<const char*>(pickle.data());
242 const char* end = start + pickle.size();
244 EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end));
245 EXPECT_TRUE(NULL == Pickle::FindNext(pickle.header_size_, start, end - 1));
246 EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end + 1));
249 TEST(PickleTest, FindNextWithIncompleteHeader) {
250 size_t header_size = sizeof(Pickle::Header);
251 scoped_ptr<char[]> buffer(new char[header_size - 1]);
252 memset(buffer.get(), 0x1, header_size - 1);
254 const char* start = buffer.get();
255 const char* end = start + header_size - 1;
257 EXPECT_TRUE(NULL == Pickle::FindNext(header_size, start, end));
260 #if defined(COMPILER_MSVC)
261 #pragma warning(push)
262 #pragma warning(disable: 4146)
263 #endif
264 TEST(PickleTest, FindNextOverflow) {
265 size_t header_size = sizeof(Pickle::Header);
266 size_t header_size2 = 2 * header_size;
267 size_t payload_received = 100;
268 scoped_ptr<char[]> buffer(new char[header_size2 + payload_received]);
269 const char* start = buffer.get();
270 Pickle::Header* header = reinterpret_cast<Pickle::Header*>(buffer.get());
271 const char* end = start + header_size2 + payload_received;
272 // It is impossible to construct an overflow test otherwise.
273 if (sizeof(size_t) > sizeof(header->payload_size) ||
274 sizeof(uintptr_t) > sizeof(header->payload_size))
275 return;
277 header->payload_size = -(reinterpret_cast<uintptr_t>(start) + header_size2);
278 EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));
280 header->payload_size = -header_size2;
281 EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));
283 header->payload_size = 0;
284 end = start + header_size;
285 EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));
287 #if defined(COMPILER_MSVC)
288 #pragma warning(pop)
289 #endif
291 TEST(PickleTest, GetReadPointerAndAdvance) {
292 Pickle pickle;
294 PickleIterator iter(pickle);
295 EXPECT_FALSE(iter.GetReadPointerAndAdvance(1));
297 EXPECT_TRUE(pickle.WriteInt(1));
298 EXPECT_TRUE(pickle.WriteInt(2));
299 int bytes = sizeof(int) * 2;
301 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(0));
302 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(1));
303 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(-1));
304 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes));
305 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes + 1));
306 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MAX));
307 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MIN));
310 TEST(PickleTest, Resize) {
311 size_t unit = Pickle::kPayloadUnit;
312 scoped_ptr<char[]> data(new char[unit]);
313 char* data_ptr = data.get();
314 for (size_t i = 0; i < unit; i++)
315 data_ptr[i] = 'G';
317 // construct a message that will be exactly the size of one payload unit,
318 // note that any data will have a 4-byte header indicating the size
319 const size_t payload_size_after_header = unit - sizeof(uint32);
320 Pickle pickle;
321 pickle.WriteData(data_ptr,
322 static_cast<int>(payload_size_after_header - sizeof(uint32)));
323 size_t cur_payload = payload_size_after_header;
325 // note: we assume 'unit' is a power of 2
326 EXPECT_EQ(unit, pickle.capacity_after_header());
327 EXPECT_EQ(pickle.payload_size(), payload_size_after_header);
329 // fill out a full page (noting data header)
330 pickle.WriteData(data_ptr, static_cast<int>(unit - sizeof(uint32)));
331 cur_payload += unit;
332 EXPECT_EQ(unit * 2, pickle.capacity_after_header());
333 EXPECT_EQ(cur_payload, pickle.payload_size());
335 // one more byte should double the capacity
336 pickle.WriteData(data_ptr, 1);
337 cur_payload += 8;
338 EXPECT_EQ(unit * 4, pickle.capacity_after_header());
339 EXPECT_EQ(cur_payload, pickle.payload_size());
342 namespace {
344 struct CustomHeader : Pickle::Header {
345 int blah;
348 } // namespace
350 TEST(PickleTest, HeaderPadding) {
351 const uint32 kMagic = 0x12345678;
353 Pickle pickle(sizeof(CustomHeader));
354 pickle.WriteInt(kMagic);
356 // this should not overwrite the 'int' payload
357 pickle.headerT<CustomHeader>()->blah = 10;
359 PickleIterator iter(pickle);
360 int result;
361 ASSERT_TRUE(iter.ReadInt(&result));
363 EXPECT_EQ(static_cast<uint32>(result), kMagic);
366 TEST(PickleTest, EqualsOperator) {
367 Pickle source;
368 source.WriteInt(1);
370 Pickle copy_refs_source_buffer(static_cast<const char*>(source.data()),
371 source.size());
372 Pickle copy;
373 copy = copy_refs_source_buffer;
374 ASSERT_EQ(source.size(), copy.size());
377 TEST(PickleTest, EvilLengths) {
378 Pickle source;
379 std::string str(100000, 'A');
380 EXPECT_TRUE(source.WriteData(str.c_str(), 100000));
381 // ReadString16 used to have its read buffer length calculation wrong leading
382 // to out-of-bounds reading.
383 PickleIterator iter(source);
384 string16 str16;
385 EXPECT_FALSE(iter.ReadString16(&str16));
387 // And check we didn't break ReadString16.
388 str16 = (wchar_t) 'A';
389 Pickle str16_pickle;
390 EXPECT_TRUE(str16_pickle.WriteString16(str16));
391 iter = PickleIterator(str16_pickle);
392 EXPECT_TRUE(iter.ReadString16(&str16));
393 EXPECT_EQ(1U, str16.length());
395 // Check we don't fail in a length check with invalid String16 size.
396 // (1<<31) * sizeof(char16) == 0, so this is particularly evil.
397 Pickle bad_len;
398 EXPECT_TRUE(bad_len.WriteInt(1 << 31));
399 iter = PickleIterator(bad_len);
400 EXPECT_FALSE(iter.ReadString16(&str16));
403 // Check we can write zero bytes of data and 'data' can be NULL.
404 TEST(PickleTest, ZeroLength) {
405 Pickle pickle;
406 EXPECT_TRUE(pickle.WriteData(NULL, 0));
408 PickleIterator iter(pickle);
409 const char* outdata;
410 int outdatalen;
411 EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
412 EXPECT_EQ(0, outdatalen);
413 // We can't assert that outdata is NULL.
416 // Check that ReadBytes works properly with an iterator initialized to NULL.
417 TEST(PickleTest, ReadBytes) {
418 Pickle pickle;
419 int data = 0x7abcd;
420 EXPECT_TRUE(pickle.WriteBytes(&data, sizeof(data)));
422 PickleIterator iter(pickle);
423 const char* outdata_char = NULL;
424 EXPECT_TRUE(iter.ReadBytes(&outdata_char, sizeof(data)));
426 int outdata;
427 memcpy(&outdata, outdata_char, sizeof(outdata));
428 EXPECT_EQ(data, outdata);
431 // Checks that when a pickle is deep-copied, the result is not larger than
432 // needed.
433 TEST(PickleTest, DeepCopyResize) {
434 Pickle pickle;
435 while (pickle.capacity_after_header() != pickle.payload_size())
436 pickle.WriteBool(true);
438 // Make a deep copy.
439 Pickle pickle2(pickle);
441 // Check that there isn't any extraneous capacity.
442 EXPECT_EQ(pickle.capacity_after_header(), pickle2.capacity_after_header());
445 } // namespace base