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 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 23 // checks that the result 24 void VerifyResult(const Pickle& pickle) { 25 void* iter = NULL; 26 27 int outint; 28 EXPECT_TRUE(pickle.ReadInt(&iter, &outint)); 29 EXPECT_EQ(testint, outint); 30 31 std::string outstr; 32 EXPECT_TRUE(pickle.ReadString(&iter, &outstr)); 33 EXPECT_EQ(teststr, outstr); 34 35 std::wstring outwstr; 36 EXPECT_TRUE(pickle.ReadWString(&iter, &outwstr)); 37 EXPECT_EQ(testwstr, outwstr); 38 39 bool outbool; 40 EXPECT_TRUE(pickle.ReadBool(&iter, &outbool)); 41 EXPECT_EQ(testbool1, outbool); 42 EXPECT_TRUE(pickle.ReadBool(&iter, &outbool)); 43 EXPECT_EQ(testbool2, outbool); 44 45 const char* outdata; 46 int outdatalen; 47 EXPECT_TRUE(pickle.ReadData(&iter, &outdata, &outdatalen)); 48 EXPECT_EQ(testdatalen, outdatalen); 49 EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0); 50 51 EXPECT_TRUE(pickle.ReadData(&iter, &outdata, &outdatalen)); 52 EXPECT_EQ(testdatalen, outdatalen); 53 EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0); 54 55 // reads past the end should fail 56 EXPECT_FALSE(pickle.ReadInt(&iter, &outint)); 57 } 58 59 } // namespace 60 61 TEST(PickleTest, EncodeDecode) { 62 Pickle pickle; 63 64 EXPECT_TRUE(pickle.WriteInt(testint)); 65 EXPECT_TRUE(pickle.WriteString(teststr)); 66 EXPECT_TRUE(pickle.WriteWString(testwstr)); 67 EXPECT_TRUE(pickle.WriteBool(testbool1)); 68 EXPECT_TRUE(pickle.WriteBool(testbool2)); 69 EXPECT_TRUE(pickle.WriteData(testdata, testdatalen)); 70 71 // Over allocate BeginWriteData so we can test TrimWriteData. 72 char* dest = pickle.BeginWriteData(testdatalen + 100); 73 EXPECT_TRUE(dest); 74 memcpy(dest, testdata, testdatalen); 75 76 pickle.TrimWriteData(testdatalen); 77 78 VerifyResult(pickle); 79 80 // test copy constructor 81 Pickle pickle2(pickle); 82 VerifyResult(pickle2); 83 84 // test operator= 85 Pickle pickle3; 86 pickle3 = pickle; 87 VerifyResult(pickle3); 88 } 89 90 TEST(PickleTest, ZeroLenStr) { 91 Pickle pickle; 92 EXPECT_TRUE(pickle.WriteString("")); 93 94 void* iter = NULL; 95 std::string outstr; 96 EXPECT_TRUE(pickle.ReadString(&iter, &outstr)); 97 EXPECT_EQ("", outstr); 98 } 99 100 TEST(PickleTest, ZeroLenWStr) { 101 Pickle pickle; 102 EXPECT_TRUE(pickle.WriteWString(L"")); 103 104 void* iter = NULL; 105 std::string outstr; 106 EXPECT_TRUE(pickle.ReadString(&iter, &outstr)); 107 EXPECT_EQ("", outstr); 108 } 109 110 TEST(PickleTest, BadLenStr) { 111 Pickle pickle; 112 EXPECT_TRUE(pickle.WriteInt(-2)); 113 114 void* iter = NULL; 115 std::string outstr; 116 EXPECT_FALSE(pickle.ReadString(&iter, &outstr)); 117 } 118 119 TEST(PickleTest, BadLenWStr) { 120 Pickle pickle; 121 EXPECT_TRUE(pickle.WriteInt(-1)); 122 123 void* iter = NULL; 124 std::wstring woutstr; 125 EXPECT_FALSE(pickle.ReadWString(&iter, &woutstr)); 126 } 127 128 TEST(PickleTest, FindNext) { 129 Pickle pickle; 130 EXPECT_TRUE(pickle.WriteInt(1)); 131 EXPECT_TRUE(pickle.WriteString("Domo")); 132 133 const char* start = reinterpret_cast<const char*>(pickle.data()); 134 const char* end = start + pickle.size(); 135 136 EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end)); 137 EXPECT_TRUE(NULL == Pickle::FindNext(pickle.header_size_, start, end - 1)); 138 EXPECT_TRUE(end == Pickle::FindNext(pickle.header_size_, start, end + 1)); 139 } 140 141 TEST(PickleTest, IteratorHasRoom) { 142 Pickle pickle; 143 EXPECT_TRUE(pickle.WriteInt(1)); 144 EXPECT_TRUE(pickle.WriteInt(2)); 145 146 const void* iter = 0; 147 EXPECT_FALSE(pickle.IteratorHasRoomFor(iter, 1)); 148 iter = pickle.payload(); 149 EXPECT_TRUE(pickle.IteratorHasRoomFor(iter, 0)); 150 EXPECT_TRUE(pickle.IteratorHasRoomFor(iter, 1)); 151 EXPECT_FALSE(pickle.IteratorHasRoomFor(iter, -1)); 152 EXPECT_TRUE(pickle.IteratorHasRoomFor(iter, sizeof(int) * 2)); 153 EXPECT_FALSE(pickle.IteratorHasRoomFor(iter, (sizeof(int) * 2) + 1)); 154 } 155 156 TEST(PickleTest, Resize) { 157 size_t unit = Pickle::kPayloadUnit; 158 scoped_array<char> data(new char[unit]); 159 char* data_ptr = data.get(); 160 for (size_t i = 0; i < unit; i++) 161 data_ptr[i] = 'G'; 162 163 // construct a message that will be exactly the size of one payload unit, 164 // note that any data will have a 4-byte header indicating the size 165 const size_t payload_size_after_header = unit - sizeof(uint32); 166 Pickle pickle; 167 pickle.WriteData(data_ptr, 168 static_cast<int>(payload_size_after_header - sizeof(uint32))); 169 size_t cur_payload = payload_size_after_header; 170 171 // note: we assume 'unit' is a power of 2 172 EXPECT_EQ(unit, pickle.capacity()); 173 EXPECT_EQ(pickle.payload_size(), payload_size_after_header); 174 175 // fill out a full page (noting data header) 176 pickle.WriteData(data_ptr, static_cast<int>(unit - sizeof(uint32))); 177 cur_payload += unit; 178 EXPECT_EQ(unit * 2, pickle.capacity()); 179 EXPECT_EQ(cur_payload, pickle.payload_size()); 180 181 // one more byte should double the capacity 182 pickle.WriteData(data_ptr, 1); 183 cur_payload += 5; 184 EXPECT_EQ(unit * 4, pickle.capacity()); 185 EXPECT_EQ(cur_payload, pickle.payload_size()); 186 } 187 188 namespace { 189 190 struct CustomHeader : Pickle::Header { 191 int blah; 192 }; 193 194 } // namespace 195 196 TEST(PickleTest, HeaderPadding) { 197 const uint32 kMagic = 0x12345678; 198 199 Pickle pickle(sizeof(CustomHeader)); 200 pickle.WriteInt(kMagic); 201 202 // this should not overwrite the 'int' payload 203 pickle.headerT<CustomHeader>()->blah = 10; 204 205 void* iter = NULL; 206 int result; 207 ASSERT_TRUE(pickle.ReadInt(&iter, &result)); 208 209 EXPECT_EQ(static_cast<uint32>(result), kMagic); 210 } 211 212 TEST(PickleTest, EqualsOperator) { 213 Pickle source; 214 source.WriteInt(1); 215 216 Pickle copy_refs_source_buffer(static_cast<const char*>(source.data()), 217 source.size()); 218 Pickle copy; 219 copy = copy_refs_source_buffer; 220 ASSERT_EQ(source.size(), copy.size()); 221 } 222 223 TEST(PickleTest, EvilLengths) { 224 Pickle source; 225 std::string str(100000, 'A'); 226 source.WriteData(str.c_str(), 100000); 227 // ReadString16 used to have its read buffer length calculation wrong leading 228 // to out-of-bounds reading. 229 void* iter = NULL; 230 string16 str16; 231 EXPECT_FALSE(source.ReadString16(&iter, &str16)); 232 233 // And check we didn't break ReadString16. 234 str16 = (wchar_t) 'A'; 235 Pickle str16_pickle; 236 str16_pickle.WriteString16(str16); 237 iter = NULL; 238 EXPECT_TRUE(str16_pickle.ReadString16(&iter, &str16)); 239 EXPECT_EQ(1U, str16.length()); 240 241 // Check we don't fail in a length check with large WStrings. 242 Pickle big_len; 243 big_len.WriteInt(1 << 30); 244 iter = NULL; 245 std::wstring wstr; 246 EXPECT_FALSE(big_len.ReadWString(&iter, &wstr)); 247 } 248 249 // Check we can write zero bytes of data and 'data' can be NULL. 250 TEST(PickleTest, ZeroLength) { 251 Pickle pickle; 252 EXPECT_TRUE(pickle.WriteData(NULL, 0)); 253 254 void* iter = NULL; 255 const char* outdata; 256 int outdatalen; 257 EXPECT_TRUE(pickle.ReadData(&iter, &outdata, &outdatalen)); 258 EXPECT_EQ(0, outdatalen); 259 // We can't assert that outdata is NULL. 260 } 261 262