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