- add sources.
[platform/framework/web/crosswalk.git] / src / base / pickle_unittest.cc
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.
4
5 #include <string>
6
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 "testing/gtest/include/gtest/gtest.h"
12
13 namespace {
14
15 const int testint = 2093847192;
16 const std::string teststr("Hello world");  // note non-aligned string length
17 const std::wstring testwstr(L"Hello, world");
18 const char testdata[] = "AAA\0BBB\0";
19 const int testdatalen = arraysize(testdata) - 1;
20 const bool testbool1 = false;
21 const bool testbool2 = true;
22 const uint16 testuint16 = 32123;
23 const float testfloat = 3.1415926935f;
24
25 // checks that the result
26 void VerifyResult(const Pickle& pickle) {
27   PickleIterator iter(pickle);
28
29   int outint;
30   EXPECT_TRUE(pickle.ReadInt(&iter, &outint));
31   EXPECT_EQ(testint, outint);
32
33   std::string outstr;
34   EXPECT_TRUE(pickle.ReadString(&iter, &outstr));
35   EXPECT_EQ(teststr, outstr);
36
37   std::wstring outwstr;
38   EXPECT_TRUE(pickle.ReadWString(&iter, &outwstr));
39   EXPECT_EQ(testwstr, outwstr);
40
41   bool outbool;
42   EXPECT_TRUE(pickle.ReadBool(&iter, &outbool));
43   EXPECT_FALSE(outbool);
44   EXPECT_TRUE(pickle.ReadBool(&iter, &outbool));
45   EXPECT_TRUE(outbool);
46
47   uint16 outuint16;
48   EXPECT_TRUE(pickle.ReadUInt16(&iter, &outuint16));
49   EXPECT_EQ(testuint16, outuint16);
50
51   float outfloat;
52   EXPECT_TRUE(pickle.ReadFloat(&iter, &outfloat));
53   EXPECT_EQ(testfloat, outfloat);
54
55   const char* outdata;
56   int outdatalen;
57   EXPECT_TRUE(pickle.ReadData(&iter, &outdata, &outdatalen));
58   EXPECT_EQ(testdatalen, outdatalen);
59   EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0);
60
61   // reads past the end should fail
62   EXPECT_FALSE(pickle.ReadInt(&iter, &outint));
63 }
64
65 }  // namespace
66
67 TEST(PickleTest, EncodeDecode) {
68   Pickle pickle;
69
70   EXPECT_TRUE(pickle.WriteInt(testint));
71   EXPECT_TRUE(pickle.WriteString(teststr));
72   EXPECT_TRUE(pickle.WriteWString(testwstr));
73   EXPECT_TRUE(pickle.WriteBool(testbool1));
74   EXPECT_TRUE(pickle.WriteBool(testbool2));
75   EXPECT_TRUE(pickle.WriteUInt16(testuint16));
76   EXPECT_TRUE(pickle.WriteFloat(testfloat));
77   EXPECT_TRUE(pickle.WriteData(testdata, testdatalen));
78   VerifyResult(pickle);
79
80   // test copy constructor
81   Pickle pickle2(pickle);
82   VerifyResult(pickle2);
83
84   // test operator=
85   Pickle pickle3;
86   pickle3 = pickle;
87   VerifyResult(pickle3);
88 }
89
90 // Tests that we can handle really small buffers.
91 TEST(PickleTest, SmallBuffer) {
92   scoped_ptr<char[]> buffer(new char[1]);
93
94   // We should not touch the buffer.
95   Pickle pickle(buffer.get(), 1);
96
97   PickleIterator iter(pickle);
98   int data;
99   EXPECT_FALSE(pickle.ReadInt(&iter, &data));
100 }
101
102 // Tests that we can handle improper headers.
103 TEST(PickleTest, BigSize) {
104   int buffer[] = { 0x56035200, 25, 40, 50 };
105
106   Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
107
108   PickleIterator iter(pickle);
109   int data;
110   EXPECT_FALSE(pickle.ReadInt(&iter, &data));
111 }
112
113 TEST(PickleTest, UnalignedSize) {
114   int buffer[] = { 10, 25, 40, 50 };
115
116   Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
117
118   PickleIterator iter(pickle);
119   int data;
120   EXPECT_FALSE(pickle.ReadInt(&iter, &data));
121 }
122
123 TEST(PickleTest, ZeroLenStr) {
124   Pickle pickle;
125   EXPECT_TRUE(pickle.WriteString(std::string()));
126
127   PickleIterator iter(pickle);
128   std::string outstr;
129   EXPECT_TRUE(pickle.ReadString(&iter, &outstr));
130   EXPECT_EQ("", outstr);
131 }
132
133 TEST(PickleTest, ZeroLenWStr) {
134   Pickle pickle;
135   EXPECT_TRUE(pickle.WriteWString(std::wstring()));
136
137   PickleIterator iter(pickle);
138   std::string outstr;
139   EXPECT_TRUE(pickle.ReadString(&iter, &outstr));
140   EXPECT_EQ("", outstr);
141 }
142
143 TEST(PickleTest, BadLenStr) {
144   Pickle pickle;
145   EXPECT_TRUE(pickle.WriteInt(-2));
146
147   PickleIterator iter(pickle);
148   std::string outstr;
149   EXPECT_FALSE(pickle.ReadString(&iter, &outstr));
150 }
151
152 TEST(PickleTest, BadLenWStr) {
153   Pickle pickle;
154   EXPECT_TRUE(pickle.WriteInt(-1));
155
156   PickleIterator iter(pickle);
157   std::wstring woutstr;
158   EXPECT_FALSE(pickle.ReadWString(&iter, &woutstr));
159 }
160
161 TEST(PickleTest, FindNext) {
162   Pickle pickle;
163   EXPECT_TRUE(pickle.WriteInt(1));
164   EXPECT_TRUE(pickle.WriteString("Domo"));
165
166   const char* start = reinterpret_cast<const char*>(pickle.data());
167   const char* end = start + pickle.size();
168
169   EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end));
170   EXPECT_TRUE(NULL == Pickle::FindNext(pickle.header_size_, start, end - 1));
171   EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end + 1));
172 }
173
174 TEST(PickleTest, FindNextWithIncompleteHeader) {
175   size_t header_size = sizeof(Pickle::Header);
176   scoped_ptr<char[]> buffer(new char[header_size - 1]);
177   memset(buffer.get(), 0x1, header_size - 1);
178
179   const char* start = buffer.get();
180   const char* end = start + header_size - 1;
181
182   EXPECT_TRUE(NULL == Pickle::FindNext(header_size, start, end));
183 }
184
185 #if defined(COMPILER_MSVC)
186 #pragma warning(push)
187 #pragma warning(disable: 4146)
188 #endif
189 TEST(PickleTest, FindNextOverflow) {
190   size_t header_size = sizeof(Pickle::Header);
191   size_t header_size2 = 2 * header_size;
192   size_t payload_received = 100;
193   scoped_ptr<char[]> buffer(new char[header_size2 + payload_received]);
194   const char* start = buffer.get();
195   Pickle::Header* header = reinterpret_cast<Pickle::Header*>(buffer.get());
196   const char* end = start + header_size2 + payload_received;
197   // It is impossible to construct an overflow test otherwise.
198   if (sizeof(size_t) > sizeof(header->payload_size) ||
199       sizeof(uintptr_t) > sizeof(header->payload_size))
200     return;
201
202   header->payload_size = -(reinterpret_cast<uintptr_t>(start) + header_size2);
203   EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));
204
205   header->payload_size = -header_size2;
206   EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));
207
208   header->payload_size = 0;
209   end = start + header_size;
210   EXPECT_TRUE(NULL == Pickle::FindNext(header_size2, start, end));
211 }
212 #if defined(COMPILER_MSVC)
213 #pragma warning(pop)
214 #endif
215
216 TEST(PickleTest, GetReadPointerAndAdvance) {
217   Pickle pickle;
218
219   PickleIterator iter(pickle);
220   EXPECT_FALSE(iter.GetReadPointerAndAdvance(1));
221
222   EXPECT_TRUE(pickle.WriteInt(1));
223   EXPECT_TRUE(pickle.WriteInt(2));
224   int bytes = sizeof(int) * 2;
225
226   EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(0));
227   EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(1));
228   EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(-1));
229   EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes));
230   EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes + 1));
231   EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MAX));
232   EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MIN));
233 }
234
235 TEST(PickleTest, Resize) {
236   size_t unit = Pickle::kPayloadUnit;
237   scoped_ptr<char[]> data(new char[unit]);
238   char* data_ptr = data.get();
239   for (size_t i = 0; i < unit; i++)
240     data_ptr[i] = 'G';
241
242   // construct a message that will be exactly the size of one payload unit,
243   // note that any data will have a 4-byte header indicating the size
244   const size_t payload_size_after_header = unit - sizeof(uint32);
245   Pickle pickle;
246   pickle.WriteData(data_ptr,
247       static_cast<int>(payload_size_after_header - sizeof(uint32)));
248   size_t cur_payload = payload_size_after_header;
249
250   // note: we assume 'unit' is a power of 2
251   EXPECT_EQ(unit, pickle.capacity_after_header());
252   EXPECT_EQ(pickle.payload_size(), payload_size_after_header);
253
254   // fill out a full page (noting data header)
255   pickle.WriteData(data_ptr, static_cast<int>(unit - sizeof(uint32)));
256   cur_payload += unit;
257   EXPECT_EQ(unit * 2, pickle.capacity_after_header());
258   EXPECT_EQ(cur_payload, pickle.payload_size());
259
260   // one more byte should double the capacity
261   pickle.WriteData(data_ptr, 1);
262   cur_payload += 5;
263   EXPECT_EQ(unit * 4, pickle.capacity_after_header());
264   EXPECT_EQ(cur_payload, pickle.payload_size());
265 }
266
267 namespace {
268
269 struct CustomHeader : Pickle::Header {
270   int blah;
271 };
272
273 }  // namespace
274
275 TEST(PickleTest, HeaderPadding) {
276   const uint32 kMagic = 0x12345678;
277
278   Pickle pickle(sizeof(CustomHeader));
279   pickle.WriteInt(kMagic);
280
281   // this should not overwrite the 'int' payload
282   pickle.headerT<CustomHeader>()->blah = 10;
283
284   PickleIterator iter(pickle);
285   int result;
286   ASSERT_TRUE(pickle.ReadInt(&iter, &result));
287
288   EXPECT_EQ(static_cast<uint32>(result), kMagic);
289 }
290
291 TEST(PickleTest, EqualsOperator) {
292   Pickle source;
293   source.WriteInt(1);
294
295   Pickle copy_refs_source_buffer(static_cast<const char*>(source.data()),
296                                  source.size());
297   Pickle copy;
298   copy = copy_refs_source_buffer;
299   ASSERT_EQ(source.size(), copy.size());
300 }
301
302 TEST(PickleTest, EvilLengths) {
303   Pickle source;
304   std::string str(100000, 'A');
305   EXPECT_TRUE(source.WriteData(str.c_str(), 100000));
306   // ReadString16 used to have its read buffer length calculation wrong leading
307   // to out-of-bounds reading.
308   PickleIterator iter(source);
309   string16 str16;
310   EXPECT_FALSE(source.ReadString16(&iter, &str16));
311
312   // And check we didn't break ReadString16.
313   str16 = (wchar_t) 'A';
314   Pickle str16_pickle;
315   EXPECT_TRUE(str16_pickle.WriteString16(str16));
316   iter = PickleIterator(str16_pickle);
317   EXPECT_TRUE(str16_pickle.ReadString16(&iter, &str16));
318   EXPECT_EQ(1U, str16.length());
319
320   // Check we don't fail in a length check with invalid String16 size.
321   // (1<<31) * sizeof(char16) == 0, so this is particularly evil.
322   Pickle bad_len;
323   EXPECT_TRUE(bad_len.WriteInt(1 << 31));
324   iter = PickleIterator(bad_len);
325   EXPECT_FALSE(bad_len.ReadString16(&iter, &str16));
326
327   // Check we don't fail in a length check with large WStrings.
328   Pickle big_len;
329   EXPECT_TRUE(big_len.WriteInt(1 << 30));
330   iter = PickleIterator(big_len);
331   std::wstring wstr;
332   EXPECT_FALSE(big_len.ReadWString(&iter, &wstr));
333 }
334
335 // Check we can write zero bytes of data and 'data' can be NULL.
336 TEST(PickleTest, ZeroLength) {
337   Pickle pickle;
338   EXPECT_TRUE(pickle.WriteData(NULL, 0));
339
340   PickleIterator iter(pickle);
341   const char* outdata;
342   int outdatalen;
343   EXPECT_TRUE(pickle.ReadData(&iter, &outdata, &outdatalen));
344   EXPECT_EQ(0, outdatalen);
345   // We can't assert that outdata is NULL.
346 }
347
348 // Check that ReadBytes works properly with an iterator initialized to NULL.
349 TEST(PickleTest, ReadBytes) {
350   Pickle pickle;
351   int data = 0x7abcd;
352   EXPECT_TRUE(pickle.WriteBytes(&data, sizeof(data)));
353
354   PickleIterator iter(pickle);
355   const char* outdata_char = NULL;
356   EXPECT_TRUE(pickle.ReadBytes(&iter, &outdata_char, sizeof(data)));
357
358   int outdata;
359   memcpy(&outdata, outdata_char, sizeof(outdata));
360   EXPECT_EQ(data, outdata);
361 }