pickle_unittest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2006-2008 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/pickle.h"
9#include "base/scoped_ptr.h"
10#include "base/string16.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace {
14
15const int testint = 2093847192;
16const std::string teststr("Hello world");  // note non-aligned string length
17const std::wstring testwstr(L"Hello, world");
18const char testdata[] = "AAA\0BBB\0";
19const int testdatalen = arraysize(testdata) - 1;
20const bool testbool1 = false;
21const bool testbool2 = true;
22const uint16 testuint16 = 32123;
23
24// checks that the result
25void 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
66TEST(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.
97TEST(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.
109TEST(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
119TEST(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
129TEST(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
139TEST(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
149TEST(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
158TEST(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
167TEST(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
180TEST(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
191TEST(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
206TEST(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
238namespace {
239
240struct CustomHeader : Pickle::Header {
241  int blah;
242};
243
244}  // namespace
245
246TEST(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
262TEST(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
273TEST(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.
300TEST(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.
313TEST(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