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