Home | History | Annotate | Download | only in base
      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
     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 
     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.
     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.
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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.
    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.
    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