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