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