| OLD | NEW |
| (Empty) |
| 1 // Copyright 2008 Google Inc. | |
| 2 // Author: Lincoln Smith | |
| 3 // | |
| 4 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 5 // you may not use this file except in compliance with the License. | |
| 6 // You may obtain a copy of the License at | |
| 7 // | |
| 8 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 9 // | |
| 10 // Unless required by applicable law or agreed to in writing, software | |
| 11 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 // See the License for the specific language governing permissions and | |
| 14 // limitations under the License. | |
| 15 | |
| 16 #include <config.h> | |
| 17 #include "google/vcdecoder.h" | |
| 18 #include <cstdlib> // free, posix_memalign | |
| 19 #include <cstring> // memcpy | |
| 20 #include <string> | |
| 21 #include "checksum.h" | |
| 22 #include "codetable.h" | |
| 23 #include "testing.h" | |
| 24 #include "varint_bigendian.h" | |
| 25 #include "vcdiff_defs.h" | |
| 26 | |
| 27 #ifdef HAVE_MALLOC_H | |
| 28 #include <malloc.h> | |
| 29 #endif // HAVE_MALLOC_H | |
| 30 | |
| 31 #ifdef HAVE_SYS_MMAN_H | |
| 32 #define _XOPEN_SOURCE 600 // posix_memalign | |
| 33 #include <sys/mman.h> // mprotect | |
| 34 #endif // HAVE_SYS_MMAN_H | |
| 35 | |
| 36 #ifdef HAVE_UNISTD_H | |
| 37 #include <unistd.h> // getpagesize | |
| 38 #endif // HAVE_UNISTD_H | |
| 39 | |
| 40 namespace open_vcdiff { | |
| 41 namespace { | |
| 42 | |
| 43 using std::string; | |
| 44 | |
| 45 // A base class used for all the decoder tests. Most tests use the same | |
| 46 // dictionary and target and construct the delta file in the same way. | |
| 47 // Those elements are provided as string members and can be modified or | |
| 48 // overwritten by each specific decoder test as needed. | |
| 49 class VCDiffDecoderTest : public testing::Test { | |
| 50 protected: | |
| 51 static const char kStandardFileHeader[]; | |
| 52 static const char kInterleavedFileHeader[]; | |
| 53 static const char kDictionary[]; | |
| 54 static const char kExpectedTarget[]; | |
| 55 static const char kExpectedAnnotatedTarget[]; | |
| 56 | |
| 57 VCDiffDecoderTest(); | |
| 58 | |
| 59 virtual ~VCDiffDecoderTest() {} | |
| 60 | |
| 61 virtual void SetUp(); | |
| 62 | |
| 63 // This function is called by SetUp(). It populates delta_file_ with the | |
| 64 // concatenated delta file header, delta window header, and delta window | |
| 65 // body, plus (if UseChecksum() is true) the corresponding checksum. | |
| 66 // It can be called again by a test that has modified the contents of | |
| 67 // delta_file_ and needs to restore them to their original state. | |
| 68 virtual void InitializeDeltaFile(); | |
| 69 | |
| 70 // This function adds an Adler32 checksum to the delta window header. | |
| 71 void AddChecksum(VCDChecksum checksum); | |
| 72 | |
| 73 // This function computes the Adler32 checksum for the expected target | |
| 74 // and adds it to the delta window header. | |
| 75 void ComputeAndAddChecksum(); | |
| 76 | |
| 77 // Write the maximum expressible positive 32-bit VarintBE | |
| 78 // (0x7FFFFFFF) at the given offset in the delta window. | |
| 79 void WriteMaxVarintAtOffset(int offset, int bytes_to_replace); | |
| 80 | |
| 81 // Write a negative 32-bit VarintBE (0x80000000) at the given offset | |
| 82 // in the delta window. | |
| 83 void WriteNegativeVarintAtOffset(int offset, int bytes_to_replace); | |
| 84 | |
| 85 // Write a VarintBE that has too many continuation bytes | |
| 86 // at the given offset in the delta window. | |
| 87 void WriteInvalidVarintAtOffset(int offset, int bytes_to_replace); | |
| 88 | |
| 89 // This function iterates through a list of fuzzers (bit masks used to corrupt | |
| 90 // bytes) and through positions in the delta file. Each time it is called, it | |
| 91 // attempts to corrupt a different byte in delta_file_ in a different way. If | |
| 92 // successful, it returns true. Once it exhausts the list of fuzzers and of | |
| 93 // byte positions in delta_file_, it returns false. | |
| 94 bool FuzzOneByteInDeltaFile(); | |
| 95 | |
| 96 // Assuming the length of the given string can be expressed as a VarintBE | |
| 97 // of length N, this function returns the byte at position which_byte, where | |
| 98 // 0 <= which_byte < N. | |
| 99 static char GetByteFromStringLength(const char* s, int which_byte) { | |
| 100 char varint_buf[VarintBE<int32_t>::kMaxBytes]; | |
| 101 VarintBE<int32_t>::Encode(static_cast<int32_t>(strlen(s)), varint_buf); | |
| 102 return varint_buf[which_byte]; | |
| 103 } | |
| 104 | |
| 105 // Assuming the length of the given string can be expressed as a one-byte | |
| 106 // VarintBE, this function returns that byte value. | |
| 107 static char StringLengthAsByte(const char* s) { | |
| 108 return GetByteFromStringLength(s, 0); | |
| 109 } | |
| 110 | |
| 111 // Assuming the length of the given string can be expressed as a two-byte | |
| 112 // VarintBE, this function returns the first byte of its representation. | |
| 113 static char FirstByteOfStringLength(const char* s) { | |
| 114 return GetByteFromStringLength(s, 0); | |
| 115 } | |
| 116 | |
| 117 // Assuming the length of the given string can be expressed as a two-byte | |
| 118 // VarintBE, this function returns the second byte of its representation. | |
| 119 static char SecondByteOfStringLength(const char* s) { | |
| 120 return GetByteFromStringLength(s, 1); | |
| 121 } | |
| 122 | |
| 123 VCDiffStreamingDecoder decoder_; | |
| 124 | |
| 125 // delta_file_ will be populated by InitializeDeltaFile() using the components | |
| 126 // delta_file_header_, delta_window_header_, and delta_window_body_. | |
| 127 string delta_file_; | |
| 128 | |
| 129 // This string is not populated during setup, but is used to receive the | |
| 130 // decoded target file in each test. | |
| 131 string output_; | |
| 132 | |
| 133 // Test fixtures that inherit from VCDiffDecoderTest can set these strings in | |
| 134 // their constructors to override their default values (which come from | |
| 135 // kDictionary, kExpectedTarget, etc.) | |
| 136 string dictionary_; | |
| 137 string expected_target_; | |
| 138 string expected_annotated_target_; | |
| 139 | |
| 140 // The components that will be used to construct delta_file_. | |
| 141 string delta_file_header_; | |
| 142 string delta_window_header_; | |
| 143 string delta_window_body_; | |
| 144 | |
| 145 private: | |
| 146 // These two counters are used by FuzzOneByteInDeltaFile() to iterate through | |
| 147 // different ways to corrupt the delta file. | |
| 148 size_t fuzzer_; | |
| 149 size_t fuzzed_byte_position_; | |
| 150 }; | |
| 151 | |
| 152 const char VCDiffDecoderTest::kStandardFileHeader[] = { | |
| 153 0xD6, // 'V' | 0x80 | |
| 154 0xC3, // 'C' | 0x80 | |
| 155 0xC4, // 'D' | 0x80 | |
| 156 0x00, // Draft standard version number | |
| 157 0x00 // Hdr_Indicator: no custom code table, no compression | |
| 158 }; | |
| 159 | |
| 160 const char VCDiffDecoderTest::kInterleavedFileHeader[] = { | |
| 161 0xD6, // 'V' | 0x80 | |
| 162 0xC3, // 'C' | 0x80 | |
| 163 0xC4, // 'D' | 0x80 | |
| 164 'S', // SDCH version code | |
| 165 0x00 // Hdr_Indicator: no custom code table, no compression | |
| 166 }; | |
| 167 | |
| 168 const char VCDiffDecoderTest::kDictionary[] = | |
| 169 "\"Just the place for a Snark!\" the Bellman cried,\n" | |
| 170 "As he landed his crew with care;\n" | |
| 171 "Supporting each man on the top of the tide\n" | |
| 172 "By a finger entwined in his hair.\n"; | |
| 173 | |
| 174 const char VCDiffDecoderTest::kExpectedTarget[] = | |
| 175 "\"Just the place for a Snark! I have said it twice:\n" | |
| 176 "That alone should encourage the crew.\n" | |
| 177 "Just the place for a Snark! I have said it thrice:\n" | |
| 178 "What I tell you three times is true.\"\n"; | |
| 179 | |
| 180 const char VCDiffDecoderTest::kExpectedAnnotatedTarget[] = | |
| 181 "<dmatch>\"Just the place for a Snark!</dmatch>" | |
| 182 "<literal> I have said it twice:\n" | |
| 183 "That alone should encourage the crew.\n</literal>" | |
| 184 "<bmatch>Just the place for a Snark! I have said it t</bmatch>" | |
| 185 "<literal>hr</literal>" | |
| 186 "<bmatch>ice:\n</bmatch>" | |
| 187 "<literal>What I te</literal>" | |
| 188 "<literal>ll</literal>" | |
| 189 "<literal> you three times is true.\"\n</literal>"; | |
| 190 | |
| 191 VCDiffDecoderTest::VCDiffDecoderTest() : fuzzer_(0), fuzzed_byte_position_(0) { | |
| 192 dictionary_ = kDictionary; | |
| 193 expected_target_ = kExpectedTarget; | |
| 194 expected_annotated_target_ = kExpectedAnnotatedTarget; | |
| 195 } | |
| 196 | |
| 197 void VCDiffDecoderTest::SetUp() { | |
| 198 InitializeDeltaFile(); | |
| 199 } | |
| 200 | |
| 201 void VCDiffDecoderTest::InitializeDeltaFile() { | |
| 202 delta_file_ = delta_file_header_ + delta_window_header_ + delta_window_body_; | |
| 203 } | |
| 204 | |
| 205 void VCDiffDecoderTest::AddChecksum(VCDChecksum checksum) { | |
| 206 int32_t checksum_as_int32 = static_cast<int32_t>(checksum); | |
| 207 delta_window_header_[0] |= VCD_CHECKSUM; | |
| 208 VarintBE<int32_t>::AppendToString(checksum_as_int32, &delta_window_header_); | |
| 209 // Adjust delta window size to include checksum. | |
| 210 // This method wouldn't work if adding to the length caused the VarintBE | |
| 211 // value to spill over into another byte. Luckily, this test data happens | |
| 212 // not to cause such an overflow. | |
| 213 delta_window_header_[4] += VarintBE<int32_t>::Length(checksum_as_int32); | |
| 214 } | |
| 215 | |
| 216 void VCDiffDecoderTest::ComputeAndAddChecksum() { | |
| 217 AddChecksum(ComputeAdler32(expected_target_.data(), | |
| 218 expected_target_.size())); | |
| 219 } | |
| 220 | |
| 221 // Write the maximum expressible positive 32-bit VarintBE | |
| 222 // (0x7FFFFFFF) at the given offset in the delta window. | |
| 223 void VCDiffDecoderTest::WriteMaxVarintAtOffset(int offset, | |
| 224 int bytes_to_replace) { | |
| 225 static const char kMaxVarint[] = { 0x87, 0xFF, 0xFF, 0xFF, 0x7F }; | |
| 226 delta_file_.replace(delta_file_header_.size() + offset, | |
| 227 bytes_to_replace, | |
| 228 kMaxVarint, | |
| 229 sizeof(kMaxVarint)); | |
| 230 } | |
| 231 | |
| 232 // Write a negative 32-bit VarintBE (0x80000000) at the given offset | |
| 233 // in the delta window. | |
| 234 void VCDiffDecoderTest::WriteNegativeVarintAtOffset(int offset, | |
| 235 int bytes_to_replace) { | |
| 236 static const char kNegativeVarint[] = { 0x88, 0x80, 0x80, 0x80, 0x00 }; | |
| 237 delta_file_.replace(delta_file_header_.size() + offset, | |
| 238 bytes_to_replace, | |
| 239 kNegativeVarint, | |
| 240 sizeof(kNegativeVarint)); | |
| 241 } | |
| 242 | |
| 243 // Write a VarintBE that has too many continuation bytes | |
| 244 // at the given offset in the delta window. | |
| 245 void VCDiffDecoderTest::WriteInvalidVarintAtOffset(int offset, | |
| 246 int bytes_to_replace) { | |
| 247 static const char kInvalidVarint[] = { 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F }; | |
| 248 delta_file_.replace(delta_file_header_.size() + offset, | |
| 249 bytes_to_replace, | |
| 250 kInvalidVarint, | |
| 251 sizeof(kInvalidVarint)); | |
| 252 } | |
| 253 | |
| 254 bool VCDiffDecoderTest::FuzzOneByteInDeltaFile() { | |
| 255 static const struct Fuzzer { | |
| 256 char _and; | |
| 257 char _or; | |
| 258 char _xor; | |
| 259 } fuzzers[] = { | |
| 260 { 0xff, 0x80, 0x00 }, | |
| 261 { 0xff, 0xff, 0x00 }, | |
| 262 { 0xff, 0x00, 0x80 }, | |
| 263 { 0xff, 0x00, 0xff }, | |
| 264 { 0xff, 0x01, 0x00 }, | |
| 265 { 0x7f, 0x00, 0x00 }, | |
| 266 }; | |
| 267 | |
| 268 for (; fuzzer_ < (sizeof(fuzzers) / sizeof(fuzzers[0])); ++fuzzer_) { | |
| 269 for (; fuzzed_byte_position_ < delta_file_.size(); | |
| 270 ++fuzzed_byte_position_) { | |
| 271 char fuzzed_byte = (((delta_file_[fuzzed_byte_position_] | |
| 272 & fuzzers[fuzzer_]._and) | |
| 273 | fuzzers[fuzzer_]._or) | |
| 274 ^ fuzzers[fuzzer_]._xor); | |
| 275 if (fuzzed_byte != delta_file_[fuzzed_byte_position_]) { | |
| 276 delta_file_[fuzzed_byte_position_] = fuzzed_byte; | |
| 277 ++fuzzed_byte_position_; | |
| 278 return true; | |
| 279 } | |
| 280 } | |
| 281 fuzzed_byte_position_ = 0; | |
| 282 } | |
| 283 return false; | |
| 284 } | |
| 285 | |
| 286 // The "standard" decoder test, which decodes a delta file that uses the | |
| 287 // standard VCDIFF (RFC 3284) format with no extensions. | |
| 288 class VCDiffStandardDecoderTest : public VCDiffDecoderTest { | |
| 289 protected: | |
| 290 VCDiffStandardDecoderTest(); | |
| 291 virtual ~VCDiffStandardDecoderTest() {} | |
| 292 | |
| 293 private: | |
| 294 static const char kWindowHeader[]; | |
| 295 static const char kWindowBody[]; | |
| 296 }; | |
| 297 | |
| 298 const char VCDiffStandardDecoderTest::kWindowHeader[] = { | |
| 299 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
| 300 FirstByteOfStringLength(kDictionary), // Source segment size | |
| 301 SecondByteOfStringLength(kDictionary), | |
| 302 0x00, // Source segment position: start of dictionary | |
| 303 0x79, // Length of the delta encoding | |
| 304 FirstByteOfStringLength(kExpectedTarget), // Size of the target window | |
| 305 SecondByteOfStringLength(kExpectedTarget), | |
| 306 0x00, // Delta_indicator (no compression) | |
| 307 0x64, // length of data for ADDs and RUNs | |
| 308 0x0C, // length of instructions section | |
| 309 0x03 // length of addresses for COPYs | |
| 310 }; | |
| 311 | |
| 312 const char VCDiffStandardDecoderTest::kWindowBody[] = { | |
| 313 // Data for ADDs: 1st section (length 61) | |
| 314 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', | |
| 315 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', | |
| 316 'T', 'h', 'a', 't', ' ', | |
| 317 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', | |
| 318 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', | |
| 319 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', | |
| 320 // Data for ADDs: 2nd section (length 2) | |
| 321 'h', 'r', | |
| 322 // Data for ADDs: 3rd section (length 9) | |
| 323 'W', 'h', 'a', 't', ' ', | |
| 324 'I', ' ', 't', 'e', | |
| 325 // Data for RUN: 4th section (length 1) | |
| 326 'l', | |
| 327 // Data for ADD: 4th section (length 27) | |
| 328 ' ', 'y', 'o', 'u', ' ', | |
| 329 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', | |
| 330 't', 'r', 'u', 'e', '.', '\"', '\n', | |
| 331 // Instructions and sizes (length 13) | |
| 332 0x13, // VCD_COPY mode VCD_SELF, size 0 | |
| 333 0x1C, // Size of COPY (28) | |
| 334 0x01, // VCD_ADD size 0 | |
| 335 0x3D, // Size of ADD (61) | |
| 336 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
| 337 0x2C, // Size of COPY (44) | |
| 338 0xCB, // VCD_ADD size 2 + VCD_COPY mode NEAR(1), size 5 | |
| 339 0x0A, // VCD_ADD size 9 | |
| 340 0x00, // VCD_RUN size 0 | |
| 341 0x02, // Size of RUN (2) | |
| 342 0x01, // VCD_ADD size 0 | |
| 343 0x1B, // Size of ADD (27) | |
| 344 // Addresses for COPYs (length 3) | |
| 345 0x00, // Start of dictionary | |
| 346 0x58, // HERE mode address for 2nd copy (27+61 back from here_address) | |
| 347 0x2D // NEAR(1) mode address for 2nd copy (45 after prior address) | |
| 348 }; | |
| 349 | |
| 350 VCDiffStandardDecoderTest::VCDiffStandardDecoderTest() { | |
| 351 delta_file_header_.assign(kStandardFileHeader, sizeof(kStandardFileHeader)); | |
| 352 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); | |
| 353 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
| 354 } | |
| 355 | |
| 356 TEST_F(VCDiffStandardDecoderTest, DecodeHeaderOnly) { | |
| 357 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 358 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), | |
| 359 delta_file_header_.size(), | |
| 360 &output_)); | |
| 361 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 362 EXPECT_EQ("", output_); | |
| 363 } | |
| 364 | |
| 365 TEST_F(VCDiffStandardDecoderTest, Decode) { | |
| 366 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 367 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 368 delta_file_.size(), | |
| 369 &output_)); | |
| 370 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 371 EXPECT_EQ(expected_target_, output_); | |
| 372 } | |
| 373 | |
| 374 // If we add a checksum to a standard-format delta file (without using format | |
| 375 // extensions), it will be interpreted as random bytes inserted into the middle | |
| 376 // of the file. The decode operation should fail, but where exactly it fails is | |
| 377 // not easy to predict. | |
| 378 TEST_F(VCDiffStandardDecoderTest, StandardFormatDoesNotSupportChecksum) { | |
| 379 ComputeAndAddChecksum(); | |
| 380 InitializeDeltaFile(); | |
| 381 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 382 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 383 delta_file_.size(), | |
| 384 &output_)); | |
| 385 EXPECT_EQ("", output_); | |
| 386 } | |
| 387 | |
| 388 // Remove one byte from the length of the chunk to process, and | |
| 389 // verify that an error is returned for FinishDecoding(). | |
| 390 TEST_F(VCDiffStandardDecoderTest, FinishAfterDecodingPartialWindow) { | |
| 391 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 392 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 393 delta_file_.size() - 1, | |
| 394 &output_)); | |
| 395 EXPECT_FALSE(decoder_.FinishDecoding()); | |
| 396 // The decoder should not create more target bytes than were expected. | |
| 397 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 398 } | |
| 399 | |
| 400 TEST_F(VCDiffStandardDecoderTest, FinishAfterDecodingPartialWindowHeader) { | |
| 401 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 402 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 403 delta_file_header_.size() | |
| 404 + delta_window_header_.size() - 1, | |
| 405 &output_)); | |
| 406 EXPECT_FALSE(decoder_.FinishDecoding()); | |
| 407 EXPECT_EQ("", output_); | |
| 408 } | |
| 409 | |
| 410 // Fuzz bits to make sure decoder does not violently crash. | |
| 411 // This test has no expected behavior except that no crashes should occur. | |
| 412 // In some cases, changing bits will still decode to the correct target; | |
| 413 // for example, changing unused bits within a bitfield. | |
| 414 TEST_F(VCDiffStandardDecoderTest, FuzzBits) { | |
| 415 while (FuzzOneByteInDeltaFile()) { | |
| 416 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 417 if (decoder_.DecodeChunk(delta_file_.data(), | |
| 418 delta_file_.size(), | |
| 419 &output_)) { | |
| 420 decoder_.FinishDecoding(); | |
| 421 } | |
| 422 InitializeDeltaFile(); | |
| 423 output_.clear(); | |
| 424 } | |
| 425 } | |
| 426 | |
| 427 TEST_F(VCDiffStandardDecoderTest, CheckAnnotatedOutput) { | |
| 428 decoder_.EnableAnnotatedOutput(); | |
| 429 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 430 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 431 delta_file_.size(), | |
| 432 &output_)); | |
| 433 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 434 string annotated_output; | |
| 435 decoder_.GetAnnotatedOutput(&annotated_output); | |
| 436 EXPECT_EQ(expected_annotated_target_, annotated_output); | |
| 437 } | |
| 438 | |
| 439 // Change each element of the delta file window to an erroneous value | |
| 440 // and make sure it's caught as an error. | |
| 441 | |
| 442 TEST_F(VCDiffStandardDecoderTest, WinIndicatorHasBothSourceAndTarget) { | |
| 443 delta_file_[delta_file_header_.size()] = VCD_SOURCE + VCD_TARGET; | |
| 444 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 445 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 446 delta_file_.size(), | |
| 447 &output_)); | |
| 448 EXPECT_EQ("", output_); | |
| 449 } | |
| 450 | |
| 451 TEST_F(VCDiffStandardDecoderTest, OkayToSetUpperBitsOfWinIndicator) { | |
| 452 // It is not an error to set any of the other bits in Win_Indicator | |
| 453 // besides VCD_SOURCE and VCD_TARGET. | |
| 454 delta_file_[delta_file_header_.size()] = 0xFD; | |
| 455 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 456 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 457 delta_file_.size(), | |
| 458 &output_)); | |
| 459 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 460 EXPECT_EQ(expected_target_, output_); | |
| 461 } | |
| 462 | |
| 463 TEST_F(VCDiffStandardDecoderTest, CopyInstructionsShouldFailIfNoSourceSegment) { | |
| 464 // Replace the Win_Indicator and the source size and source offset with a | |
| 465 // single 0 byte (a Win_Indicator for a window with no source segment.) | |
| 466 delta_window_header_.replace(0, 4, "\0", 1); | |
| 467 InitializeDeltaFile(); | |
| 468 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 469 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 470 delta_file_.size(), | |
| 471 &output_)); | |
| 472 // The first COPY instruction should fail, so there should be no output | |
| 473 EXPECT_EQ("", output_); | |
| 474 } | |
| 475 | |
| 476 TEST_F(VCDiffStandardDecoderTest, SourceSegmentSizeExceedsDictionarySize) { | |
| 477 ++delta_file_[delta_file_header_.size() + 2]; // increment size | |
| 478 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 479 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 480 delta_file_.size(), | |
| 481 &output_)); | |
| 482 EXPECT_EQ("", output_); | |
| 483 } | |
| 484 | |
| 485 TEST_F(VCDiffStandardDecoderTest, SourceSegmentSizeMaxInt) { | |
| 486 WriteMaxVarintAtOffset(1, 2); | |
| 487 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 488 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 489 delta_file_.size(), | |
| 490 &output_)); | |
| 491 EXPECT_EQ("", output_); | |
| 492 } | |
| 493 | |
| 494 TEST_F(VCDiffStandardDecoderTest, SourceSegmentSizeNegative) { | |
| 495 WriteNegativeVarintAtOffset(1, 2); | |
| 496 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 497 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 498 delta_file_.size(), | |
| 499 &output_)); | |
| 500 EXPECT_EQ("", output_); | |
| 501 } | |
| 502 | |
| 503 TEST_F(VCDiffStandardDecoderTest, SourceSegmentSizeInvalid) { | |
| 504 WriteInvalidVarintAtOffset(1, 2); | |
| 505 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 506 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 507 delta_file_.size(), | |
| 508 &output_)); | |
| 509 EXPECT_EQ("", output_); | |
| 510 } | |
| 511 | |
| 512 TEST_F(VCDiffStandardDecoderTest, SourceSegmentEndExceedsDictionarySize) { | |
| 513 ++delta_file_[delta_file_header_.size() + 3]; // increment start pos | |
| 514 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 515 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 516 delta_file_.size(), | |
| 517 &output_)); | |
| 518 EXPECT_EQ("", output_); | |
| 519 } | |
| 520 | |
| 521 TEST_F(VCDiffStandardDecoderTest, SourceSegmentPosMaxInt) { | |
| 522 WriteMaxVarintAtOffset(3, 1); | |
| 523 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 524 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 525 delta_file_.size(), | |
| 526 &output_)); | |
| 527 EXPECT_EQ("", output_); | |
| 528 } | |
| 529 | |
| 530 TEST_F(VCDiffStandardDecoderTest, SourceSegmentPosNegative) { | |
| 531 WriteNegativeVarintAtOffset(3, 1); | |
| 532 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 533 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 534 delta_file_.size(), | |
| 535 &output_)); | |
| 536 EXPECT_EQ("", output_); | |
| 537 } | |
| 538 | |
| 539 TEST_F(VCDiffStandardDecoderTest, SourceSegmentPosInvalid) { | |
| 540 WriteInvalidVarintAtOffset(3, 1); | |
| 541 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 542 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 543 delta_file_.size(), | |
| 544 &output_)); | |
| 545 EXPECT_EQ("", output_); | |
| 546 } | |
| 547 | |
| 548 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthZero) { | |
| 549 delta_file_[delta_file_header_.size() + 4] = 0; | |
| 550 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 551 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 552 delta_file_.size(), | |
| 553 &output_)); | |
| 554 EXPECT_EQ("", output_); | |
| 555 } | |
| 556 | |
| 557 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthTooLargeByOne) { | |
| 558 ++delta_file_[delta_file_header_.size() + 4]; | |
| 559 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 560 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 561 delta_file_.size(), | |
| 562 &output_)); | |
| 563 EXPECT_EQ("", output_); | |
| 564 } | |
| 565 | |
| 566 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthTooSmallByOne) { | |
| 567 --delta_file_[delta_file_header_.size() + 4]; | |
| 568 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 569 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 570 delta_file_.size(), | |
| 571 &output_)); | |
| 572 EXPECT_EQ("", output_); | |
| 573 } | |
| 574 | |
| 575 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthMaxInt) { | |
| 576 WriteMaxVarintAtOffset(4, 1); | |
| 577 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 578 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 579 delta_file_.size(), | |
| 580 &output_)); | |
| 581 EXPECT_EQ("", output_); | |
| 582 } | |
| 583 | |
| 584 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthNegative) { | |
| 585 WriteNegativeVarintAtOffset(4, 1); | |
| 586 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 587 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 588 delta_file_.size(), | |
| 589 &output_)); | |
| 590 EXPECT_EQ("", output_); | |
| 591 } | |
| 592 | |
| 593 TEST_F(VCDiffStandardDecoderTest, DeltaEncodingLengthInvalid) { | |
| 594 WriteInvalidVarintAtOffset(4, 1); | |
| 595 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 596 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 597 delta_file_.size(), | |
| 598 &output_)); | |
| 599 EXPECT_EQ("", output_); | |
| 600 } | |
| 601 | |
| 602 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeZero) { | |
| 603 static const char zero_size[] = { 0x00 }; | |
| 604 delta_file_.replace(delta_file_header_.size() + 5, 2, zero_size, 1); | |
| 605 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 606 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 607 delta_file_.size(), | |
| 608 &output_)); | |
| 609 EXPECT_EQ("", output_); | |
| 610 } | |
| 611 | |
| 612 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeTooLargeByOne) { | |
| 613 ++delta_file_[delta_file_header_.size() + 6]; | |
| 614 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 615 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 616 delta_file_.size(), | |
| 617 &output_)); | |
| 618 EXPECT_EQ("", output_); | |
| 619 } | |
| 620 | |
| 621 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeTooSmallByOne) { | |
| 622 --delta_file_[delta_file_header_.size() + 6]; | |
| 623 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 624 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 625 delta_file_.size(), | |
| 626 &output_)); | |
| 627 EXPECT_EQ("", output_); | |
| 628 } | |
| 629 | |
| 630 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeMaxInt) { | |
| 631 WriteMaxVarintAtOffset(5, 2); | |
| 632 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 633 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 634 delta_file_.size(), | |
| 635 &output_)); | |
| 636 EXPECT_EQ("", output_); | |
| 637 } | |
| 638 | |
| 639 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeNegative) { | |
| 640 WriteNegativeVarintAtOffset(5, 2); | |
| 641 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 642 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 643 delta_file_.size(), | |
| 644 &output_)); | |
| 645 EXPECT_EQ("", output_); | |
| 646 } | |
| 647 | |
| 648 TEST_F(VCDiffStandardDecoderTest, TargetWindowSizeInvalid) { | |
| 649 WriteInvalidVarintAtOffset(5, 2); | |
| 650 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 651 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 652 delta_file_.size(), | |
| 653 &output_)); | |
| 654 EXPECT_EQ("", output_); | |
| 655 } | |
| 656 | |
| 657 TEST_F(VCDiffStandardDecoderTest, OkayToSetUpperBitsOfDeltaIndicator) { | |
| 658 delta_file_[delta_file_header_.size() + 7] = 0xF8; | |
| 659 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 660 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 661 delta_file_.size(), | |
| 662 &output_)); | |
| 663 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 664 EXPECT_EQ(expected_target_, output_); | |
| 665 } | |
| 666 | |
| 667 TEST_F(VCDiffStandardDecoderTest, DataCompressionNotSupported) { | |
| 668 delta_file_[delta_file_header_.size() + 7] = 0x01; | |
| 669 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 670 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 671 delta_file_.size(), | |
| 672 &output_)); | |
| 673 EXPECT_EQ("", output_); | |
| 674 } | |
| 675 | |
| 676 TEST_F(VCDiffStandardDecoderTest, InstructionCompressionNotSupported) { | |
| 677 delta_file_[delta_file_header_.size() + 7] = 0x02; | |
| 678 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 679 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 680 delta_file_.size(), | |
| 681 &output_)); | |
| 682 EXPECT_EQ("", output_); | |
| 683 } | |
| 684 | |
| 685 TEST_F(VCDiffStandardDecoderTest, AddressCompressionNotSupported) { | |
| 686 delta_file_[delta_file_header_.size() + 7] = 0x04; | |
| 687 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 688 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 689 delta_file_.size(), | |
| 690 &output_)); | |
| 691 EXPECT_EQ("", output_); | |
| 692 } | |
| 693 | |
| 694 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeZero) { | |
| 695 delta_file_[delta_file_header_.size() + 8] = 0; | |
| 696 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 697 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 698 delta_file_.size(), | |
| 699 &output_)); | |
| 700 EXPECT_EQ("", output_); | |
| 701 } | |
| 702 | |
| 703 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeTooLargeByOne) { | |
| 704 ++delta_file_[delta_file_header_.size() + 8]; | |
| 705 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 706 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 707 delta_file_.size(), | |
| 708 &output_)); | |
| 709 EXPECT_EQ("", output_); | |
| 710 } | |
| 711 | |
| 712 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeTooSmallByOne) { | |
| 713 --delta_file_[delta_file_header_.size() + 8]; | |
| 714 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 715 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 716 delta_file_.size(), | |
| 717 &output_)); | |
| 718 EXPECT_EQ("", output_); | |
| 719 } | |
| 720 | |
| 721 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeMaxInt) { | |
| 722 WriteMaxVarintAtOffset(8, 1); | |
| 723 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 724 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 725 delta_file_.size(), | |
| 726 &output_)); | |
| 727 EXPECT_EQ("", output_); | |
| 728 } | |
| 729 | |
| 730 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeNegative) { | |
| 731 WriteNegativeVarintAtOffset(8, 1); | |
| 732 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 733 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 734 delta_file_.size(), | |
| 735 &output_)); | |
| 736 EXPECT_EQ("", output_); | |
| 737 } | |
| 738 | |
| 739 TEST_F(VCDiffStandardDecoderTest, AddRunDataSizeInvalid) { | |
| 740 WriteInvalidVarintAtOffset(8, 1); | |
| 741 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 742 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 743 delta_file_.size(), | |
| 744 &output_)); | |
| 745 EXPECT_EQ("", output_); | |
| 746 } | |
| 747 | |
| 748 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeZero) { | |
| 749 delta_file_[delta_file_header_.size() + 9] = 0; | |
| 750 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 751 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 752 delta_file_.size(), | |
| 753 &output_)); | |
| 754 EXPECT_EQ("", output_); | |
| 755 } | |
| 756 | |
| 757 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeTooLargeByOne) { | |
| 758 ++delta_file_[delta_file_header_.size() + 9]; | |
| 759 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 760 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 761 delta_file_.size(), | |
| 762 &output_)); | |
| 763 EXPECT_EQ("", output_); | |
| 764 } | |
| 765 | |
| 766 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeTooSmallByOne) { | |
| 767 --delta_file_[delta_file_header_.size() + 9]; | |
| 768 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 769 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 770 delta_file_.size(), | |
| 771 &output_)); | |
| 772 EXPECT_EQ("", output_); | |
| 773 } | |
| 774 | |
| 775 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeMaxInt) { | |
| 776 WriteMaxVarintAtOffset(9, 1); | |
| 777 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 778 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 779 delta_file_.size(), | |
| 780 &output_)); | |
| 781 EXPECT_EQ("", output_); | |
| 782 } | |
| 783 | |
| 784 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeNegative) { | |
| 785 WriteNegativeVarintAtOffset(9, 1); | |
| 786 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 787 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 788 delta_file_.size(), | |
| 789 &output_)); | |
| 790 EXPECT_EQ("", output_); | |
| 791 } | |
| 792 | |
| 793 TEST_F(VCDiffStandardDecoderTest, InstructionsSizeInvalid) { | |
| 794 WriteInvalidVarintAtOffset(9, 1); | |
| 795 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 796 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 797 delta_file_.size(), | |
| 798 &output_)); | |
| 799 EXPECT_EQ("", output_); | |
| 800 } | |
| 801 | |
| 802 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeZero) { | |
| 803 delta_file_[delta_file_header_.size() + 10] = 0; | |
| 804 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 805 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 806 delta_file_.size(), | |
| 807 &output_)); | |
| 808 EXPECT_EQ("", output_); | |
| 809 } | |
| 810 | |
| 811 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeTooLargeByOne) { | |
| 812 ++delta_file_[delta_file_header_.size() + 10]; | |
| 813 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 814 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 815 delta_file_.size(), | |
| 816 &output_)); | |
| 817 EXPECT_EQ("", output_); | |
| 818 } | |
| 819 | |
| 820 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeTooSmallByOne) { | |
| 821 --delta_file_[delta_file_header_.size() + 10]; | |
| 822 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 823 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 824 delta_file_.size(), | |
| 825 &output_)); | |
| 826 EXPECT_EQ("", output_); | |
| 827 } | |
| 828 | |
| 829 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeMaxInt) { | |
| 830 WriteMaxVarintAtOffset(10, 1); | |
| 831 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 832 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 833 delta_file_.size(), | |
| 834 &output_)); | |
| 835 EXPECT_EQ("", output_); | |
| 836 } | |
| 837 | |
| 838 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeNegative) { | |
| 839 WriteNegativeVarintAtOffset(10, 1); | |
| 840 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 841 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 842 delta_file_.size(), | |
| 843 &output_)); | |
| 844 EXPECT_EQ("", output_); | |
| 845 } | |
| 846 | |
| 847 TEST_F(VCDiffStandardDecoderTest, CopyAddressSizeInvalid) { | |
| 848 WriteInvalidVarintAtOffset(10, 1); | |
| 849 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 850 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 851 delta_file_.size(), | |
| 852 &output_)); | |
| 853 EXPECT_EQ("", output_); | |
| 854 } | |
| 855 | |
| 856 TEST_F(VCDiffStandardDecoderTest, InstructionsEndEarly) { | |
| 857 --delta_file_[delta_file_header_.size() + 9]; | |
| 858 ++delta_file_[delta_file_header_.size() + 10]; | |
| 859 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 860 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 861 delta_file_.size(), | |
| 862 &output_)); | |
| 863 EXPECT_EQ("", output_); | |
| 864 } | |
| 865 | |
| 866 // From this point on, the tests should also be run against the interleaved | |
| 867 // format. | |
| 868 | |
| 869 TEST_F(VCDiffStandardDecoderTest, CopyMoreThanExpectedTarget) { | |
| 870 delta_file_[delta_file_header_.size() + 0x70] = | |
| 871 FirstByteOfStringLength(kExpectedTarget); | |
| 872 delta_file_[delta_file_header_.size() + 0x71] = | |
| 873 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 874 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 875 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 876 delta_file_.size(), | |
| 877 &output_)); | |
| 878 EXPECT_EQ("", output_); | |
| 879 } | |
| 880 | |
| 881 TEST_F(VCDiffStandardDecoderTest, CopySizeZero) { | |
| 882 delta_file_[delta_file_header_.size() + 0x70] = 0; | |
| 883 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 884 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 885 delta_file_.size(), | |
| 886 &output_)); | |
| 887 EXPECT_EQ("", output_); | |
| 888 } | |
| 889 | |
| 890 TEST_F(VCDiffStandardDecoderTest, CopySizeTooLargeByOne) { | |
| 891 ++delta_file_[delta_file_header_.size() + 0x70]; | |
| 892 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 893 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 894 delta_file_.size(), | |
| 895 &output_)); | |
| 896 EXPECT_EQ("", output_); | |
| 897 } | |
| 898 | |
| 899 TEST_F(VCDiffStandardDecoderTest, CopySizeTooSmallByOne) { | |
| 900 --delta_file_[delta_file_header_.size() + 0x70]; | |
| 901 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 902 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 903 delta_file_.size(), | |
| 904 &output_)); | |
| 905 EXPECT_EQ("", output_); | |
| 906 } | |
| 907 | |
| 908 TEST_F(VCDiffStandardDecoderTest, CopySizeMaxInt) { | |
| 909 WriteMaxVarintAtOffset(0x70, 1); | |
| 910 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 911 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 912 delta_file_.size(), | |
| 913 &output_)); | |
| 914 EXPECT_EQ("", output_); | |
| 915 } | |
| 916 | |
| 917 TEST_F(VCDiffStandardDecoderTest, CopySizeNegative) { | |
| 918 WriteNegativeVarintAtOffset(0x70, 1); | |
| 919 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 920 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 921 delta_file_.size(), | |
| 922 &output_)); | |
| 923 EXPECT_EQ("", output_); | |
| 924 } | |
| 925 | |
| 926 TEST_F(VCDiffStandardDecoderTest, CopySizeInvalid) { | |
| 927 WriteInvalidVarintAtOffset(0x70, 1); | |
| 928 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 929 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 930 delta_file_.size(), | |
| 931 &output_)); | |
| 932 EXPECT_EQ("", output_); | |
| 933 } | |
| 934 | |
| 935 TEST_F(VCDiffStandardDecoderTest, CopyAddressBeyondHereAddress) { | |
| 936 delta_file_[delta_file_header_.size() + 0x7B] = | |
| 937 FirstByteOfStringLength(kDictionary); | |
| 938 delta_file_[delta_file_header_.size() + 0x7C] = | |
| 939 SecondByteOfStringLength(kDictionary); | |
| 940 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 941 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 942 delta_file_.size(), | |
| 943 &output_)); | |
| 944 EXPECT_EQ("", output_); | |
| 945 } | |
| 946 | |
| 947 TEST_F(VCDiffStandardDecoderTest, CopyAddressMaxInt) { | |
| 948 WriteMaxVarintAtOffset(0x7B, 1); | |
| 949 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 950 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 951 delta_file_.size(), | |
| 952 &output_)); | |
| 953 EXPECT_EQ("", output_); | |
| 954 } | |
| 955 | |
| 956 TEST_F(VCDiffStandardDecoderTest, CopyAddressNegative) { | |
| 957 WriteNegativeVarintAtOffset(0x70, 1); | |
| 958 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 959 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 960 delta_file_.size(), | |
| 961 &output_)); | |
| 962 EXPECT_EQ("", output_); | |
| 963 } | |
| 964 | |
| 965 TEST_F(VCDiffStandardDecoderTest, CopyAddressInvalid) { | |
| 966 WriteInvalidVarintAtOffset(0x70, 1); | |
| 967 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 968 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 969 delta_file_.size(), | |
| 970 &output_)); | |
| 971 EXPECT_EQ("", output_); | |
| 972 } | |
| 973 | |
| 974 TEST_F(VCDiffStandardDecoderTest, AddMoreThanExpectedTarget) { | |
| 975 delta_file_[delta_file_header_.size() + 0x72] = | |
| 976 FirstByteOfStringLength(kExpectedTarget); | |
| 977 delta_file_[delta_file_header_.size() + 0x73] = | |
| 978 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 979 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 980 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 981 delta_file_.size(), | |
| 982 &output_)); | |
| 983 EXPECT_EQ("", output_); | |
| 984 } | |
| 985 | |
| 986 TEST_F(VCDiffStandardDecoderTest, AddSizeZero) { | |
| 987 delta_file_[delta_file_header_.size() + 0x72] = 0; | |
| 988 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 989 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 990 delta_file_.size(), | |
| 991 &output_)); | |
| 992 EXPECT_EQ("", output_); | |
| 993 } | |
| 994 | |
| 995 TEST_F(VCDiffStandardDecoderTest, AddSizeTooLargeByOne) { | |
| 996 ++delta_file_[delta_file_header_.size() + 0x72]; | |
| 997 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 998 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 999 delta_file_.size(), | |
| 1000 &output_)); | |
| 1001 EXPECT_EQ("", output_); | |
| 1002 } | |
| 1003 | |
| 1004 TEST_F(VCDiffStandardDecoderTest, AddSizeTooSmallByOne) { | |
| 1005 --delta_file_[delta_file_header_.size() + 0x72]; | |
| 1006 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1007 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1008 delta_file_.size(), | |
| 1009 &output_)); | |
| 1010 EXPECT_EQ("", output_); | |
| 1011 } | |
| 1012 | |
| 1013 TEST_F(VCDiffStandardDecoderTest, AddSizeMaxInt) { | |
| 1014 WriteMaxVarintAtOffset(0x72, 1); | |
| 1015 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1016 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1017 delta_file_.size(), | |
| 1018 &output_)); | |
| 1019 EXPECT_EQ("", output_); | |
| 1020 } | |
| 1021 | |
| 1022 TEST_F(VCDiffStandardDecoderTest, AddSizeNegative) { | |
| 1023 WriteNegativeVarintAtOffset(0x72, 1); | |
| 1024 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1025 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1026 delta_file_.size(), | |
| 1027 &output_)); | |
| 1028 EXPECT_EQ("", output_); | |
| 1029 } | |
| 1030 | |
| 1031 TEST_F(VCDiffStandardDecoderTest, AddSizeInvalid) { | |
| 1032 WriteInvalidVarintAtOffset(0x72, 1); | |
| 1033 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1034 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1035 delta_file_.size(), | |
| 1036 &output_)); | |
| 1037 EXPECT_EQ("", output_); | |
| 1038 } | |
| 1039 | |
| 1040 TEST_F(VCDiffStandardDecoderTest, RunMoreThanExpectedTarget) { | |
| 1041 delta_file_[delta_file_header_.size() + 0x78] = | |
| 1042 FirstByteOfStringLength(kExpectedTarget); | |
| 1043 delta_file_[delta_file_header_.size() + 0x79] = | |
| 1044 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 1045 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1046 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1047 delta_file_.size(), | |
| 1048 &output_)); | |
| 1049 EXPECT_EQ("", output_); | |
| 1050 } | |
| 1051 | |
| 1052 TEST_F(VCDiffStandardDecoderTest, RunSizeZero) { | |
| 1053 delta_file_[delta_file_header_.size() + 0x78] = 0; | |
| 1054 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1055 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1056 delta_file_.size(), | |
| 1057 &output_)); | |
| 1058 EXPECT_EQ("", output_); | |
| 1059 } | |
| 1060 | |
| 1061 TEST_F(VCDiffStandardDecoderTest, RunSizeTooLargeByOne) { | |
| 1062 ++delta_file_[delta_file_header_.size() + 0x78]; | |
| 1063 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1064 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1065 delta_file_.size(), | |
| 1066 &output_)); | |
| 1067 EXPECT_EQ("", output_); | |
| 1068 } | |
| 1069 | |
| 1070 TEST_F(VCDiffStandardDecoderTest, RunSizeTooSmallByOne) { | |
| 1071 --delta_file_[delta_file_header_.size() + 0x78]; | |
| 1072 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1073 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1074 delta_file_.size(), | |
| 1075 &output_)); | |
| 1076 EXPECT_EQ("", output_); | |
| 1077 } | |
| 1078 | |
| 1079 TEST_F(VCDiffStandardDecoderTest, RunSizeMaxInt) { | |
| 1080 WriteMaxVarintAtOffset(0x78, 1); | |
| 1081 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1082 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1083 delta_file_.size(), | |
| 1084 &output_)); | |
| 1085 EXPECT_EQ("", output_); | |
| 1086 } | |
| 1087 | |
| 1088 TEST_F(VCDiffStandardDecoderTest, RunSizeNegative) { | |
| 1089 WriteNegativeVarintAtOffset(0x78, 1); | |
| 1090 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1091 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1092 delta_file_.size(), | |
| 1093 &output_)); | |
| 1094 EXPECT_EQ("", output_); | |
| 1095 } | |
| 1096 | |
| 1097 TEST_F(VCDiffStandardDecoderTest, RunSizeInvalid) { | |
| 1098 WriteInvalidVarintAtOffset(0x78, 1); | |
| 1099 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1100 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 1101 delta_file_.size(), | |
| 1102 &output_)); | |
| 1103 EXPECT_EQ("", output_); | |
| 1104 } | |
| 1105 | |
| 1106 // These are the same tests as for VCDiffStandardDecoderTest, with the added | |
| 1107 // complication that instead of calling DecodeChunk() once with the entire data | |
| 1108 // set, DecodeChunk() is called once for each byte of input. This is intended | |
| 1109 // to shake out any bugs with rewind and resume while parsing chunked data. | |
| 1110 | |
| 1111 typedef VCDiffStandardDecoderTest VCDiffStandardDecoderTestByteByByte; | |
| 1112 | |
| 1113 TEST_F(VCDiffStandardDecoderTestByteByByte, DecodeHeaderOnly) { | |
| 1114 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1115 for (size_t i = 0; i < delta_file_header_.size(); ++i) { | |
| 1116 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_header_[i], 1, &output_)); | |
| 1117 } | |
| 1118 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 1119 EXPECT_EQ("", output_); | |
| 1120 } | |
| 1121 | |
| 1122 TEST_F(VCDiffStandardDecoderTestByteByByte, Decode) { | |
| 1123 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1124 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1125 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 1126 } | |
| 1127 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 1128 EXPECT_EQ(expected_target_, output_); | |
| 1129 } | |
| 1130 | |
| 1131 // Remove one byte from the length of the chunk to process, and | |
| 1132 // verify that an error is returned for FinishDecoding(). | |
| 1133 TEST_F(VCDiffStandardDecoderTestByteByByte, FinishAfterDecodingPartialWindow) { | |
| 1134 delta_file_.resize(delta_file_.size() - 1); | |
| 1135 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1136 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1137 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 1138 } | |
| 1139 EXPECT_FALSE(decoder_.FinishDecoding()); | |
| 1140 // The decoder should not create more target bytes than were expected. | |
| 1141 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 1142 } | |
| 1143 | |
| 1144 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
| 1145 FinishAfterDecodingPartialWindowHeader) { | |
| 1146 delta_file_.resize(delta_file_header_.size() | |
| 1147 + delta_window_header_.size() - 1); | |
| 1148 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1149 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1150 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 1151 } | |
| 1152 EXPECT_FALSE(decoder_.FinishDecoding()); | |
| 1153 EXPECT_EQ("", output_); | |
| 1154 } | |
| 1155 | |
| 1156 // If we add a checksum to a standard-format delta file (without using format | |
| 1157 // extensions), it will be interpreted as random bytes inserted into the middle | |
| 1158 // of the file. The decode operation should fail, but where exactly it fails is | |
| 1159 // undefined. | |
| 1160 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
| 1161 StandardFormatDoesNotSupportChecksum) { | |
| 1162 ComputeAndAddChecksum(); | |
| 1163 InitializeDeltaFile(); | |
| 1164 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1165 bool failed = false; | |
| 1166 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1167 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1168 failed = true; | |
| 1169 break; | |
| 1170 } | |
| 1171 } | |
| 1172 EXPECT_TRUE(failed); | |
| 1173 // The decoder should not create more target bytes than were expected. | |
| 1174 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 1175 } | |
| 1176 | |
| 1177 // Fuzz bits to make sure decoder does not violently crash. | |
| 1178 // This test has no expected behavior except that no crashes should occur. | |
| 1179 // In some cases, changing bits will still decode to the correct target; | |
| 1180 // for example, changing unused bits within a bitfield. | |
| 1181 TEST_F(VCDiffStandardDecoderTestByteByByte, FuzzBits) { | |
| 1182 while (FuzzOneByteInDeltaFile()) { | |
| 1183 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1184 bool failed = false; | |
| 1185 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1186 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1187 failed = true; | |
| 1188 break; | |
| 1189 } | |
| 1190 } | |
| 1191 if (!failed) { | |
| 1192 decoder_.FinishDecoding(); | |
| 1193 } | |
| 1194 // The decoder should not create more target bytes than were expected. | |
| 1195 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 1196 InitializeDeltaFile(); | |
| 1197 output_.clear(); | |
| 1198 } | |
| 1199 } | |
| 1200 | |
| 1201 TEST_F(VCDiffStandardDecoderTestByteByByte, CheckAnnotatedOutput) { | |
| 1202 decoder_.EnableAnnotatedOutput(); | |
| 1203 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1204 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1205 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 1206 } | |
| 1207 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 1208 string annotated_output; | |
| 1209 decoder_.GetAnnotatedOutput(&annotated_output); | |
| 1210 EXPECT_EQ(expected_annotated_target_, annotated_output); | |
| 1211 } | |
| 1212 | |
| 1213 // Change each element of the delta file window to an erroneous value | |
| 1214 // and make sure it's caught as an error. | |
| 1215 | |
| 1216 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
| 1217 WinIndicatorHasBothSourceAndTarget) { | |
| 1218 delta_file_[delta_file_header_.size()] = VCD_SOURCE + VCD_TARGET; | |
| 1219 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1220 bool failed = false; | |
| 1221 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1222 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1223 failed = true; | |
| 1224 // It should fail at the position that was altered | |
| 1225 EXPECT_EQ(delta_file_header_.size(), i); | |
| 1226 break; | |
| 1227 } | |
| 1228 } | |
| 1229 EXPECT_TRUE(failed); | |
| 1230 EXPECT_EQ("", output_); | |
| 1231 } | |
| 1232 | |
| 1233 TEST_F(VCDiffStandardDecoderTestByteByByte, OkayToSetUpperBitsOfWinIndicator) { | |
| 1234 // It is not an error to set any of the other bits in Win_Indicator | |
| 1235 // besides VCD_SOURCE and VCD_TARGET. | |
| 1236 delta_file_[delta_file_header_.size()] = 0xFD; | |
| 1237 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1238 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1239 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 1240 } | |
| 1241 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 1242 EXPECT_EQ(expected_target_, output_); | |
| 1243 } | |
| 1244 | |
| 1245 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
| 1246 CopyInstructionsShouldFailIfNoSourceSegment) { | |
| 1247 // Replace the Win_Indicator and the source size and source offset with a | |
| 1248 // single 0 byte (a Win_Indicator for a window with no source segment.) | |
| 1249 delta_window_header_.replace(0, 4, "\0", 1); | |
| 1250 InitializeDeltaFile(); | |
| 1251 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1252 bool failed = false; | |
| 1253 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1254 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1255 failed = true; | |
| 1256 // The first COPY instruction should fail. With the standard format, | |
| 1257 // it may need to see the whole delta window before knowing that it is | |
| 1258 // invalid. | |
| 1259 break; | |
| 1260 } | |
| 1261 } | |
| 1262 EXPECT_TRUE(failed); | |
| 1263 EXPECT_EQ("", output_); | |
| 1264 } | |
| 1265 | |
| 1266 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
| 1267 SourceSegmentSizeExceedsDictionarySize) { | |
| 1268 ++delta_file_[delta_file_header_.size() + 2]; // increment size | |
| 1269 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1270 bool failed = false; | |
| 1271 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1272 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1273 failed = true; | |
| 1274 // It should fail after decoding the source segment size | |
| 1275 EXPECT_EQ(delta_file_header_.size() + 2, i); | |
| 1276 break; | |
| 1277 } | |
| 1278 } | |
| 1279 EXPECT_TRUE(failed); | |
| 1280 EXPECT_EQ("", output_); | |
| 1281 } | |
| 1282 | |
| 1283 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentSizeMaxInt) { | |
| 1284 WriteMaxVarintAtOffset(1, 2); | |
| 1285 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1286 bool failed = false; | |
| 1287 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1288 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1289 failed = true; | |
| 1290 // It should fail after decoding the source segment size | |
| 1291 EXPECT_EQ(delta_file_header_.size() + 5, i); | |
| 1292 break; | |
| 1293 } | |
| 1294 } | |
| 1295 EXPECT_TRUE(failed); | |
| 1296 EXPECT_EQ("", output_); | |
| 1297 } | |
| 1298 | |
| 1299 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentSizeNegative) { | |
| 1300 WriteNegativeVarintAtOffset(1, 2); | |
| 1301 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1302 bool failed = false; | |
| 1303 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1304 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1305 failed = true; | |
| 1306 // It should fail after decoding the source segment size | |
| 1307 EXPECT_EQ(delta_file_header_.size() + 5, i); | |
| 1308 break; | |
| 1309 } | |
| 1310 } | |
| 1311 EXPECT_TRUE(failed); | |
| 1312 EXPECT_EQ("", output_); | |
| 1313 } | |
| 1314 | |
| 1315 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentSizeInvalid) { | |
| 1316 WriteInvalidVarintAtOffset(1, 2); | |
| 1317 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1318 bool failed = false; | |
| 1319 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1320 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1321 failed = true; | |
| 1322 // It should fail after decoding the source segment size | |
| 1323 EXPECT_GE(delta_file_header_.size() + 6, i); | |
| 1324 break; | |
| 1325 } | |
| 1326 } | |
| 1327 EXPECT_TRUE(failed); | |
| 1328 EXPECT_EQ("", output_); | |
| 1329 } | |
| 1330 | |
| 1331 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
| 1332 SourceSegmentEndExceedsDictionarySize) { | |
| 1333 ++delta_file_[delta_file_header_.size() + 3]; // increment start pos | |
| 1334 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1335 bool failed = false; | |
| 1336 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1337 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1338 failed = true; | |
| 1339 // It should fail after decoding the source segment end | |
| 1340 EXPECT_EQ(delta_file_header_.size() + 3, i); | |
| 1341 break; | |
| 1342 } | |
| 1343 } | |
| 1344 EXPECT_TRUE(failed); | |
| 1345 EXPECT_EQ("", output_); | |
| 1346 } | |
| 1347 | |
| 1348 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentPosMaxInt) { | |
| 1349 WriteMaxVarintAtOffset(3, 1); | |
| 1350 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1351 bool failed = false; | |
| 1352 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1353 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1354 failed = true; | |
| 1355 // It should fail after decoding the source segment pos | |
| 1356 EXPECT_EQ(delta_file_header_.size() + 7, i); | |
| 1357 break; | |
| 1358 } | |
| 1359 } | |
| 1360 EXPECT_TRUE(failed); | |
| 1361 EXPECT_EQ("", output_); | |
| 1362 } | |
| 1363 | |
| 1364 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentPosNegative) { | |
| 1365 WriteNegativeVarintAtOffset(3, 1); | |
| 1366 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1367 bool failed = false; | |
| 1368 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1369 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1370 failed = true; | |
| 1371 // It should fail after decoding the source segment pos | |
| 1372 EXPECT_EQ(delta_file_header_.size() + 7, i); | |
| 1373 break; | |
| 1374 } | |
| 1375 } | |
| 1376 EXPECT_TRUE(failed); | |
| 1377 EXPECT_EQ("", output_); | |
| 1378 } | |
| 1379 | |
| 1380 TEST_F(VCDiffStandardDecoderTestByteByByte, SourceSegmentPosInvalid) { | |
| 1381 WriteInvalidVarintAtOffset(3, 1); | |
| 1382 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1383 bool failed = false; | |
| 1384 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1385 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1386 failed = true; | |
| 1387 // It should fail after decoding the source segment pos | |
| 1388 EXPECT_GE(delta_file_header_.size() + 8, i); | |
| 1389 break; | |
| 1390 } | |
| 1391 } | |
| 1392 EXPECT_TRUE(failed); | |
| 1393 EXPECT_EQ("", output_); | |
| 1394 } | |
| 1395 | |
| 1396 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthZero) { | |
| 1397 delta_file_[delta_file_header_.size() + 4] = 0; | |
| 1398 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1399 bool failed = false; | |
| 1400 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1401 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1402 failed = true; | |
| 1403 // It should fail after decoding the copy address segment size | |
| 1404 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1405 break; | |
| 1406 } | |
| 1407 } | |
| 1408 EXPECT_TRUE(failed); | |
| 1409 EXPECT_EQ("", output_); | |
| 1410 } | |
| 1411 | |
| 1412 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthTooLargeByOne) { | |
| 1413 ++delta_file_[delta_file_header_.size() + 4]; | |
| 1414 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1415 bool failed = false; | |
| 1416 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1417 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1418 failed = true; | |
| 1419 // It should fail after decoding the copy address segment size | |
| 1420 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1421 break; | |
| 1422 } | |
| 1423 } | |
| 1424 EXPECT_TRUE(failed); | |
| 1425 EXPECT_EQ("", output_); | |
| 1426 } | |
| 1427 | |
| 1428 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthTooSmallByOne) { | |
| 1429 --delta_file_[delta_file_header_.size() + 4]; | |
| 1430 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1431 bool failed = false; | |
| 1432 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1433 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1434 failed = true; | |
| 1435 // It should fail after decoding the copy address segment size | |
| 1436 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1437 break; | |
| 1438 } | |
| 1439 } | |
| 1440 EXPECT_TRUE(failed); | |
| 1441 EXPECT_EQ("", output_); | |
| 1442 } | |
| 1443 | |
| 1444 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthMaxInt) { | |
| 1445 WriteMaxVarintAtOffset(4, 1); | |
| 1446 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1447 bool failed = false; | |
| 1448 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1449 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1450 failed = true; | |
| 1451 // It should fail before finishing the window header | |
| 1452 EXPECT_GE(delta_file_header_.size() + delta_window_header_.size() + 4, | |
| 1453 i); | |
| 1454 break; | |
| 1455 } | |
| 1456 } | |
| 1457 EXPECT_TRUE(failed); | |
| 1458 EXPECT_EQ("", output_); | |
| 1459 } | |
| 1460 | |
| 1461 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthNegative) { | |
| 1462 WriteNegativeVarintAtOffset(4, 1); | |
| 1463 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1464 bool failed = false; | |
| 1465 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1466 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1467 failed = true; | |
| 1468 // It should fail after decoding the delta encoding length | |
| 1469 EXPECT_EQ(delta_file_header_.size() + 8, i); | |
| 1470 break; | |
| 1471 } | |
| 1472 } | |
| 1473 EXPECT_TRUE(failed); | |
| 1474 EXPECT_EQ("", output_); | |
| 1475 } | |
| 1476 | |
| 1477 TEST_F(VCDiffStandardDecoderTestByteByByte, DeltaEncodingLengthInvalid) { | |
| 1478 WriteInvalidVarintAtOffset(4, 1); | |
| 1479 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1480 bool failed = false; | |
| 1481 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1482 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1483 failed = true; | |
| 1484 // It should fail after decoding the delta encoding length | |
| 1485 EXPECT_GE(delta_file_header_.size() + 9, i); | |
| 1486 break; | |
| 1487 } | |
| 1488 } | |
| 1489 EXPECT_TRUE(failed); | |
| 1490 EXPECT_EQ("", output_); | |
| 1491 } | |
| 1492 | |
| 1493 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeZero) { | |
| 1494 static const char zero_size[] = { 0x00 }; | |
| 1495 delta_file_.replace(delta_file_header_.size() + 5, 2, zero_size, 1); | |
| 1496 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1497 bool failed = false; | |
| 1498 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1499 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1500 failed = true; | |
| 1501 break; | |
| 1502 } | |
| 1503 } | |
| 1504 EXPECT_TRUE(failed); | |
| 1505 EXPECT_EQ("", output_); | |
| 1506 } | |
| 1507 | |
| 1508 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeTooLargeByOne) { | |
| 1509 ++delta_file_[delta_file_header_.size() + 6]; | |
| 1510 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1511 bool failed = false; | |
| 1512 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1513 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1514 failed = true; | |
| 1515 break; | |
| 1516 } | |
| 1517 } | |
| 1518 EXPECT_TRUE(failed); | |
| 1519 // The decoder should not create more target bytes than were expected. | |
| 1520 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 1521 } | |
| 1522 | |
| 1523 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeTooSmallByOne) { | |
| 1524 --delta_file_[delta_file_header_.size() + 6]; | |
| 1525 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1526 bool failed = false; | |
| 1527 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1528 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1529 failed = true; | |
| 1530 break; | |
| 1531 } | |
| 1532 } | |
| 1533 EXPECT_TRUE(failed); | |
| 1534 // The decoder should not create more target bytes than were expected. | |
| 1535 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 1536 } | |
| 1537 | |
| 1538 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeMaxInt) { | |
| 1539 WriteMaxVarintAtOffset(5, 2); | |
| 1540 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1541 bool failed = false; | |
| 1542 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1543 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1544 failed = true; | |
| 1545 // It should fail after decoding the target window size | |
| 1546 EXPECT_EQ(delta_file_header_.size() + 9, i); | |
| 1547 break; | |
| 1548 } | |
| 1549 } | |
| 1550 EXPECT_TRUE(failed); | |
| 1551 EXPECT_EQ("", output_); | |
| 1552 } | |
| 1553 | |
| 1554 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeNegative) { | |
| 1555 WriteNegativeVarintAtOffset(5, 2); | |
| 1556 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1557 bool failed = false; | |
| 1558 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1559 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1560 failed = true; | |
| 1561 // It should fail after decoding the target window size | |
| 1562 EXPECT_EQ(delta_file_header_.size() + 9, i); | |
| 1563 break; | |
| 1564 } | |
| 1565 } | |
| 1566 EXPECT_TRUE(failed); | |
| 1567 EXPECT_EQ("", output_); | |
| 1568 } | |
| 1569 | |
| 1570 TEST_F(VCDiffStandardDecoderTestByteByByte, TargetWindowSizeInvalid) { | |
| 1571 WriteInvalidVarintAtOffset(5, 2); | |
| 1572 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1573 bool failed = false; | |
| 1574 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1575 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1576 failed = true; | |
| 1577 // It should fail after decoding the target window size | |
| 1578 EXPECT_GE(delta_file_header_.size() + 10, i); | |
| 1579 break; | |
| 1580 } | |
| 1581 } | |
| 1582 EXPECT_TRUE(failed); | |
| 1583 EXPECT_EQ("", output_); | |
| 1584 } | |
| 1585 | |
| 1586 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
| 1587 OkayToSetUpperBitsOfDeltaIndicator) { | |
| 1588 delta_file_[delta_file_header_.size() + 7] = 0xF8; | |
| 1589 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1590 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1591 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 1592 } | |
| 1593 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 1594 EXPECT_EQ(expected_target_, output_); | |
| 1595 } | |
| 1596 | |
| 1597 TEST_F(VCDiffStandardDecoderTestByteByByte, DataCompressionNotSupported) { | |
| 1598 delta_file_[delta_file_header_.size() + 7] = 0x01; | |
| 1599 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1600 bool failed = false; | |
| 1601 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1602 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1603 failed = true; | |
| 1604 // It should fail after decoding the delta indicator | |
| 1605 EXPECT_EQ(delta_file_header_.size() + 7, i); | |
| 1606 break; | |
| 1607 } | |
| 1608 } | |
| 1609 EXPECT_TRUE(failed); | |
| 1610 EXPECT_EQ("", output_); | |
| 1611 } | |
| 1612 | |
| 1613 TEST_F(VCDiffStandardDecoderTestByteByByte, | |
| 1614 InstructionCompressionNotSupported) { | |
| 1615 delta_file_[delta_file_header_.size() + 7] = 0x02; | |
| 1616 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1617 bool failed = false; | |
| 1618 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1619 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1620 failed = true; | |
| 1621 // It should fail after decoding the delta indicator | |
| 1622 EXPECT_EQ(delta_file_header_.size() + 7, i); | |
| 1623 break; | |
| 1624 } | |
| 1625 } | |
| 1626 EXPECT_TRUE(failed); | |
| 1627 EXPECT_EQ("", output_); | |
| 1628 } | |
| 1629 | |
| 1630 TEST_F(VCDiffStandardDecoderTestByteByByte, AddressCompressionNotSupported) { | |
| 1631 delta_file_[delta_file_header_.size() + 7] = 0x04; | |
| 1632 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1633 bool failed = false; | |
| 1634 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1635 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1636 failed = true; | |
| 1637 // It should fail after decoding the delta indicator | |
| 1638 EXPECT_EQ(delta_file_header_.size() + 7, i); | |
| 1639 break; | |
| 1640 } | |
| 1641 } | |
| 1642 EXPECT_TRUE(failed); | |
| 1643 EXPECT_EQ("", output_); | |
| 1644 } | |
| 1645 | |
| 1646 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeZero) { | |
| 1647 delta_file_[delta_file_header_.size() + 8] = 0; | |
| 1648 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1649 bool failed = false; | |
| 1650 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1651 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1652 failed = true; | |
| 1653 // It should fail after decoding the copy address segment size | |
| 1654 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1655 break; | |
| 1656 } | |
| 1657 } | |
| 1658 EXPECT_TRUE(failed); | |
| 1659 EXPECT_EQ("", output_); | |
| 1660 } | |
| 1661 | |
| 1662 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeTooLargeByOne) { | |
| 1663 ++delta_file_[delta_file_header_.size() + 8]; | |
| 1664 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1665 bool failed = false; | |
| 1666 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1667 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1668 failed = true; | |
| 1669 // It should fail after decoding the copy address segment size | |
| 1670 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1671 break; | |
| 1672 } | |
| 1673 } | |
| 1674 EXPECT_TRUE(failed); | |
| 1675 EXPECT_EQ("", output_); | |
| 1676 } | |
| 1677 | |
| 1678 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeTooSmallByOne) { | |
| 1679 --delta_file_[delta_file_header_.size() + 8]; | |
| 1680 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1681 bool failed = false; | |
| 1682 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1683 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1684 failed = true; | |
| 1685 // It should fail after decoding the copy address segment size | |
| 1686 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1687 break; | |
| 1688 } | |
| 1689 } | |
| 1690 EXPECT_TRUE(failed); | |
| 1691 EXPECT_EQ("", output_); | |
| 1692 } | |
| 1693 | |
| 1694 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeMaxInt) { | |
| 1695 WriteMaxVarintAtOffset(8, 1); | |
| 1696 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1697 bool failed = false; | |
| 1698 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1699 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1700 failed = true; | |
| 1701 // It should fail before finishing the window header | |
| 1702 EXPECT_GE(delta_file_header_.size() + delta_window_header_.size() + 4, | |
| 1703 i); | |
| 1704 break; | |
| 1705 } | |
| 1706 } | |
| 1707 EXPECT_TRUE(failed); | |
| 1708 EXPECT_EQ("", output_); | |
| 1709 } | |
| 1710 | |
| 1711 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeNegative) { | |
| 1712 WriteNegativeVarintAtOffset(8, 1); | |
| 1713 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1714 bool failed = false; | |
| 1715 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1716 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1717 failed = true; | |
| 1718 // It should fail after decoding the add/run data segment size | |
| 1719 EXPECT_EQ(delta_file_header_.size() + 12, i); | |
| 1720 break; | |
| 1721 } | |
| 1722 } | |
| 1723 EXPECT_TRUE(failed); | |
| 1724 EXPECT_EQ("", output_); | |
| 1725 } | |
| 1726 | |
| 1727 TEST_F(VCDiffStandardDecoderTestByteByByte, AddRunDataSizeInvalid) { | |
| 1728 WriteInvalidVarintAtOffset(8, 1); | |
| 1729 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1730 bool failed = false; | |
| 1731 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1732 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1733 failed = true; | |
| 1734 // It should fail after decoding the add/run data segment size | |
| 1735 EXPECT_GE(delta_file_header_.size() + 13, i); | |
| 1736 break; | |
| 1737 } | |
| 1738 } | |
| 1739 EXPECT_TRUE(failed); | |
| 1740 EXPECT_EQ("", output_); | |
| 1741 } | |
| 1742 | |
| 1743 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeZero) { | |
| 1744 delta_file_[delta_file_header_.size() + 9] = 0; | |
| 1745 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1746 bool failed = false; | |
| 1747 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1748 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1749 failed = true; | |
| 1750 // It should fail after decoding the copy address segment size | |
| 1751 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1752 break; | |
| 1753 } | |
| 1754 } | |
| 1755 EXPECT_TRUE(failed); | |
| 1756 EXPECT_EQ("", output_); | |
| 1757 } | |
| 1758 | |
| 1759 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeTooLargeByOne) { | |
| 1760 ++delta_file_[delta_file_header_.size() + 9]; | |
| 1761 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1762 bool failed = false; | |
| 1763 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1764 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1765 failed = true; | |
| 1766 // It should fail after decoding the copy address segment size | |
| 1767 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1768 break; | |
| 1769 } | |
| 1770 } | |
| 1771 EXPECT_TRUE(failed); | |
| 1772 EXPECT_EQ("", output_); | |
| 1773 } | |
| 1774 | |
| 1775 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeTooSmallByOne) { | |
| 1776 --delta_file_[delta_file_header_.size() + 9]; | |
| 1777 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1778 bool failed = false; | |
| 1779 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1780 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1781 failed = true; | |
| 1782 // It should fail after decoding the copy address segment size | |
| 1783 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1784 break; | |
| 1785 } | |
| 1786 } | |
| 1787 EXPECT_TRUE(failed); | |
| 1788 EXPECT_EQ("", output_); | |
| 1789 } | |
| 1790 | |
| 1791 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeMaxInt) { | |
| 1792 WriteMaxVarintAtOffset(9, 1); | |
| 1793 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1794 bool failed = false; | |
| 1795 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1796 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1797 failed = true; | |
| 1798 // It should fail before finishing the window header | |
| 1799 EXPECT_GE(delta_file_header_.size() + delta_window_header_.size() + 4, | |
| 1800 i); | |
| 1801 break; | |
| 1802 } | |
| 1803 } | |
| 1804 EXPECT_TRUE(failed); | |
| 1805 EXPECT_EQ("", output_); | |
| 1806 } | |
| 1807 | |
| 1808 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeNegative) { | |
| 1809 WriteNegativeVarintAtOffset(9, 1); | |
| 1810 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1811 bool failed = false; | |
| 1812 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1813 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1814 failed = true; | |
| 1815 // It should fail after decoding the instructions segment size | |
| 1816 EXPECT_EQ(delta_file_header_.size() + 13, i); | |
| 1817 break; | |
| 1818 } | |
| 1819 } | |
| 1820 EXPECT_TRUE(failed); | |
| 1821 EXPECT_EQ("", output_); | |
| 1822 } | |
| 1823 | |
| 1824 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsSizeInvalid) { | |
| 1825 WriteInvalidVarintAtOffset(9, 1); | |
| 1826 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1827 bool failed = false; | |
| 1828 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1829 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1830 failed = true; | |
| 1831 // It should fail after decoding the instructions segment size | |
| 1832 EXPECT_GE(delta_file_header_.size() + 14, i); | |
| 1833 break; | |
| 1834 } | |
| 1835 } | |
| 1836 EXPECT_TRUE(failed); | |
| 1837 EXPECT_EQ("", output_); | |
| 1838 } | |
| 1839 | |
| 1840 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeZero) { | |
| 1841 delta_file_[delta_file_header_.size() + 10] = 0; | |
| 1842 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1843 bool failed = false; | |
| 1844 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1845 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1846 failed = true; | |
| 1847 // It should fail after decoding the copy address segment size | |
| 1848 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1849 break; | |
| 1850 } | |
| 1851 } | |
| 1852 EXPECT_TRUE(failed); | |
| 1853 EXPECT_EQ("", output_); | |
| 1854 } | |
| 1855 | |
| 1856 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeTooLargeByOne) { | |
| 1857 ++delta_file_[delta_file_header_.size() + 10]; | |
| 1858 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1859 bool failed = false; | |
| 1860 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1861 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1862 failed = true; | |
| 1863 // It should fail after decoding the copy address segment size | |
| 1864 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1865 break; | |
| 1866 } | |
| 1867 } | |
| 1868 EXPECT_TRUE(failed); | |
| 1869 EXPECT_EQ("", output_); | |
| 1870 } | |
| 1871 | |
| 1872 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeTooSmallByOne) { | |
| 1873 --delta_file_[delta_file_header_.size() + 10]; | |
| 1874 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1875 bool failed = false; | |
| 1876 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1877 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1878 failed = true; | |
| 1879 // It should fail after decoding the copy address segment size | |
| 1880 EXPECT_EQ(delta_file_header_.size() + 10, i); | |
| 1881 break; | |
| 1882 } | |
| 1883 } | |
| 1884 EXPECT_TRUE(failed); | |
| 1885 EXPECT_EQ("", output_); | |
| 1886 } | |
| 1887 | |
| 1888 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeMaxInt) { | |
| 1889 WriteMaxVarintAtOffset(10, 1); | |
| 1890 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1891 bool failed = false; | |
| 1892 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1893 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1894 failed = true; | |
| 1895 // It should fail after decoding the copy address segment size | |
| 1896 EXPECT_EQ(delta_file_header_.size() + 14, i); | |
| 1897 break; | |
| 1898 } | |
| 1899 } | |
| 1900 EXPECT_TRUE(failed); | |
| 1901 EXPECT_EQ("", output_); | |
| 1902 } | |
| 1903 | |
| 1904 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeNegative) { | |
| 1905 WriteNegativeVarintAtOffset(10, 1); | |
| 1906 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1907 bool failed = false; | |
| 1908 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1909 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1910 failed = true; | |
| 1911 // It should fail after decoding the copy address segment size | |
| 1912 EXPECT_EQ(delta_file_header_.size() + 14, i); | |
| 1913 break; | |
| 1914 } | |
| 1915 } | |
| 1916 EXPECT_TRUE(failed); | |
| 1917 EXPECT_EQ("", output_); | |
| 1918 } | |
| 1919 | |
| 1920 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressSizeInvalid) { | |
| 1921 WriteInvalidVarintAtOffset(10, 1); | |
| 1922 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1923 bool failed = false; | |
| 1924 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1925 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1926 failed = true; | |
| 1927 // It should fail after decoding the copy address segment size | |
| 1928 EXPECT_GE(delta_file_header_.size() + 15, i); | |
| 1929 break; | |
| 1930 } | |
| 1931 } | |
| 1932 EXPECT_TRUE(failed); | |
| 1933 EXPECT_EQ("", output_); | |
| 1934 } | |
| 1935 | |
| 1936 TEST_F(VCDiffStandardDecoderTestByteByByte, InstructionsEndEarly) { | |
| 1937 --delta_file_[delta_file_header_.size() + 9]; | |
| 1938 ++delta_file_[delta_file_header_.size() + 10]; | |
| 1939 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1940 bool failed = false; | |
| 1941 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1942 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1943 failed = true; | |
| 1944 break; | |
| 1945 } | |
| 1946 } | |
| 1947 EXPECT_TRUE(failed); | |
| 1948 // The decoder should not create more target bytes than were expected. | |
| 1949 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 1950 } | |
| 1951 | |
| 1952 // From this point on, the tests should also be run against the interleaved | |
| 1953 // format. | |
| 1954 | |
| 1955 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyMoreThanExpectedTarget) { | |
| 1956 delta_file_[delta_file_header_.size() + 0x70] = | |
| 1957 FirstByteOfStringLength(kExpectedTarget); | |
| 1958 delta_file_[delta_file_header_.size() + 0x71] = | |
| 1959 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 1960 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1961 bool failed = false; | |
| 1962 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1963 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1964 failed = true; | |
| 1965 break; | |
| 1966 } | |
| 1967 } | |
| 1968 EXPECT_TRUE(failed); | |
| 1969 // The decoder should not create more target bytes than were expected. | |
| 1970 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 1971 } | |
| 1972 | |
| 1973 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeZero) { | |
| 1974 delta_file_[delta_file_header_.size() + 0x70] = 0; | |
| 1975 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1976 bool failed = false; | |
| 1977 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1978 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1979 failed = true; | |
| 1980 break; | |
| 1981 } | |
| 1982 } | |
| 1983 EXPECT_TRUE(failed); | |
| 1984 // The decoder should not create more target bytes than were expected. | |
| 1985 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 1986 } | |
| 1987 | |
| 1988 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeTooLargeByOne) { | |
| 1989 ++delta_file_[delta_file_header_.size() + 0x70]; | |
| 1990 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 1991 bool failed = false; | |
| 1992 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 1993 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 1994 failed = true; | |
| 1995 break; | |
| 1996 } | |
| 1997 } | |
| 1998 EXPECT_TRUE(failed); | |
| 1999 // The decoder should not create more target bytes than were expected. | |
| 2000 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2001 } | |
| 2002 | |
| 2003 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeTooSmallByOne) { | |
| 2004 --delta_file_[delta_file_header_.size() + 0x70]; | |
| 2005 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2006 bool failed = false; | |
| 2007 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2008 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2009 failed = true; | |
| 2010 break; | |
| 2011 } | |
| 2012 } | |
| 2013 EXPECT_TRUE(failed); | |
| 2014 // The decoder should not create more target bytes than were expected. | |
| 2015 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2016 } | |
| 2017 | |
| 2018 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeMaxInt) { | |
| 2019 WriteMaxVarintAtOffset(0x70, 1); | |
| 2020 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2021 bool failed = false; | |
| 2022 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2023 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2024 failed = true; | |
| 2025 break; | |
| 2026 } | |
| 2027 } | |
| 2028 EXPECT_TRUE(failed); | |
| 2029 // The decoder should not create more target bytes than were expected. | |
| 2030 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2031 } | |
| 2032 | |
| 2033 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeNegative) { | |
| 2034 WriteNegativeVarintAtOffset(0x70, 1); | |
| 2035 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2036 bool failed = false; | |
| 2037 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2038 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2039 failed = true; | |
| 2040 break; | |
| 2041 } | |
| 2042 } | |
| 2043 EXPECT_TRUE(failed); | |
| 2044 // The decoder should not create more target bytes than were expected. | |
| 2045 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2046 } | |
| 2047 | |
| 2048 TEST_F(VCDiffStandardDecoderTestByteByByte, CopySizeInvalid) { | |
| 2049 WriteInvalidVarintAtOffset(0x70, 1); | |
| 2050 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2051 bool failed = false; | |
| 2052 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2053 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2054 failed = true; | |
| 2055 break; | |
| 2056 } | |
| 2057 } | |
| 2058 EXPECT_TRUE(failed); | |
| 2059 // The decoder should not create more target bytes than were expected. | |
| 2060 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2061 } | |
| 2062 | |
| 2063 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressBeyondHereAddress) { | |
| 2064 delta_file_[delta_file_header_.size() + 0x7B] = | |
| 2065 FirstByteOfStringLength(kDictionary); | |
| 2066 delta_file_[delta_file_header_.size() + 0x7C] = | |
| 2067 SecondByteOfStringLength(kDictionary); | |
| 2068 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2069 bool failed = false; | |
| 2070 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2071 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2072 failed = true; | |
| 2073 break; | |
| 2074 } | |
| 2075 } | |
| 2076 EXPECT_TRUE(failed); | |
| 2077 // The decoder should not create more target bytes than were expected. | |
| 2078 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2079 } | |
| 2080 | |
| 2081 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressMaxInt) { | |
| 2082 WriteMaxVarintAtOffset(0x7B, 1); | |
| 2083 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2084 bool failed = false; | |
| 2085 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2086 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2087 failed = true; | |
| 2088 break; | |
| 2089 } | |
| 2090 } | |
| 2091 EXPECT_TRUE(failed); | |
| 2092 // The decoder should not create more target bytes than were expected. | |
| 2093 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2094 } | |
| 2095 | |
| 2096 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressNegative) { | |
| 2097 WriteNegativeVarintAtOffset(0x70, 1); | |
| 2098 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2099 bool failed = false; | |
| 2100 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2101 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2102 failed = true; | |
| 2103 break; | |
| 2104 } | |
| 2105 } | |
| 2106 EXPECT_TRUE(failed); | |
| 2107 // The decoder should not create more target bytes than were expected. | |
| 2108 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2109 } | |
| 2110 | |
| 2111 TEST_F(VCDiffStandardDecoderTestByteByByte, CopyAddressInvalid) { | |
| 2112 WriteInvalidVarintAtOffset(0x70, 1); | |
| 2113 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2114 bool failed = false; | |
| 2115 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2116 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2117 failed = true; | |
| 2118 break; | |
| 2119 } | |
| 2120 } | |
| 2121 EXPECT_TRUE(failed); | |
| 2122 // The decoder should not create more target bytes than were expected. | |
| 2123 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2124 } | |
| 2125 | |
| 2126 TEST_F(VCDiffStandardDecoderTestByteByByte, AddMoreThanExpectedTarget) { | |
| 2127 delta_file_[delta_file_header_.size() + 0x72] = | |
| 2128 FirstByteOfStringLength(kExpectedTarget); | |
| 2129 delta_file_[delta_file_header_.size() + 0x73] = | |
| 2130 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 2131 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2132 bool failed = false; | |
| 2133 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2134 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2135 failed = true; | |
| 2136 break; | |
| 2137 } | |
| 2138 } | |
| 2139 EXPECT_TRUE(failed); | |
| 2140 // The decoder should not create more target bytes than were expected. | |
| 2141 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2142 } | |
| 2143 | |
| 2144 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeZero) { | |
| 2145 delta_file_[delta_file_header_.size() + 0x72] = 0; | |
| 2146 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2147 bool failed = false; | |
| 2148 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2149 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2150 failed = true; | |
| 2151 break; | |
| 2152 } | |
| 2153 } | |
| 2154 EXPECT_TRUE(failed); | |
| 2155 // The decoder should not create more target bytes than were expected. | |
| 2156 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2157 } | |
| 2158 | |
| 2159 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeTooLargeByOne) { | |
| 2160 ++delta_file_[delta_file_header_.size() + 0x72]; | |
| 2161 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2162 bool failed = false; | |
| 2163 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2164 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2165 failed = true; | |
| 2166 break; | |
| 2167 } | |
| 2168 } | |
| 2169 EXPECT_TRUE(failed); | |
| 2170 // The decoder should not create more target bytes than were expected. | |
| 2171 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2172 } | |
| 2173 | |
| 2174 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeTooSmallByOne) { | |
| 2175 --delta_file_[delta_file_header_.size() + 0x72]; | |
| 2176 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2177 bool failed = false; | |
| 2178 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2179 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2180 failed = true; | |
| 2181 break; | |
| 2182 } | |
| 2183 } | |
| 2184 EXPECT_TRUE(failed); | |
| 2185 // The decoder should not create more target bytes than were expected. | |
| 2186 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2187 } | |
| 2188 | |
| 2189 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeMaxInt) { | |
| 2190 WriteMaxVarintAtOffset(0x72, 1); | |
| 2191 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2192 bool failed = false; | |
| 2193 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2194 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2195 failed = true; | |
| 2196 break; | |
| 2197 } | |
| 2198 } | |
| 2199 EXPECT_TRUE(failed); | |
| 2200 // The decoder should not create more target bytes than were expected. | |
| 2201 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2202 } | |
| 2203 | |
| 2204 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeNegative) { | |
| 2205 WriteNegativeVarintAtOffset(0x72, 1); | |
| 2206 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2207 bool failed = false; | |
| 2208 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2209 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2210 failed = true; | |
| 2211 break; | |
| 2212 } | |
| 2213 } | |
| 2214 EXPECT_TRUE(failed); | |
| 2215 // The decoder should not create more target bytes than were expected. | |
| 2216 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2217 } | |
| 2218 | |
| 2219 TEST_F(VCDiffStandardDecoderTestByteByByte, AddSizeInvalid) { | |
| 2220 WriteInvalidVarintAtOffset(0x72, 1); | |
| 2221 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2222 bool failed = false; | |
| 2223 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2224 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2225 failed = true; | |
| 2226 break; | |
| 2227 } | |
| 2228 } | |
| 2229 EXPECT_TRUE(failed); | |
| 2230 // The decoder should not create more target bytes than were expected. | |
| 2231 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2232 } | |
| 2233 | |
| 2234 TEST_F(VCDiffStandardDecoderTestByteByByte, RunMoreThanExpectedTarget) { | |
| 2235 delta_file_[delta_file_header_.size() + 0x78] = | |
| 2236 FirstByteOfStringLength(kExpectedTarget); | |
| 2237 delta_file_[delta_file_header_.size() + 0x79] = | |
| 2238 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 2239 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2240 bool failed = false; | |
| 2241 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2242 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2243 failed = true; | |
| 2244 break; | |
| 2245 } | |
| 2246 } | |
| 2247 EXPECT_TRUE(failed); | |
| 2248 // The decoder should not create more target bytes than were expected. | |
| 2249 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2250 } | |
| 2251 | |
| 2252 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeZero) { | |
| 2253 delta_file_[delta_file_header_.size() + 0x78] = 0; | |
| 2254 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2255 bool failed = false; | |
| 2256 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2257 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2258 failed = true; | |
| 2259 break; | |
| 2260 } | |
| 2261 } | |
| 2262 EXPECT_TRUE(failed); | |
| 2263 // The decoder should not create more target bytes than were expected. | |
| 2264 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2265 } | |
| 2266 | |
| 2267 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeTooLargeByOne) { | |
| 2268 ++delta_file_[delta_file_header_.size() + 0x78]; | |
| 2269 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2270 bool failed = false; | |
| 2271 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2272 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2273 failed = true; | |
| 2274 break; | |
| 2275 } | |
| 2276 } | |
| 2277 EXPECT_TRUE(failed); | |
| 2278 // The decoder should not create more target bytes than were expected. | |
| 2279 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2280 } | |
| 2281 | |
| 2282 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeTooSmallByOne) { | |
| 2283 --delta_file_[delta_file_header_.size() + 0x78]; | |
| 2284 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2285 bool failed = false; | |
| 2286 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2287 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2288 failed = true; | |
| 2289 break; | |
| 2290 } | |
| 2291 } | |
| 2292 EXPECT_TRUE(failed); | |
| 2293 // The decoder should not create more target bytes than were expected. | |
| 2294 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2295 } | |
| 2296 | |
| 2297 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeMaxInt) { | |
| 2298 WriteMaxVarintAtOffset(0x78, 1); | |
| 2299 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2300 bool failed = false; | |
| 2301 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2302 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2303 failed = true; | |
| 2304 break; | |
| 2305 } | |
| 2306 } | |
| 2307 EXPECT_TRUE(failed); | |
| 2308 // The decoder should not create more target bytes than were expected. | |
| 2309 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2310 } | |
| 2311 | |
| 2312 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeNegative) { | |
| 2313 WriteNegativeVarintAtOffset(0x78, 1); | |
| 2314 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2315 bool failed = false; | |
| 2316 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2317 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2318 failed = true; | |
| 2319 break; | |
| 2320 } | |
| 2321 } | |
| 2322 EXPECT_TRUE(failed); | |
| 2323 // The decoder should not create more target bytes than were expected. | |
| 2324 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2325 } | |
| 2326 | |
| 2327 TEST_F(VCDiffStandardDecoderTestByteByByte, RunSizeInvalid) { | |
| 2328 WriteInvalidVarintAtOffset(0x78, 1); | |
| 2329 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2330 bool failed = false; | |
| 2331 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2332 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2333 failed = true; | |
| 2334 break; | |
| 2335 } | |
| 2336 } | |
| 2337 EXPECT_TRUE(failed); | |
| 2338 // The decoder should not create more target bytes than were expected. | |
| 2339 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2340 } | |
| 2341 | |
| 2342 // The "interleaved" decoder test, which decodes a delta file that uses the | |
| 2343 // SDCH extension of interleaving instructions, addresses, and literal data | |
| 2344 // instead of placing them in three separate sections. | |
| 2345 class VCDiffInterleavedDecoderTest : public VCDiffDecoderTest { | |
| 2346 protected: | |
| 2347 VCDiffInterleavedDecoderTest(); | |
| 2348 virtual ~VCDiffInterleavedDecoderTest() {} | |
| 2349 | |
| 2350 private: | |
| 2351 static const char kWindowHeader[]; | |
| 2352 static const char kWindowBody[]; | |
| 2353 }; | |
| 2354 | |
| 2355 const char VCDiffInterleavedDecoderTest::kWindowHeader[] = { | |
| 2356 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
| 2357 FirstByteOfStringLength(kDictionary), // Source segment size | |
| 2358 SecondByteOfStringLength(kDictionary), | |
| 2359 0x00, // Source segment position: start of dictionary | |
| 2360 0x79, // Length of the delta encoding | |
| 2361 FirstByteOfStringLength(kExpectedTarget), // Size of the target window | |
| 2362 SecondByteOfStringLength(kExpectedTarget), | |
| 2363 0x00, // Delta_indicator (no compression) | |
| 2364 0x00, // length of data for ADDs and RUNs (unused) | |
| 2365 0x73, // length of interleaved section | |
| 2366 0x00 // length of addresses for COPYs (unused) | |
| 2367 }; | |
| 2368 | |
| 2369 const char VCDiffInterleavedDecoderTest::kWindowBody[] = { | |
| 2370 0x13, // VCD_COPY mode VCD_SELF, size 0 | |
| 2371 0x1C, // Size of COPY (28) | |
| 2372 0x00, // Address of COPY: Start of dictionary | |
| 2373 0x01, // VCD_ADD size 0 | |
| 2374 0x3D, // Size of ADD (61) | |
| 2375 // Data for ADD (length 61) | |
| 2376 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', | |
| 2377 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', | |
| 2378 'T', 'h', 'a', 't', ' ', | |
| 2379 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', | |
| 2380 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', | |
| 2381 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', | |
| 2382 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
| 2383 0x2C, // Size of COPY (44) | |
| 2384 0x58, // HERE mode address (27+61 back from here_address) | |
| 2385 0xCB, // VCD_ADD size 2 + VCD_COPY mode NEAR(1), size 5 | |
| 2386 // Data for ADDs: 2nd section (length 2) | |
| 2387 'h', 'r', | |
| 2388 0x2D, // NEAR(1) mode address (45 after prior address) | |
| 2389 0x0A, // VCD_ADD size 9 | |
| 2390 // Data for ADDs: 3rd section (length 9) | |
| 2391 'W', 'h', 'a', 't', ' ', | |
| 2392 'I', ' ', 't', 'e', | |
| 2393 0x00, // VCD_RUN size 0 | |
| 2394 0x02, // Size of RUN (2) | |
| 2395 // Data for RUN: 4th section (length 1) | |
| 2396 'l', | |
| 2397 0x01, // VCD_ADD size 0 | |
| 2398 0x1B, // Size of ADD (27) | |
| 2399 // Data for ADD: 4th section (length 27) | |
| 2400 ' ', 'y', 'o', 'u', ' ', | |
| 2401 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', | |
| 2402 't', 'r', 'u', 'e', '.', '\"', '\n' | |
| 2403 }; | |
| 2404 | |
| 2405 VCDiffInterleavedDecoderTest::VCDiffInterleavedDecoderTest() { | |
| 2406 delta_file_header_.assign(kInterleavedFileHeader, | |
| 2407 sizeof(kInterleavedFileHeader)); | |
| 2408 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); | |
| 2409 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
| 2410 } | |
| 2411 | |
| 2412 // Test headers, valid and invalid. | |
| 2413 | |
| 2414 TEST_F(VCDiffInterleavedDecoderTest, DecodeHeaderOnly) { | |
| 2415 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2416 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), | |
| 2417 delta_file_header_.size(), | |
| 2418 &output_)); | |
| 2419 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 2420 EXPECT_EQ("", output_); | |
| 2421 } | |
| 2422 | |
| 2423 TEST_F(VCDiffInterleavedDecoderTest, PartialHeaderNotEnough) { | |
| 2424 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2425 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), | |
| 2426 delta_file_header_.size() - 2, | |
| 2427 &output_)); | |
| 2428 EXPECT_FALSE(decoder_.FinishDecoding()); | |
| 2429 EXPECT_EQ("", output_); | |
| 2430 } | |
| 2431 | |
| 2432 TEST_F(VCDiffInterleavedDecoderTest, BadMagicNumber) { | |
| 2433 delta_file_[1] = 'Q' | 0x80; | |
| 2434 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2435 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2436 delta_file_.size(), | |
| 2437 &output_)); | |
| 2438 EXPECT_EQ("", output_); | |
| 2439 } | |
| 2440 | |
| 2441 TEST_F(VCDiffInterleavedDecoderTest, BadVersionNumber) { | |
| 2442 delta_file_[3] = 0x01; | |
| 2443 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2444 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2445 delta_file_.size(), | |
| 2446 &output_)); | |
| 2447 EXPECT_EQ("", output_); | |
| 2448 } | |
| 2449 | |
| 2450 TEST_F(VCDiffInterleavedDecoderTest, SecondaryCompressionNotSupported) { | |
| 2451 delta_file_[4] = 0x01; | |
| 2452 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2453 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2454 delta_file_.size(), | |
| 2455 &output_)); | |
| 2456 EXPECT_EQ("", output_); | |
| 2457 } | |
| 2458 | |
| 2459 TEST_F(VCDiffInterleavedDecoderTest, Decode) { | |
| 2460 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2461 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2462 delta_file_.size(), | |
| 2463 &output_)); | |
| 2464 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 2465 EXPECT_EQ(expected_target_, output_); | |
| 2466 } | |
| 2467 | |
| 2468 TEST_F(VCDiffInterleavedDecoderTest, DecodeWithChecksum) { | |
| 2469 ComputeAndAddChecksum(); | |
| 2470 InitializeDeltaFile(); | |
| 2471 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2472 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2473 delta_file_.size(), | |
| 2474 &output_)); | |
| 2475 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 2476 EXPECT_EQ(expected_target_, output_); | |
| 2477 } | |
| 2478 | |
| 2479 TEST_F(VCDiffInterleavedDecoderTest, ChecksumDoesNotMatch) { | |
| 2480 AddChecksum(0xBADBAD); | |
| 2481 InitializeDeltaFile(); | |
| 2482 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2483 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2484 delta_file_.size(), | |
| 2485 &output_)); | |
| 2486 EXPECT_EQ("", output_); | |
| 2487 } | |
| 2488 | |
| 2489 // Remove one byte from the length of the chunk to process, and | |
| 2490 // verify that an error is returned for FinishDecoding(). | |
| 2491 TEST_F(VCDiffInterleavedDecoderTest, FinishAfterDecodingPartialWindow) { | |
| 2492 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2493 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2494 delta_file_.size() - 1, | |
| 2495 &output_)); | |
| 2496 EXPECT_FALSE(decoder_.FinishDecoding()); | |
| 2497 // The decoder should not create more target bytes than were expected. | |
| 2498 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2499 } | |
| 2500 | |
| 2501 TEST_F(VCDiffInterleavedDecoderTest, FinishAfterDecodingPartialWindowHeader) { | |
| 2502 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2503 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2504 delta_file_header_.size() | |
| 2505 + delta_window_header_.size() - 1, | |
| 2506 &output_)); | |
| 2507 EXPECT_FALSE(decoder_.FinishDecoding()); | |
| 2508 // The decoder should not create more target bytes than were expected. | |
| 2509 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2510 } | |
| 2511 | |
| 2512 // Fuzz bits to make sure decoder does not violently crash. | |
| 2513 // This test has no expected behavior except that no crashes should occur. | |
| 2514 // In some cases, changing bits will still decode to the correct target; | |
| 2515 // for example, changing unused bits within a bitfield. | |
| 2516 TEST_F(VCDiffInterleavedDecoderTest, FuzzBits) { | |
| 2517 while (FuzzOneByteInDeltaFile()) { | |
| 2518 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2519 if (decoder_.DecodeChunk(delta_file_.data(), | |
| 2520 delta_file_.size(), | |
| 2521 &output_)) { | |
| 2522 decoder_.FinishDecoding(); | |
| 2523 } | |
| 2524 InitializeDeltaFile(); | |
| 2525 output_.clear(); | |
| 2526 } | |
| 2527 } | |
| 2528 | |
| 2529 // If a checksum is present, then fuzzing any of the bits may produce an error, | |
| 2530 // but it should not result in an incorrect target being produced without | |
| 2531 // an error. | |
| 2532 TEST_F(VCDiffInterleavedDecoderTest, FuzzBitsWithChecksum) { | |
| 2533 ComputeAndAddChecksum(); | |
| 2534 InitializeDeltaFile(); | |
| 2535 while (FuzzOneByteInDeltaFile()) { | |
| 2536 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2537 if (decoder_.DecodeChunk(delta_file_.data(), | |
| 2538 delta_file_.size(), | |
| 2539 &output_)) { | |
| 2540 if (decoder_.FinishDecoding()) { | |
| 2541 // Decoding succeeded. Make sure the correct target was produced. | |
| 2542 EXPECT_EQ(expected_target_, output_); | |
| 2543 } | |
| 2544 } else { | |
| 2545 EXPECT_EQ("", output_); | |
| 2546 } | |
| 2547 InitializeDeltaFile(); | |
| 2548 output_.clear(); | |
| 2549 } | |
| 2550 } | |
| 2551 | |
| 2552 TEST_F(VCDiffInterleavedDecoderTest, CheckAnnotatedOutput) { | |
| 2553 decoder_.EnableAnnotatedOutput(); | |
| 2554 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2555 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2556 delta_file_.size(), | |
| 2557 &output_)); | |
| 2558 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 2559 string annotated_output; | |
| 2560 decoder_.GetAnnotatedOutput(&annotated_output); | |
| 2561 EXPECT_EQ(expected_annotated_target_, annotated_output); | |
| 2562 } | |
| 2563 | |
| 2564 TEST_F(VCDiffInterleavedDecoderTest, CopyMoreThanExpectedTarget) { | |
| 2565 delta_file_[delta_file_header_.size() + 0x0C] = | |
| 2566 FirstByteOfStringLength(kExpectedTarget); | |
| 2567 delta_file_[delta_file_header_.size() + 0x0D] = | |
| 2568 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 2569 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2570 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2571 delta_file_.size(), | |
| 2572 &output_)); | |
| 2573 EXPECT_EQ("", output_); | |
| 2574 } | |
| 2575 | |
| 2576 TEST_F(VCDiffInterleavedDecoderTest, CopySizeZero) { | |
| 2577 delta_file_[delta_file_header_.size() + 0x0C] = 0; | |
| 2578 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2579 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2580 delta_file_.size(), | |
| 2581 &output_)); | |
| 2582 EXPECT_EQ("", output_); | |
| 2583 } | |
| 2584 | |
| 2585 TEST_F(VCDiffInterleavedDecoderTest, CopySizeTooLargeByOne) { | |
| 2586 ++delta_file_[delta_file_header_.size() + 0x0C]; | |
| 2587 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2588 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2589 delta_file_.size(), | |
| 2590 &output_)); | |
| 2591 EXPECT_EQ("", output_); | |
| 2592 } | |
| 2593 | |
| 2594 TEST_F(VCDiffInterleavedDecoderTest, CopySizeTooSmallByOne) { | |
| 2595 --delta_file_[delta_file_header_.size() + 0x0C]; | |
| 2596 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2597 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2598 delta_file_.size(), | |
| 2599 &output_)); | |
| 2600 EXPECT_EQ("", output_); | |
| 2601 } | |
| 2602 | |
| 2603 TEST_F(VCDiffInterleavedDecoderTest, CopySizeMaxInt) { | |
| 2604 WriteMaxVarintAtOffset(0x0C, 1); | |
| 2605 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2606 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2607 delta_file_.size(), | |
| 2608 &output_)); | |
| 2609 EXPECT_EQ("", output_); | |
| 2610 } | |
| 2611 | |
| 2612 TEST_F(VCDiffInterleavedDecoderTest, CopySizeNegative) { | |
| 2613 WriteNegativeVarintAtOffset(0x0C, 1); | |
| 2614 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2615 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2616 delta_file_.size(), | |
| 2617 &output_)); | |
| 2618 EXPECT_EQ("", output_); | |
| 2619 } | |
| 2620 | |
| 2621 TEST_F(VCDiffInterleavedDecoderTest, CopySizeInvalid) { | |
| 2622 WriteInvalidVarintAtOffset(0x0C, 1); | |
| 2623 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2624 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2625 delta_file_.size(), | |
| 2626 &output_)); | |
| 2627 EXPECT_EQ("", output_); | |
| 2628 } | |
| 2629 | |
| 2630 TEST_F(VCDiffInterleavedDecoderTest, CopyAddressBeyondHereAddress) { | |
| 2631 delta_file_[delta_file_header_.size() + 0x0D] = | |
| 2632 FirstByteOfStringLength(kDictionary); | |
| 2633 delta_file_[delta_file_header_.size() + 0x0E] = | |
| 2634 SecondByteOfStringLength(kDictionary); | |
| 2635 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2636 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2637 delta_file_.size(), | |
| 2638 &output_)); | |
| 2639 EXPECT_EQ("", output_); | |
| 2640 } | |
| 2641 | |
| 2642 TEST_F(VCDiffInterleavedDecoderTest, CopyAddressMaxInt) { | |
| 2643 WriteMaxVarintAtOffset(0x0D, 1); | |
| 2644 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2645 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2646 delta_file_.size(), | |
| 2647 &output_)); | |
| 2648 EXPECT_EQ("", output_); | |
| 2649 } | |
| 2650 | |
| 2651 TEST_F(VCDiffInterleavedDecoderTest, CopyAddressNegative) { | |
| 2652 WriteNegativeVarintAtOffset(0x0D, 1); | |
| 2653 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2654 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2655 delta_file_.size(), | |
| 2656 &output_)); | |
| 2657 EXPECT_EQ("", output_); | |
| 2658 } | |
| 2659 | |
| 2660 TEST_F(VCDiffInterleavedDecoderTest, CopyAddressInvalid) { | |
| 2661 WriteInvalidVarintAtOffset(0x0D, 1); | |
| 2662 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2663 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2664 delta_file_.size(), | |
| 2665 &output_)); | |
| 2666 EXPECT_EQ("", output_); | |
| 2667 } | |
| 2668 | |
| 2669 TEST_F(VCDiffInterleavedDecoderTest, AddMoreThanExpectedTarget) { | |
| 2670 delta_file_[delta_file_header_.size() + 0x0F] = | |
| 2671 FirstByteOfStringLength(kExpectedTarget); | |
| 2672 delta_file_[delta_file_header_.size() + 0x10] = | |
| 2673 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 2674 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2675 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2676 delta_file_.size(), | |
| 2677 &output_)); | |
| 2678 EXPECT_EQ("", output_); | |
| 2679 } | |
| 2680 | |
| 2681 TEST_F(VCDiffInterleavedDecoderTest, AddSizeZero) { | |
| 2682 delta_file_[delta_file_header_.size() + 0x0F] = 0; | |
| 2683 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2684 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2685 delta_file_.size(), | |
| 2686 &output_)); | |
| 2687 EXPECT_EQ("", output_); | |
| 2688 } | |
| 2689 | |
| 2690 TEST_F(VCDiffInterleavedDecoderTest, AddSizeTooLargeByOne) { | |
| 2691 ++delta_file_[delta_file_header_.size() + 0x0F]; | |
| 2692 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2693 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2694 delta_file_.size(), | |
| 2695 &output_)); | |
| 2696 EXPECT_EQ("", output_); | |
| 2697 } | |
| 2698 | |
| 2699 TEST_F(VCDiffInterleavedDecoderTest, AddSizeTooSmallByOne) { | |
| 2700 --delta_file_[delta_file_header_.size() + 0x0F]; | |
| 2701 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2702 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2703 delta_file_.size(), | |
| 2704 &output_)); | |
| 2705 EXPECT_EQ("", output_); | |
| 2706 } | |
| 2707 | |
| 2708 TEST_F(VCDiffInterleavedDecoderTest, AddSizeMaxInt) { | |
| 2709 WriteMaxVarintAtOffset(0x0F, 1); | |
| 2710 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2711 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2712 delta_file_.size(), | |
| 2713 &output_)); | |
| 2714 EXPECT_EQ("", output_); | |
| 2715 } | |
| 2716 | |
| 2717 TEST_F(VCDiffInterleavedDecoderTest, AddSizeNegative) { | |
| 2718 WriteNegativeVarintAtOffset(0x0F, 1); | |
| 2719 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2720 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2721 delta_file_.size(), | |
| 2722 &output_)); | |
| 2723 EXPECT_EQ("", output_); | |
| 2724 } | |
| 2725 | |
| 2726 TEST_F(VCDiffInterleavedDecoderTest, AddSizeInvalid) { | |
| 2727 WriteInvalidVarintAtOffset(0x0F, 1); | |
| 2728 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2729 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2730 delta_file_.size(), | |
| 2731 &output_)); | |
| 2732 EXPECT_EQ("", output_); | |
| 2733 } | |
| 2734 | |
| 2735 TEST_F(VCDiffInterleavedDecoderTest, RunMoreThanExpectedTarget) { | |
| 2736 delta_file_[delta_file_header_.size() + 0x5F] = | |
| 2737 FirstByteOfStringLength(kExpectedTarget); | |
| 2738 delta_file_[delta_file_header_.size() + 0x60] = | |
| 2739 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 2740 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2741 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2742 delta_file_.size(), | |
| 2743 &output_)); | |
| 2744 EXPECT_EQ("", output_); | |
| 2745 } | |
| 2746 | |
| 2747 TEST_F(VCDiffInterleavedDecoderTest, RunSizeZero) { | |
| 2748 delta_file_[delta_file_header_.size() + 0x5F] = 0; | |
| 2749 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2750 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2751 delta_file_.size(), | |
| 2752 &output_)); | |
| 2753 EXPECT_EQ("", output_); | |
| 2754 } | |
| 2755 | |
| 2756 TEST_F(VCDiffInterleavedDecoderTest, RunSizeTooLargeByOne) { | |
| 2757 ++delta_file_[delta_file_header_.size() + 0x5F]; | |
| 2758 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2759 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2760 delta_file_.size(), | |
| 2761 &output_)); | |
| 2762 EXPECT_EQ("", output_); | |
| 2763 } | |
| 2764 | |
| 2765 TEST_F(VCDiffInterleavedDecoderTest, RunSizeTooSmallByOne) { | |
| 2766 --delta_file_[delta_file_header_.size() + 0x5F]; | |
| 2767 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2768 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2769 delta_file_.size(), | |
| 2770 &output_)); | |
| 2771 EXPECT_EQ("", output_); | |
| 2772 } | |
| 2773 | |
| 2774 TEST_F(VCDiffInterleavedDecoderTest, RunSizeMaxInt) { | |
| 2775 WriteMaxVarintAtOffset(0x5F, 1); | |
| 2776 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2777 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2778 delta_file_.size(), | |
| 2779 &output_)); | |
| 2780 EXPECT_EQ("", output_); | |
| 2781 } | |
| 2782 | |
| 2783 TEST_F(VCDiffInterleavedDecoderTest, RunSizeNegative) { | |
| 2784 WriteNegativeVarintAtOffset(0x5F, 1); | |
| 2785 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2786 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2787 delta_file_.size(), | |
| 2788 &output_)); | |
| 2789 EXPECT_EQ("", output_); | |
| 2790 } | |
| 2791 | |
| 2792 TEST_F(VCDiffInterleavedDecoderTest, RunSizeInvalid) { | |
| 2793 WriteInvalidVarintAtOffset(0x5F, 1); | |
| 2794 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2795 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 2796 delta_file_.size(), | |
| 2797 &output_)); | |
| 2798 EXPECT_EQ("", output_); | |
| 2799 } | |
| 2800 | |
| 2801 #if defined(HAVE_MPROTECT) && \ | |
| 2802 (defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN)) | |
| 2803 TEST_F(VCDiffInterleavedDecoderTest, ShouldNotReadPastEndOfBuffer) { | |
| 2804 // Allocate two memory pages. | |
| 2805 const int page_size = getpagesize(); | |
| 2806 void* two_pages = NULL; | |
| 2807 #ifdef HAVE_POSIX_MEMALIGN | |
| 2808 posix_memalign(&two_pages, page_size, 2 * page_size); | |
| 2809 #else // !HAVE_POSIX_MEMALIGN | |
| 2810 two_pages = memalign(page_size, 2 * page_size); | |
| 2811 #endif // HAVE_POSIX_MEMALIGN | |
| 2812 char* const first_page = reinterpret_cast<char*>(two_pages); | |
| 2813 char* const second_page = first_page + page_size; | |
| 2814 | |
| 2815 // Place the delta string at the end of the first page. | |
| 2816 char* delta_with_guard = second_page - delta_file_.size(); | |
| 2817 memcpy(delta_with_guard, delta_file_.data(), delta_file_.size()); | |
| 2818 | |
| 2819 // Make the second page unreadable. | |
| 2820 mprotect(second_page, page_size, PROT_NONE); | |
| 2821 | |
| 2822 // Now perform the decode operation, which will cause a segmentation fault | |
| 2823 // if it reads past the end of the buffer. | |
| 2824 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2825 EXPECT_TRUE(decoder_.DecodeChunk(delta_with_guard, | |
| 2826 delta_file_.size(), | |
| 2827 &output_)); | |
| 2828 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 2829 EXPECT_EQ(expected_target_, output_); | |
| 2830 | |
| 2831 // Undo the mprotect. | |
| 2832 mprotect(second_page, page_size, PROT_READ|PROT_WRITE); | |
| 2833 free(two_pages); | |
| 2834 } | |
| 2835 | |
| 2836 TEST_F(VCDiffInterleavedDecoderTest, ShouldNotReadPastBeginningOfBuffer) { | |
| 2837 // Allocate two memory pages. | |
| 2838 const int page_size = getpagesize(); | |
| 2839 void* two_pages = NULL; | |
| 2840 #ifdef HAVE_POSIX_MEMALIGN | |
| 2841 posix_memalign(&two_pages, page_size, 2 * page_size); | |
| 2842 #else // !HAVE_POSIX_MEMALIGN | |
| 2843 two_pages = memalign(page_size, 2 * page_size); | |
| 2844 #endif // HAVE_POSIX_MEMALIGN | |
| 2845 char* const first_page = reinterpret_cast<char*>(two_pages); | |
| 2846 char* const second_page = first_page + page_size; | |
| 2847 | |
| 2848 // Make the first page unreadable. | |
| 2849 mprotect(first_page, page_size, PROT_NONE); | |
| 2850 | |
| 2851 // Place the delta string at the beginning of the second page. | |
| 2852 char* delta_with_guard = second_page; | |
| 2853 memcpy(delta_with_guard, delta_file_.data(), delta_file_.size()); | |
| 2854 | |
| 2855 // Now perform the decode operation, which will cause a segmentation fault | |
| 2856 // if it reads past the beginning of the buffer. | |
| 2857 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2858 EXPECT_TRUE(decoder_.DecodeChunk(delta_with_guard, | |
| 2859 delta_file_.size(), | |
| 2860 &output_)); | |
| 2861 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 2862 EXPECT_EQ(expected_target_, output_); | |
| 2863 | |
| 2864 // Undo the mprotect. | |
| 2865 mprotect(first_page, page_size, PROT_READ|PROT_WRITE); | |
| 2866 free(two_pages); | |
| 2867 } | |
| 2868 #endif // HAVE_MPROTECT && (HAVE_MEMALIGN || HAVE_POSIX_MEMALIGN) | |
| 2869 | |
| 2870 // These are the same tests as for VCDiffInterleavedDecoderTest, with the added | |
| 2871 // complication that instead of calling DecodeChunk() once with the entire data | |
| 2872 // set, DecodeChunk() is called once for each byte of input. This is intended | |
| 2873 // to shake out any bugs with rewind and resume while parsing chunked data. | |
| 2874 | |
| 2875 typedef VCDiffInterleavedDecoderTest VCDiffInterleavedDecoderTestByteByByte; | |
| 2876 | |
| 2877 // Test headers, valid and invalid. | |
| 2878 | |
| 2879 TEST_F(VCDiffInterleavedDecoderTestByteByByte, DecodeHeaderOnly) { | |
| 2880 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2881 for (size_t i = 0; i < delta_file_header_.size(); ++i) { | |
| 2882 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_header_[i], 1, &output_)); | |
| 2883 } | |
| 2884 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 2885 EXPECT_EQ("", output_); | |
| 2886 } | |
| 2887 | |
| 2888 TEST_F(VCDiffInterleavedDecoderTestByteByByte, PartialHeaderNotEnough) { | |
| 2889 delta_file_.resize(delta_file_header_.size() - 2); | |
| 2890 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2891 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2892 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 2893 } | |
| 2894 EXPECT_FALSE(decoder_.FinishDecoding()); | |
| 2895 EXPECT_EQ("", output_); | |
| 2896 } | |
| 2897 | |
| 2898 TEST_F(VCDiffInterleavedDecoderTestByteByByte, BadMagicNumber) { | |
| 2899 delta_file_[1] = 'Q' | 0x80; | |
| 2900 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2901 bool failed = false; | |
| 2902 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2903 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2904 // It should fail at the position that was altered | |
| 2905 EXPECT_EQ(1U, i); | |
| 2906 failed = true; | |
| 2907 break; | |
| 2908 } | |
| 2909 } | |
| 2910 EXPECT_TRUE(failed); | |
| 2911 EXPECT_EQ("", output_); | |
| 2912 } | |
| 2913 | |
| 2914 TEST_F(VCDiffInterleavedDecoderTestByteByByte, BadVersionNumber) { | |
| 2915 delta_file_[3] = 0x01; | |
| 2916 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2917 bool failed = false; | |
| 2918 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2919 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2920 failed = true; | |
| 2921 // It should fail at the position that was altered | |
| 2922 EXPECT_EQ(3U, i); | |
| 2923 break; | |
| 2924 } | |
| 2925 } | |
| 2926 EXPECT_TRUE(failed); | |
| 2927 EXPECT_EQ("", output_); | |
| 2928 } | |
| 2929 | |
| 2930 TEST_F(VCDiffInterleavedDecoderTestByteByByte, | |
| 2931 SecondaryCompressionNotSupported) { | |
| 2932 delta_file_[4] = 0x01; | |
| 2933 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2934 bool failed = false; | |
| 2935 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2936 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2937 failed = true; | |
| 2938 // It should fail at the position that was altered | |
| 2939 EXPECT_EQ(4U, i); | |
| 2940 break; | |
| 2941 } | |
| 2942 } | |
| 2943 EXPECT_TRUE(failed); | |
| 2944 EXPECT_EQ("", output_); | |
| 2945 } | |
| 2946 | |
| 2947 TEST_F(VCDiffInterleavedDecoderTestByteByByte, Decode) { | |
| 2948 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2949 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2950 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 2951 } | |
| 2952 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 2953 EXPECT_EQ(expected_target_, output_); | |
| 2954 } | |
| 2955 | |
| 2956 TEST_F(VCDiffInterleavedDecoderTestByteByByte, DecodeWithChecksum) { | |
| 2957 ComputeAndAddChecksum(); | |
| 2958 InitializeDeltaFile(); | |
| 2959 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2960 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2961 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 2962 } | |
| 2963 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 2964 EXPECT_EQ(expected_target_, output_); | |
| 2965 } | |
| 2966 | |
| 2967 TEST_F(VCDiffInterleavedDecoderTestByteByByte, ChecksumDoesNotMatch) { | |
| 2968 AddChecksum(0xBADBAD); | |
| 2969 InitializeDeltaFile(); | |
| 2970 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2971 bool failed = false; | |
| 2972 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2973 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2974 failed = true; | |
| 2975 // It should fail after decoding the entire delta file | |
| 2976 EXPECT_EQ(delta_file_.size() - 1, i); | |
| 2977 break; | |
| 2978 } | |
| 2979 } | |
| 2980 EXPECT_TRUE(failed); | |
| 2981 // The decoder should not create more target bytes than were expected. | |
| 2982 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 2983 } | |
| 2984 | |
| 2985 // Fuzz bits to make sure decoder does not violently crash. | |
| 2986 // This test has no expected behavior except that no crashes should occur. | |
| 2987 // In some cases, changing bits will still decode to the correct target; | |
| 2988 // for example, changing unused bits within a bitfield. | |
| 2989 TEST_F(VCDiffInterleavedDecoderTestByteByByte, FuzzBits) { | |
| 2990 while (FuzzOneByteInDeltaFile()) { | |
| 2991 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 2992 bool failed = false; | |
| 2993 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 2994 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 2995 failed = true; | |
| 2996 break; | |
| 2997 } | |
| 2998 } | |
| 2999 if (!failed) { | |
| 3000 decoder_.FinishDecoding(); | |
| 3001 } | |
| 3002 InitializeDeltaFile(); | |
| 3003 output_.clear(); | |
| 3004 } | |
| 3005 } | |
| 3006 | |
| 3007 // If a checksum is present, then fuzzing any of the bits may produce an error, | |
| 3008 // but it should not result in an incorrect target being produced without | |
| 3009 // an error. | |
| 3010 TEST_F(VCDiffInterleavedDecoderTestByteByByte, FuzzBitsWithChecksum) { | |
| 3011 ComputeAndAddChecksum(); | |
| 3012 InitializeDeltaFile(); | |
| 3013 while (FuzzOneByteInDeltaFile()) { | |
| 3014 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3015 bool failed = false; | |
| 3016 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3017 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3018 failed = true; | |
| 3019 break; | |
| 3020 } | |
| 3021 } | |
| 3022 if (!failed) { | |
| 3023 if (decoder_.FinishDecoding()) { | |
| 3024 // Decoding succeeded. Make sure the correct target was produced. | |
| 3025 EXPECT_EQ(expected_target_, output_); | |
| 3026 } | |
| 3027 } | |
| 3028 // The decoder should not create more target bytes than were expected. | |
| 3029 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3030 InitializeDeltaFile(); | |
| 3031 output_.clear(); | |
| 3032 } | |
| 3033 } | |
| 3034 | |
| 3035 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CheckAnnotatedOutput) { | |
| 3036 decoder_.EnableAnnotatedOutput(); | |
| 3037 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3038 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3039 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 3040 } | |
| 3041 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3042 string annotated_output; | |
| 3043 decoder_.GetAnnotatedOutput(&annotated_output); | |
| 3044 EXPECT_EQ(expected_annotated_target_, annotated_output); | |
| 3045 } | |
| 3046 | |
| 3047 TEST_F(VCDiffInterleavedDecoderTestByteByByte, | |
| 3048 CopyInstructionsShouldFailIfNoSourceSegment) { | |
| 3049 // Replace the Win_Indicator and the source size and source offset with a | |
| 3050 // single 0 byte (a Win_Indicator for a window with no source segment.) | |
| 3051 delta_window_header_.replace(0, 4, "\0", 1); | |
| 3052 InitializeDeltaFile(); | |
| 3053 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3054 bool failed = false; | |
| 3055 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3056 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3057 failed = true; | |
| 3058 // The first COPY instruction should fail. | |
| 3059 EXPECT_EQ(delta_file_header_.size() + delta_window_header_.size() + 2, i); | |
| 3060 break; | |
| 3061 } | |
| 3062 } | |
| 3063 EXPECT_TRUE(failed); | |
| 3064 EXPECT_EQ("", output_); | |
| 3065 } | |
| 3066 | |
| 3067 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyMoreThanExpectedTarget) { | |
| 3068 delta_file_[delta_file_header_.size() + 0x0C] = | |
| 3069 FirstByteOfStringLength(kExpectedTarget); | |
| 3070 delta_file_[delta_file_header_.size() + 0x0D] = | |
| 3071 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 3072 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3073 bool failed = false; | |
| 3074 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3075 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3076 failed = true; | |
| 3077 // It should fail at the position that was altered | |
| 3078 EXPECT_EQ(delta_file_header_.size() + 0x0D, i); | |
| 3079 break; | |
| 3080 } | |
| 3081 } | |
| 3082 EXPECT_TRUE(failed); | |
| 3083 // The decoder should not create more target bytes than were expected. | |
| 3084 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3085 } | |
| 3086 | |
| 3087 // A COPY instruction with an explicit size of 0 is not illegal according to the | |
| 3088 // standard, although it is inefficient and should not be generated by any | |
| 3089 // reasonable encoder. Changing the size of a COPY instruction to zero will | |
| 3090 // cause a failure because the generated target window size will not match the | |
| 3091 // expected target size. | |
| 3092 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeZero) { | |
| 3093 delta_file_[delta_file_header_.size() + 0x0C] = 0; | |
| 3094 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3095 bool failed = false; | |
| 3096 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3097 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3098 failed = true; | |
| 3099 break; | |
| 3100 } | |
| 3101 } | |
| 3102 EXPECT_TRUE(failed); | |
| 3103 // The decoder should not create more target bytes than were expected. | |
| 3104 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3105 } | |
| 3106 | |
| 3107 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeTooLargeByOne) { | |
| 3108 ++delta_file_[delta_file_header_.size() + 0x0C]; | |
| 3109 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3110 bool failed = false; | |
| 3111 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3112 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3113 failed = true; | |
| 3114 break; | |
| 3115 } | |
| 3116 } | |
| 3117 EXPECT_TRUE(failed); | |
| 3118 // The decoder should not create more target bytes than were expected. | |
| 3119 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3120 } | |
| 3121 | |
| 3122 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeTooSmallByOne) { | |
| 3123 --delta_file_[delta_file_header_.size() + 0x0C]; | |
| 3124 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3125 bool failed = false; | |
| 3126 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3127 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3128 failed = true; | |
| 3129 break; | |
| 3130 } | |
| 3131 } | |
| 3132 EXPECT_TRUE(failed); | |
| 3133 // The decoder should not create more target bytes than were expected. | |
| 3134 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3135 } | |
| 3136 | |
| 3137 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeMaxInt) { | |
| 3138 WriteMaxVarintAtOffset(0x0C, 1); | |
| 3139 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3140 bool failed = false; | |
| 3141 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3142 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3143 failed = true; | |
| 3144 // It should fail at the position that was altered | |
| 3145 EXPECT_EQ(delta_file_header_.size() + 0x10, i); | |
| 3146 break; | |
| 3147 } | |
| 3148 } | |
| 3149 EXPECT_TRUE(failed); | |
| 3150 // The decoder should not create more target bytes than were expected. | |
| 3151 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3152 } | |
| 3153 | |
| 3154 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeNegative) { | |
| 3155 WriteNegativeVarintAtOffset(0x0C, 1); | |
| 3156 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3157 bool failed = false; | |
| 3158 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3159 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3160 failed = true; | |
| 3161 // It should fail at the position that was altered | |
| 3162 EXPECT_EQ(delta_file_header_.size() + 0x10, i); | |
| 3163 break; | |
| 3164 } | |
| 3165 } | |
| 3166 EXPECT_TRUE(failed); | |
| 3167 // The decoder should not create more target bytes than were expected. | |
| 3168 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3169 } | |
| 3170 | |
| 3171 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeInvalid) { | |
| 3172 WriteInvalidVarintAtOffset(0x0C, 1); | |
| 3173 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3174 bool failed = false; | |
| 3175 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3176 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3177 failed = true; | |
| 3178 // It should fail at the position that was altered | |
| 3179 EXPECT_EQ(delta_file_header_.size() + 0x10, i); | |
| 3180 break; | |
| 3181 } | |
| 3182 } | |
| 3183 EXPECT_TRUE(failed); | |
| 3184 // The decoder should not create more target bytes than were expected. | |
| 3185 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3186 } | |
| 3187 | |
| 3188 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressBeyondHereAddress) { | |
| 3189 delta_file_[delta_file_header_.size() + 0x0D] = | |
| 3190 FirstByteOfStringLength(kDictionary); | |
| 3191 delta_file_[delta_file_header_.size() + 0x0E] = | |
| 3192 SecondByteOfStringLength(kDictionary); | |
| 3193 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3194 bool failed = false; | |
| 3195 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3196 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3197 failed = true; | |
| 3198 // It should fail at the position that was altered | |
| 3199 EXPECT_EQ(delta_file_header_.size() + 0x0E, i); | |
| 3200 break; | |
| 3201 } | |
| 3202 } | |
| 3203 EXPECT_TRUE(failed); | |
| 3204 // The decoder should not create more target bytes than were expected. | |
| 3205 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3206 } | |
| 3207 | |
| 3208 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressMaxInt) { | |
| 3209 WriteMaxVarintAtOffset(0x0D, 1); | |
| 3210 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3211 bool failed = false; | |
| 3212 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3213 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3214 failed = true; | |
| 3215 // It should fail at the position that was altered | |
| 3216 EXPECT_EQ(delta_file_header_.size() + 0x11, i); | |
| 3217 break; | |
| 3218 } | |
| 3219 } | |
| 3220 EXPECT_TRUE(failed); | |
| 3221 // The decoder should not create more target bytes than were expected. | |
| 3222 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3223 } | |
| 3224 | |
| 3225 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressNegative) { | |
| 3226 WriteNegativeVarintAtOffset(0x0D, 1); | |
| 3227 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3228 bool failed = false; | |
| 3229 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3230 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3231 failed = true; | |
| 3232 // It should fail at the position that was altered | |
| 3233 EXPECT_EQ(delta_file_header_.size() + 0x11, i); | |
| 3234 break; | |
| 3235 } | |
| 3236 } | |
| 3237 EXPECT_TRUE(failed); | |
| 3238 // The decoder should not create more target bytes than were expected. | |
| 3239 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3240 } | |
| 3241 | |
| 3242 TEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressInvalid) { | |
| 3243 WriteInvalidVarintAtOffset(0x0D, 1); | |
| 3244 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3245 bool failed = false; | |
| 3246 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3247 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3248 failed = true; | |
| 3249 // It should fail at the position that was altered | |
| 3250 EXPECT_EQ(delta_file_header_.size() + 0x11, i); | |
| 3251 break; | |
| 3252 } | |
| 3253 } | |
| 3254 EXPECT_TRUE(failed); | |
| 3255 // The decoder should not create more target bytes than were expected. | |
| 3256 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3257 } | |
| 3258 | |
| 3259 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddMoreThanExpectedTarget) { | |
| 3260 delta_file_[delta_file_header_.size() + 0x0F] = | |
| 3261 FirstByteOfStringLength(kExpectedTarget); | |
| 3262 delta_file_[delta_file_header_.size() + 0x10] = | |
| 3263 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 3264 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3265 bool failed = false; | |
| 3266 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3267 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3268 failed = true; | |
| 3269 // It should fail at the position that was altered | |
| 3270 EXPECT_EQ(delta_file_header_.size() + 0x10, i); | |
| 3271 break; | |
| 3272 } | |
| 3273 } | |
| 3274 EXPECT_TRUE(failed); | |
| 3275 // The decoder should not create more target bytes than were expected. | |
| 3276 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3277 } | |
| 3278 | |
| 3279 // An ADD instruction with an explicit size of 0 is not illegal according to the | |
| 3280 // standard, although it is inefficient and should not be generated by any | |
| 3281 // reasonable encoder. Changing the size of an ADD instruction to zero will | |
| 3282 // cause a failure because the generated target window size will not match the | |
| 3283 // expected target size. | |
| 3284 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeZero) { | |
| 3285 delta_file_[delta_file_header_.size() + 0x0F] = 0; | |
| 3286 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3287 bool failed = false; | |
| 3288 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3289 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3290 failed = true; | |
| 3291 break; | |
| 3292 } | |
| 3293 } | |
| 3294 EXPECT_TRUE(failed); | |
| 3295 // The decoder should not create more target bytes than were expected. | |
| 3296 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3297 } | |
| 3298 | |
| 3299 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeTooLargeByOne) { | |
| 3300 ++delta_file_[delta_file_header_.size() + 0x0F]; | |
| 3301 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3302 bool failed = false; | |
| 3303 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3304 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3305 failed = true; | |
| 3306 break; | |
| 3307 } | |
| 3308 } | |
| 3309 EXPECT_TRUE(failed); | |
| 3310 // The decoder should not create more target bytes than were expected. | |
| 3311 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3312 } | |
| 3313 | |
| 3314 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeTooSmallByOne) { | |
| 3315 --delta_file_[delta_file_header_.size() + 0x0F]; | |
| 3316 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3317 bool failed = false; | |
| 3318 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3319 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3320 failed = true; | |
| 3321 break; | |
| 3322 } | |
| 3323 } | |
| 3324 EXPECT_TRUE(failed); | |
| 3325 // The decoder should not create more target bytes than were expected. | |
| 3326 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3327 } | |
| 3328 | |
| 3329 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeMaxInt) { | |
| 3330 WriteMaxVarintAtOffset(0x0F, 1); | |
| 3331 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3332 bool failed = false; | |
| 3333 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3334 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3335 failed = true; | |
| 3336 // It should fail at the position that was altered | |
| 3337 EXPECT_EQ(delta_file_header_.size() + 0x13, i); | |
| 3338 break; | |
| 3339 } | |
| 3340 } | |
| 3341 EXPECT_TRUE(failed); | |
| 3342 // The decoder should not create more target bytes than were expected. | |
| 3343 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3344 } | |
| 3345 | |
| 3346 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeNegative) { | |
| 3347 WriteNegativeVarintAtOffset(0x0F, 1); | |
| 3348 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3349 bool failed = false; | |
| 3350 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3351 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3352 failed = true; | |
| 3353 // It should fail at the position that was altered | |
| 3354 EXPECT_EQ(delta_file_header_.size() + 0x13, i); | |
| 3355 break; | |
| 3356 } | |
| 3357 } | |
| 3358 EXPECT_TRUE(failed); | |
| 3359 // The decoder should not create more target bytes than were expected. | |
| 3360 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3361 } | |
| 3362 | |
| 3363 TEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeInvalid) { | |
| 3364 WriteInvalidVarintAtOffset(0x0F, 1); | |
| 3365 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3366 bool failed = false; | |
| 3367 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3368 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3369 failed = true; | |
| 3370 // It should fail at the position that was altered | |
| 3371 EXPECT_EQ(delta_file_header_.size() + 0x13, i); | |
| 3372 break; | |
| 3373 } | |
| 3374 } | |
| 3375 EXPECT_TRUE(failed); | |
| 3376 // The decoder should not create more target bytes than were expected. | |
| 3377 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3378 } | |
| 3379 | |
| 3380 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunMoreThanExpectedTarget) { | |
| 3381 delta_file_[delta_file_header_.size() + 0x5F] = | |
| 3382 FirstByteOfStringLength(kExpectedTarget); | |
| 3383 delta_file_[delta_file_header_.size() + 0x60] = | |
| 3384 SecondByteOfStringLength(kExpectedTarget) + 1; | |
| 3385 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3386 bool failed = false; | |
| 3387 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3388 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3389 failed = true; | |
| 3390 // It should fail at the position that was altered | |
| 3391 EXPECT_EQ(delta_file_header_.size() + 0x60, i); | |
| 3392 break; | |
| 3393 } | |
| 3394 } | |
| 3395 EXPECT_TRUE(failed); | |
| 3396 // The decoder should not create more target bytes than were expected. | |
| 3397 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3398 } | |
| 3399 | |
| 3400 // A RUN instruction with an explicit size of 0 is not illegal according to the | |
| 3401 // standard, although it is inefficient and should not be generated by any | |
| 3402 // reasonable encoder. Changing the size of a RUN instruction to zero will | |
| 3403 // cause a failure because the generated target window size will not match the | |
| 3404 // expected target size. | |
| 3405 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeZero) { | |
| 3406 delta_file_[delta_file_header_.size() + 0x5F] = 0; | |
| 3407 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3408 bool failed = false; | |
| 3409 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3410 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3411 failed = true; | |
| 3412 break; | |
| 3413 } | |
| 3414 } | |
| 3415 EXPECT_TRUE(failed); | |
| 3416 // The decoder should not create more target bytes than were expected. | |
| 3417 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3418 } | |
| 3419 | |
| 3420 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeTooLargeByOne) { | |
| 3421 ++delta_file_[delta_file_header_.size() + 0x5F]; | |
| 3422 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3423 bool failed = false; | |
| 3424 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3425 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3426 failed = true; | |
| 3427 break; | |
| 3428 } | |
| 3429 } | |
| 3430 EXPECT_TRUE(failed); | |
| 3431 // The decoder should not create more target bytes than were expected. | |
| 3432 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3433 } | |
| 3434 | |
| 3435 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeTooSmallByOne) { | |
| 3436 --delta_file_[delta_file_header_.size() + 0x5F]; | |
| 3437 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3438 bool failed = false; | |
| 3439 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3440 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3441 failed = true; | |
| 3442 break; | |
| 3443 } | |
| 3444 } | |
| 3445 EXPECT_TRUE(failed); | |
| 3446 // The decoder should not create more target bytes than were expected. | |
| 3447 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3448 } | |
| 3449 | |
| 3450 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeMaxInt) { | |
| 3451 WriteMaxVarintAtOffset(0x5F, 1); | |
| 3452 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3453 bool failed = false; | |
| 3454 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3455 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3456 failed = true; | |
| 3457 // It should fail at the position that was altered | |
| 3458 EXPECT_EQ(delta_file_header_.size() + 0x63, i); | |
| 3459 break; | |
| 3460 } | |
| 3461 } | |
| 3462 EXPECT_TRUE(failed); | |
| 3463 // The decoder should not create more target bytes than were expected. | |
| 3464 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3465 } | |
| 3466 | |
| 3467 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeNegative) { | |
| 3468 WriteNegativeVarintAtOffset(0x5F, 1); | |
| 3469 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3470 bool failed = false; | |
| 3471 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3472 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3473 failed = true; | |
| 3474 // It should fail at the position that was altered | |
| 3475 EXPECT_EQ(delta_file_header_.size() + 0x63, i); | |
| 3476 break; | |
| 3477 } | |
| 3478 } | |
| 3479 EXPECT_TRUE(failed); | |
| 3480 // The decoder should not create more target bytes than were expected. | |
| 3481 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3482 } | |
| 3483 | |
| 3484 TEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeInvalid) { | |
| 3485 WriteInvalidVarintAtOffset(0x5F, 1); | |
| 3486 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3487 bool failed = false; | |
| 3488 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3489 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3490 failed = true; | |
| 3491 // It should fail at the position that was altered | |
| 3492 EXPECT_EQ(delta_file_header_.size() + 0x63, i); | |
| 3493 break; | |
| 3494 } | |
| 3495 } | |
| 3496 EXPECT_TRUE(failed); | |
| 3497 // The decoder should not create more target bytes than were expected. | |
| 3498 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3499 } | |
| 3500 | |
| 3501 // Use the interleaved file header with the standard encoding. Should work. | |
| 3502 class VCDiffDecoderInterleavedAllowedButNotUsed | |
| 3503 : public VCDiffStandardDecoderTest { | |
| 3504 public: | |
| 3505 VCDiffDecoderInterleavedAllowedButNotUsed() { | |
| 3506 delta_file_header_.assign(kInterleavedFileHeader, | |
| 3507 sizeof(kInterleavedFileHeader)); | |
| 3508 } | |
| 3509 virtual ~VCDiffDecoderInterleavedAllowedButNotUsed() { } | |
| 3510 }; | |
| 3511 | |
| 3512 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsed, Decode) { | |
| 3513 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3514 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 3515 delta_file_.size(), | |
| 3516 &output_)); | |
| 3517 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3518 EXPECT_EQ(expected_target_, output_); | |
| 3519 } | |
| 3520 | |
| 3521 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsed, DecodeWithChecksum) { | |
| 3522 ComputeAndAddChecksum(); | |
| 3523 InitializeDeltaFile(); | |
| 3524 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3525 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 3526 delta_file_.size(), | |
| 3527 &output_)); | |
| 3528 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3529 EXPECT_EQ(expected_target_, output_); | |
| 3530 } | |
| 3531 | |
| 3532 typedef VCDiffDecoderInterleavedAllowedButNotUsed | |
| 3533 VCDiffDecoderInterleavedAllowedButNotUsedByteByByte; | |
| 3534 | |
| 3535 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsedByteByByte, Decode) { | |
| 3536 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3537 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3538 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 3539 } | |
| 3540 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3541 EXPECT_EQ(expected_target_, output_); | |
| 3542 } | |
| 3543 | |
| 3544 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsedByteByByte, | |
| 3545 DecodeWithChecksum) { | |
| 3546 ComputeAndAddChecksum(); | |
| 3547 InitializeDeltaFile(); | |
| 3548 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3549 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3550 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 3551 } | |
| 3552 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3553 EXPECT_EQ(expected_target_, output_); | |
| 3554 } | |
| 3555 | |
| 3556 // Use the standard file header with the interleaved encoding. Should fail. | |
| 3557 class VCDiffDecoderInterleavedUsedButNotSupported | |
| 3558 : public VCDiffInterleavedDecoderTest { | |
| 3559 public: | |
| 3560 VCDiffDecoderInterleavedUsedButNotSupported() { | |
| 3561 delta_file_header_.assign(kStandardFileHeader, sizeof(kStandardFileHeader)); | |
| 3562 } | |
| 3563 virtual ~VCDiffDecoderInterleavedUsedButNotSupported() { } | |
| 3564 }; | |
| 3565 | |
| 3566 TEST_F(VCDiffDecoderInterleavedUsedButNotSupported, DecodeShouldFail) { | |
| 3567 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3568 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 3569 delta_file_.size(), | |
| 3570 &output_)); | |
| 3571 EXPECT_EQ("", output_); | |
| 3572 } | |
| 3573 | |
| 3574 TEST_F(VCDiffDecoderInterleavedUsedButNotSupported, | |
| 3575 DecodeByteByByteShouldFail) { | |
| 3576 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3577 bool failed = false; | |
| 3578 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3579 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { | |
| 3580 failed = true; | |
| 3581 break; | |
| 3582 } | |
| 3583 } | |
| 3584 EXPECT_TRUE(failed); | |
| 3585 // The decoder should not create more target bytes than were expected. | |
| 3586 EXPECT_GE(expected_target_.size(), output_.size()); | |
| 3587 } | |
| 3588 | |
| 3589 // Divides up the standard encoding into eight separate delta file windows. | |
| 3590 // Each delta instruction appears in its own window. | |
| 3591 class VCDiffStandardWindowDecoderTest : public VCDiffDecoderTest { | |
| 3592 protected: | |
| 3593 VCDiffStandardWindowDecoderTest(); | |
| 3594 virtual ~VCDiffStandardWindowDecoderTest() {} | |
| 3595 | |
| 3596 private: | |
| 3597 static const char kExpectedAnnotatedTarget[]; | |
| 3598 static const char kWindowBody[]; | |
| 3599 }; | |
| 3600 | |
| 3601 const char VCDiffStandardWindowDecoderTest::kWindowBody[] = { | |
| 3602 // Window 1: | |
| 3603 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
| 3604 FirstByteOfStringLength(kDictionary), // Source segment size | |
| 3605 SecondByteOfStringLength(kDictionary), | |
| 3606 0x00, // Source segment position: start of dictionary | |
| 3607 0x08, // Length of the delta encoding | |
| 3608 0x1C, // Size of the target window (28) | |
| 3609 0x00, // Delta_indicator (no compression) | |
| 3610 0x00, // length of data for ADDs and RUNs | |
| 3611 0x02, // length of instructions section | |
| 3612 0x01, // length of addresses for COPYs | |
| 3613 // No data for ADDs and RUNs | |
| 3614 // Instructions and sizes (length 2) | |
| 3615 0x13, // VCD_COPY mode VCD_SELF, size 0 | |
| 3616 0x1C, // Size of COPY (28) | |
| 3617 // Addresses for COPYs (length 1) | |
| 3618 0x00, // Start of dictionary | |
| 3619 // Window 2: | |
| 3620 0x00, // Win_Indicator: No source segment (ADD only) | |
| 3621 0x44, // Length of the delta encoding | |
| 3622 0x3D, // Size of the target window (61) | |
| 3623 0x00, // Delta_indicator (no compression) | |
| 3624 0x3D, // length of data for ADDs and RUNs | |
| 3625 0x02, // length of instructions section | |
| 3626 0x00, // length of addresses for COPYs | |
| 3627 // Data for ADD (length 61) | |
| 3628 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', | |
| 3629 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', | |
| 3630 'T', 'h', 'a', 't', ' ', | |
| 3631 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', | |
| 3632 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', | |
| 3633 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', | |
| 3634 // Instructions and sizes (length 2) | |
| 3635 0x01, // VCD_ADD size 0 | |
| 3636 0x3D, // Size of ADD (61) | |
| 3637 // No addresses for COPYs | |
| 3638 // Window 3: | |
| 3639 VCD_TARGET, // Win_Indicator: take source from decoded data | |
| 3640 0x59, // Source segment size: length of data decoded so far | |
| 3641 0x00, // Source segment position: start of decoded data | |
| 3642 0x08, // Length of the delta encoding | |
| 3643 0x2C, // Size of the target window | |
| 3644 0x00, // Delta_indicator (no compression) | |
| 3645 0x00, // length of data for ADDs and RUNs | |
| 3646 0x02, // length of instructions section | |
| 3647 0x01, // length of addresses for COPYs | |
| 3648 // No data for ADDs and RUNs | |
| 3649 // Instructions and sizes (length 2) | |
| 3650 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
| 3651 0x2C, // Size of COPY (44) | |
| 3652 // Addresses for COPYs (length 1) | |
| 3653 0x58, // HERE mode address (27+61 back from here_address) | |
| 3654 // Window 4: | |
| 3655 VCD_TARGET, // Win_Indicator: take source from decoded data | |
| 3656 0x05, // Source segment size: only 5 bytes needed for this COPY | |
| 3657 0x2E, // Source segment position: offset for COPY | |
| 3658 0x09, // Length of the delta encoding | |
| 3659 0x07, // Size of the target window | |
| 3660 0x00, // Delta_indicator (no compression) | |
| 3661 0x02, // length of data for ADDs and RUNs | |
| 3662 0x01, // length of instructions section | |
| 3663 0x01, // length of addresses for COPYs | |
| 3664 // Data for ADD (length 2) | |
| 3665 'h', 'r', | |
| 3666 // Instructions and sizes (length 1) | |
| 3667 0xA7, // VCD_ADD size 2 + VCD_COPY mode SELF size 5 | |
| 3668 // Addresses for COPYs (length 1) | |
| 3669 0x00, // SELF mode address (start of source segment) | |
| 3670 // Window 5: | |
| 3671 0x00, // Win_Indicator: No source segment (ADD only) | |
| 3672 0x0F, // Length of the delta encoding | |
| 3673 0x09, // Size of the target window | |
| 3674 0x00, // Delta_indicator (no compression) | |
| 3675 0x09, // length of data for ADDs and RUNs | |
| 3676 0x01, // length of instructions section | |
| 3677 0x00, // length of addresses for COPYs | |
| 3678 // Data for ADD (length 9) | |
| 3679 'W', 'h', 'a', 't', ' ', 'I', ' ', 't', 'e', | |
| 3680 // Instructions and sizes (length 1) | |
| 3681 0x0A, // VCD_ADD size 9 | |
| 3682 // No addresses for COPYs | |
| 3683 // Window 6: | |
| 3684 0x00, // Win_Indicator: No source segment (RUN only) | |
| 3685 0x08, // Length of the delta encoding | |
| 3686 0x02, // Size of the target window | |
| 3687 0x00, // Delta_indicator (no compression) | |
| 3688 0x01, // length of data for ADDs and RUNs | |
| 3689 0x02, // length of instructions section | |
| 3690 0x00, // length of addresses for COPYs | |
| 3691 // Data for RUN (length 1) | |
| 3692 'l', | |
| 3693 // Instructions and sizes (length 2) | |
| 3694 0x00, // VCD_RUN size 0 | |
| 3695 0x02, // Size of RUN (2) | |
| 3696 // No addresses for COPYs | |
| 3697 // Window 7: | |
| 3698 0x00, // Win_Indicator: No source segment (ADD only) | |
| 3699 0x22, // Length of the delta encoding | |
| 3700 0x1B, // Size of the target window | |
| 3701 0x00, // Delta_indicator (no compression) | |
| 3702 0x1B, // length of data for ADDs and RUNs | |
| 3703 0x02, // length of instructions section | |
| 3704 0x00, // length of addresses for COPYs | |
| 3705 // Data for ADD: 4th section (length 27) | |
| 3706 ' ', 'y', 'o', 'u', ' ', | |
| 3707 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', | |
| 3708 't', 'r', 'u', 'e', '.', '\"', '\n', | |
| 3709 // Instructions and sizes (length 2) | |
| 3710 0x01, // VCD_ADD size 0 | |
| 3711 0x1B, // Size of ADD (27) | |
| 3712 // No addresses for COPYs | |
| 3713 }; | |
| 3714 | |
| 3715 // The window encoding should produce the same target file as the standard | |
| 3716 // encoding, but the annotated target will be different because some of the | |
| 3717 // <bmatch> tags (copying from the previously decoded data in the current target | |
| 3718 // window) are changed to <dmatch> (copying from the previously decoded data in | |
| 3719 // another target window, which is used as the source window for the current | |
| 3720 // delta window.) | |
| 3721 const char VCDiffStandardWindowDecoderTest::kExpectedAnnotatedTarget[] = | |
| 3722 "<dmatch>\"Just the place for a Snark!</dmatch>" | |
| 3723 "<literal> I have said it twice:\n" | |
| 3724 "That alone should encourage the crew.\n</literal>" | |
| 3725 "<dmatch>Just the place for a Snark! I have said it t</dmatch>" | |
| 3726 "<literal>hr</literal>" | |
| 3727 "<dmatch>ice:\n</dmatch>" | |
| 3728 "<literal>What I te</literal>" | |
| 3729 "<literal>ll</literal>" | |
| 3730 "<literal> you three times is true.\"\n</literal>"; | |
| 3731 | |
| 3732 VCDiffStandardWindowDecoderTest::VCDiffStandardWindowDecoderTest() { | |
| 3733 delta_file_header_.assign(kStandardFileHeader, sizeof(kStandardFileHeader)); | |
| 3734 expected_annotated_target_.assign(kExpectedAnnotatedTarget); | |
| 3735 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
| 3736 } | |
| 3737 | |
| 3738 TEST_F(VCDiffStandardWindowDecoderTest, Decode) { | |
| 3739 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3740 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 3741 delta_file_.size(), | |
| 3742 &output_)); | |
| 3743 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3744 EXPECT_EQ(expected_target_, output_); | |
| 3745 } | |
| 3746 | |
| 3747 // Bug 1287926: If DecodeChunk() stops in the middle of the window header, | |
| 3748 // and the expected size of the current target window is smaller than the | |
| 3749 // cumulative target bytes decoded so far, an underflow occurs and the decoder | |
| 3750 // tries to allocate ~MAX_INT bytes. | |
| 3751 TEST_F(VCDiffStandardWindowDecoderTest, DecodeBreakInFourthWindowHeader) { | |
| 3752 // Parse file header + first two windows. | |
| 3753 const int chunk_1_size = sizeof(kStandardFileHeader) + 83; | |
| 3754 // Parse third window, plus everything up to "Size of the target window" field | |
| 3755 // of fourth window, but do not parse complete header of fourth window. | |
| 3756 const int chunk_2_size = 12 + 5; | |
| 3757 CHECK_EQ(VCD_TARGET, static_cast<unsigned char>(delta_file_[chunk_1_size])); | |
| 3758 CHECK_EQ(0x00, static_cast<int>(delta_file_[chunk_1_size + chunk_2_size])); | |
| 3759 string output_chunk1, output_chunk2, output_chunk3; | |
| 3760 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3761 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], | |
| 3762 chunk_1_size, | |
| 3763 &output_chunk1)); | |
| 3764 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[chunk_1_size], | |
| 3765 chunk_2_size, | |
| 3766 &output_chunk2)); | |
| 3767 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[chunk_1_size + chunk_2_size], | |
| 3768 delta_file_.size() | |
| 3769 - (chunk_1_size + chunk_2_size), | |
| 3770 &output_chunk3)); | |
| 3771 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3772 EXPECT_EQ(expected_target_, output_chunk1 + output_chunk2 + output_chunk3); | |
| 3773 } | |
| 3774 | |
| 3775 TEST_F(VCDiffStandardWindowDecoderTest, DecodeInTwoParts) { | |
| 3776 const size_t delta_file_size = delta_file_.size(); | |
| 3777 for (size_t i = 1; i < delta_file_size; i++) { | |
| 3778 string output_chunk1, output_chunk2; | |
| 3779 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3780 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], | |
| 3781 i, | |
| 3782 &output_chunk1)); | |
| 3783 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], | |
| 3784 delta_file_size - i, | |
| 3785 &output_chunk2)); | |
| 3786 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3787 EXPECT_EQ(expected_target_, output_chunk1 + output_chunk2); | |
| 3788 } | |
| 3789 } | |
| 3790 | |
| 3791 TEST_F(VCDiffStandardWindowDecoderTest, DecodeInThreeParts) { | |
| 3792 const size_t delta_file_size = delta_file_.size(); | |
| 3793 for (size_t i = 1; i < delta_file_size - 1; i++) { | |
| 3794 for (size_t j = i + 1; j < delta_file_size; j++) { | |
| 3795 string output_chunk1, output_chunk2, output_chunk3; | |
| 3796 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3797 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], | |
| 3798 i, | |
| 3799 &output_chunk1)); | |
| 3800 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], | |
| 3801 j - i, | |
| 3802 &output_chunk2)); | |
| 3803 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[j], | |
| 3804 delta_file_size - j, | |
| 3805 &output_chunk3)); | |
| 3806 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3807 EXPECT_EQ(expected_target_, | |
| 3808 output_chunk1 + output_chunk2 + output_chunk3); | |
| 3809 } | |
| 3810 } | |
| 3811 } | |
| 3812 | |
| 3813 typedef VCDiffStandardWindowDecoderTest | |
| 3814 VCDiffStandardWindowDecoderTestByteByByte; | |
| 3815 TEST_F(VCDiffStandardWindowDecoderTestByteByByte, Decode) { | |
| 3816 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3817 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3818 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 3819 } | |
| 3820 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3821 EXPECT_EQ(expected_target_, output_); | |
| 3822 } | |
| 3823 | |
| 3824 // Divides up the interleaved encoding into eight separate delta file windows. | |
| 3825 class VCDiffInterleavedWindowDecoderTest | |
| 3826 : public VCDiffStandardWindowDecoderTest { | |
| 3827 protected: | |
| 3828 VCDiffInterleavedWindowDecoderTest(); | |
| 3829 virtual ~VCDiffInterleavedWindowDecoderTest() {} | |
| 3830 private: | |
| 3831 static const char kWindowBody[]; | |
| 3832 }; | |
| 3833 | |
| 3834 const char VCDiffInterleavedWindowDecoderTest::kWindowBody[] = { | |
| 3835 // Window 1: | |
| 3836 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
| 3837 FirstByteOfStringLength(kDictionary), // Source segment size | |
| 3838 SecondByteOfStringLength(kDictionary), | |
| 3839 0x00, // Source segment position: start of dictionary | |
| 3840 0x08, // Length of the delta encoding | |
| 3841 0x1C, // Size of the target window (28) | |
| 3842 0x00, // Delta_indicator (no compression) | |
| 3843 0x00, // length of data for ADDs and RUNs | |
| 3844 0x03, // length of instructions section | |
| 3845 0x00, // length of addresses for COPYs | |
| 3846 0x13, // VCD_COPY mode VCD_SELF, size 0 | |
| 3847 0x1C, // Size of COPY (28) | |
| 3848 0x00, // Start of dictionary | |
| 3849 // Window 2: | |
| 3850 0x00, // Win_Indicator: No source segment (ADD only) | |
| 3851 0x44, // Length of the delta encoding | |
| 3852 0x3D, // Size of the target window (61) | |
| 3853 0x00, // Delta_indicator (no compression) | |
| 3854 0x00, // length of data for ADDs and RUNs | |
| 3855 0x3F, // length of instructions section | |
| 3856 0x00, // length of addresses for COPYs | |
| 3857 0x01, // VCD_ADD size 0 | |
| 3858 0x3D, // Size of ADD (61) | |
| 3859 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', | |
| 3860 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', | |
| 3861 'T', 'h', 'a', 't', ' ', | |
| 3862 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', | |
| 3863 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', | |
| 3864 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', | |
| 3865 // Window 3: | |
| 3866 VCD_TARGET, // Win_Indicator: take source from decoded data | |
| 3867 0x59, // Source segment size: length of data decoded so far | |
| 3868 0x00, // Source segment position: start of decoded data | |
| 3869 0x08, // Length of the delta encoding | |
| 3870 0x2C, // Size of the target window | |
| 3871 0x00, // Delta_indicator (no compression) | |
| 3872 0x00, // length of data for ADDs and RUNs | |
| 3873 0x03, // length of instructions section | |
| 3874 0x00, // length of addresses for COPYs | |
| 3875 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
| 3876 0x2C, // Size of COPY (44) | |
| 3877 0x58, // HERE mode address (27+61 back from here_address) | |
| 3878 // Window 4: | |
| 3879 VCD_TARGET, // Win_Indicator: take source from decoded data | |
| 3880 0x05, // Source segment size: only 5 bytes needed for this COPY | |
| 3881 0x2E, // Source segment position: offset for COPY | |
| 3882 0x09, // Length of the delta encoding | |
| 3883 0x07, // Size of the target window | |
| 3884 0x00, // Delta_indicator (no compression) | |
| 3885 0x00, // length of data for ADDs and RUNs | |
| 3886 0x04, // length of instructions section | |
| 3887 0x00, // length of addresses for COPYs | |
| 3888 0xA7, // VCD_ADD size 2 + VCD_COPY mode SELF, size 5 | |
| 3889 'h', 'r', | |
| 3890 0x00, // SELF mode address (start of source segment) | |
| 3891 // Window 5: | |
| 3892 0x00, // Win_Indicator: No source segment (ADD only) | |
| 3893 0x0F, // Length of the delta encoding | |
| 3894 0x09, // Size of the target window | |
| 3895 0x00, // Delta_indicator (no compression) | |
| 3896 0x00, // length of data for ADDs and RUNs | |
| 3897 0x0A, // length of instructions section | |
| 3898 0x00, // length of addresses for COPYs | |
| 3899 0x0A, // VCD_ADD size 9 | |
| 3900 'W', 'h', 'a', 't', ' ', 'I', ' ', 't', 'e', | |
| 3901 // Window 6: | |
| 3902 0x00, // Win_Indicator: No source segment (RUN only) | |
| 3903 0x08, // Length of the delta encoding | |
| 3904 0x02, // Size of the target window | |
| 3905 0x00, // Delta_indicator (no compression) | |
| 3906 0x00, // length of data for ADDs and RUNs | |
| 3907 0x03, // length of instructions section | |
| 3908 0x00, // length of addresses for COPYs | |
| 3909 0x00, // VCD_RUN size 0 | |
| 3910 0x02, // Size of RUN (2) | |
| 3911 'l', | |
| 3912 // Window 7: | |
| 3913 0x00, // Win_Indicator: No source segment (ADD only) | |
| 3914 0x22, // Length of the delta encoding | |
| 3915 0x1B, // Size of the target window | |
| 3916 0x00, // Delta_indicator (no compression) | |
| 3917 0x00, // length of data for ADDs and RUNs | |
| 3918 0x1D, // length of instructions section | |
| 3919 0x00, // length of addresses for COPYs | |
| 3920 0x01, // VCD_ADD size 0 | |
| 3921 0x1B, // Size of ADD (27) | |
| 3922 ' ', 'y', 'o', 'u', ' ', | |
| 3923 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', | |
| 3924 't', 'r', 'u', 'e', '.', '\"', '\n', | |
| 3925 }; | |
| 3926 | |
| 3927 VCDiffInterleavedWindowDecoderTest::VCDiffInterleavedWindowDecoderTest() { | |
| 3928 delta_file_header_.assign(kInterleavedFileHeader, | |
| 3929 sizeof(kInterleavedFileHeader)); | |
| 3930 // delta_window_header_ is left blank. All window headers and bodies are | |
| 3931 // lumped together in delta_window_body_. This means that AddChecksum() | |
| 3932 // cannot be used to test the checksum feature. | |
| 3933 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
| 3934 } | |
| 3935 | |
| 3936 TEST_F(VCDiffInterleavedWindowDecoderTest, Decode) { | |
| 3937 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3938 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 3939 delta_file_.size(), | |
| 3940 &output_)); | |
| 3941 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3942 EXPECT_EQ(expected_target_, output_); | |
| 3943 } | |
| 3944 | |
| 3945 TEST_F(VCDiffInterleavedWindowDecoderTest, DecodeInTwoParts) { | |
| 3946 const size_t delta_file_size = delta_file_.size(); | |
| 3947 for (size_t i = 1; i < delta_file_size; i++) { | |
| 3948 string output_chunk1, output_chunk2; | |
| 3949 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3950 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], | |
| 3951 i, | |
| 3952 &output_chunk1)); | |
| 3953 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], | |
| 3954 delta_file_size - i, | |
| 3955 &output_chunk2)); | |
| 3956 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3957 EXPECT_EQ(expected_target_, output_chunk1 + output_chunk2); | |
| 3958 } | |
| 3959 } | |
| 3960 | |
| 3961 TEST_F(VCDiffInterleavedWindowDecoderTest, DecodeInThreeParts) { | |
| 3962 const size_t delta_file_size = delta_file_.size(); | |
| 3963 for (size_t i = 1; i < delta_file_size - 1; i++) { | |
| 3964 for (size_t j = i + 1; j < delta_file_size; j++) { | |
| 3965 string output_chunk1, output_chunk2, output_chunk3; | |
| 3966 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3967 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], | |
| 3968 i, | |
| 3969 &output_chunk1)); | |
| 3970 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], | |
| 3971 j - i, | |
| 3972 &output_chunk2)); | |
| 3973 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[j], | |
| 3974 delta_file_size - j, | |
| 3975 &output_chunk3)); | |
| 3976 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3977 EXPECT_EQ(expected_target_, | |
| 3978 output_chunk1 + output_chunk2 + output_chunk3); | |
| 3979 } | |
| 3980 } | |
| 3981 } | |
| 3982 | |
| 3983 typedef VCDiffInterleavedWindowDecoderTest | |
| 3984 VCDiffInterleavedWindowDecoderTestByteByByte; | |
| 3985 | |
| 3986 TEST_F(VCDiffInterleavedWindowDecoderTestByteByByte, Decode) { | |
| 3987 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 3988 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 3989 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 3990 } | |
| 3991 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 3992 EXPECT_EQ(expected_target_, output_); | |
| 3993 } | |
| 3994 | |
| 3995 // The original version of VCDiffDecoder did not allow the caller to modify the | |
| 3996 // contents of output_string between calls to DecodeChunk(). That restriction | |
| 3997 // has been removed. Verify that the same result is still produced if the | |
| 3998 // output string is cleared after each call to DecodeChunk(). Use the window | |
| 3999 // encoding because it refers back to the previously decoded target data, which | |
| 4000 // is the feature that would fail if the restriction still applied. | |
| 4001 // | |
| 4002 TEST_F(VCDiffInterleavedWindowDecoderTest, OutputStringCanBeModified) { | |
| 4003 string temp_output; | |
| 4004 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4005 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 4006 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &temp_output)); | |
| 4007 output_.append(temp_output); | |
| 4008 temp_output.clear(); | |
| 4009 } | |
| 4010 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4011 EXPECT_EQ(expected_target_, output_); | |
| 4012 } | |
| 4013 | |
| 4014 TEST_F(VCDiffInterleavedWindowDecoderTest, OutputStringIsPreserved) { | |
| 4015 const string previous_data("Previous data"); | |
| 4016 output_ = previous_data; | |
| 4017 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4018 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 4019 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 4020 } | |
| 4021 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4022 EXPECT_EQ(previous_data + expected_target_, output_); | |
| 4023 } | |
| 4024 | |
| 4025 // A decode job that tests the ability to COPY across the boundary between | |
| 4026 // source data and target data. | |
| 4027 class VCDiffStandardCrossDecoderTest : public VCDiffDecoderTest { | |
| 4028 protected: | |
| 4029 static const char kExpectedTarget[]; | |
| 4030 static const char kExpectedAnnotatedTarget[]; | |
| 4031 static const char kWindowHeader[]; | |
| 4032 static const char kWindowBody[]; | |
| 4033 | |
| 4034 VCDiffStandardCrossDecoderTest(); | |
| 4035 virtual ~VCDiffStandardCrossDecoderTest() {} | |
| 4036 }; | |
| 4037 | |
| 4038 const char VCDiffStandardCrossDecoderTest::kWindowHeader[] = { | |
| 4039 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
| 4040 FirstByteOfStringLength(kDictionary), // Source segment size | |
| 4041 SecondByteOfStringLength(kDictionary), | |
| 4042 0x00, // Source segment position: start of dictionary | |
| 4043 0x15, // Length of the delta encoding | |
| 4044 StringLengthAsByte(kExpectedTarget), // Size of the target window | |
| 4045 0x00, // Delta_indicator (no compression) | |
| 4046 0x07, // length of data for ADDs and RUNs | |
| 4047 0x06, // length of instructions section | |
| 4048 0x03 // length of addresses for COPYs | |
| 4049 }; | |
| 4050 | |
| 4051 const char VCDiffStandardCrossDecoderTest::kWindowBody[] = { | |
| 4052 // Data for ADD (length 7) | |
| 4053 'S', 'p', 'i', 'd', 'e', 'r', 's', | |
| 4054 // Instructions and sizes (length 6) | |
| 4055 0x01, // VCD_ADD size 0 | |
| 4056 0x07, // Size of ADD (7) | |
| 4057 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
| 4058 0x19, // Size of COPY (25) | |
| 4059 0x14, // VCD_COPY mode VCD_SELF, size 4 | |
| 4060 0x25, // VCD_COPY mode VCD_HERE, size 5 | |
| 4061 // Addresses for COPYs (length 3) | |
| 4062 0x15, // HERE mode address for 1st copy (21 back from here_address) | |
| 4063 0x06, // SELF mode address for 2nd copy | |
| 4064 0x14 // HERE mode address for 3rd copy | |
| 4065 }; | |
| 4066 | |
| 4067 const char VCDiffStandardCrossDecoderTest::kExpectedTarget[] = | |
| 4068 "Spiders in his hair.\n" | |
| 4069 "Spiders in the air.\n"; | |
| 4070 | |
| 4071 const char VCDiffStandardCrossDecoderTest::kExpectedAnnotatedTarget[] = | |
| 4072 "<literal>Spiders</literal>" | |
| 4073 "<dmatch> in his hair.\n</dmatch>" // crosses source-target boundary | |
| 4074 "<bmatch>Spiders in </bmatch>" | |
| 4075 "<dmatch>the </dmatch>" | |
| 4076 "<bmatch>air.\n</bmatch>"; | |
| 4077 | |
| 4078 VCDiffStandardCrossDecoderTest::VCDiffStandardCrossDecoderTest() { | |
| 4079 delta_file_header_.assign(kStandardFileHeader, sizeof(kStandardFileHeader)); | |
| 4080 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); | |
| 4081 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
| 4082 expected_target_.assign(kExpectedTarget); | |
| 4083 expected_annotated_target_.assign(kExpectedAnnotatedTarget); | |
| 4084 } | |
| 4085 | |
| 4086 TEST_F(VCDiffStandardCrossDecoderTest, Decode) { | |
| 4087 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4088 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 4089 delta_file_.size(), | |
| 4090 &output_)); | |
| 4091 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4092 EXPECT_EQ(expected_target_, output_); | |
| 4093 } | |
| 4094 | |
| 4095 typedef VCDiffStandardCrossDecoderTest VCDiffStandardCrossDecoderTestByteByByte; | |
| 4096 | |
| 4097 TEST_F(VCDiffStandardCrossDecoderTestByteByByte, Decode) { | |
| 4098 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4099 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 4100 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 4101 } | |
| 4102 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4103 EXPECT_EQ(expected_target_, output_); | |
| 4104 } | |
| 4105 | |
| 4106 // The same decode job that tests the ability to COPY across the boundary | |
| 4107 // between source data and target data, but using the interleaved format rather | |
| 4108 // than the standard format. | |
| 4109 class VCDiffInterleavedCrossDecoderTest | |
| 4110 : public VCDiffStandardCrossDecoderTest { | |
| 4111 protected: | |
| 4112 VCDiffInterleavedCrossDecoderTest(); | |
| 4113 virtual ~VCDiffInterleavedCrossDecoderTest() {} | |
| 4114 | |
| 4115 private: | |
| 4116 static const char kWindowHeader[]; | |
| 4117 static const char kWindowBody[]; | |
| 4118 }; | |
| 4119 | |
| 4120 const char VCDiffInterleavedCrossDecoderTest::kWindowHeader[] = { | |
| 4121 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
| 4122 FirstByteOfStringLength(kDictionary), // Source segment size | |
| 4123 SecondByteOfStringLength(kDictionary), | |
| 4124 0x00, // Source segment position: start of dictionary | |
| 4125 0x15, // Length of the delta encoding | |
| 4126 StringLengthAsByte(kExpectedTarget), // Size of the target window | |
| 4127 0x00, // Delta_indicator (no compression) | |
| 4128 0x00, // length of data for ADDs and RUNs | |
| 4129 0x10, // length of instructions section | |
| 4130 0x00, // length of addresses for COPYs | |
| 4131 }; | |
| 4132 | |
| 4133 const char VCDiffInterleavedCrossDecoderTest::kWindowBody[] = { | |
| 4134 0x01, // VCD_ADD size 0 | |
| 4135 0x07, // Size of ADD (7) | |
| 4136 // Data for ADD (length 7) | |
| 4137 'S', 'p', 'i', 'd', 'e', 'r', 's', | |
| 4138 0x23, // VCD_COPY mode VCD_HERE, size 0 | |
| 4139 0x19, // Size of COPY (25) | |
| 4140 0x15, // HERE mode address for 1st copy (21 back from here_address) | |
| 4141 0x14, // VCD_COPY mode VCD_SELF, size 4 | |
| 4142 0x06, // SELF mode address for 2nd copy | |
| 4143 0x25, // VCD_COPY mode VCD_HERE, size 5 | |
| 4144 0x14 // HERE mode address for 3rd copy | |
| 4145 }; | |
| 4146 | |
| 4147 VCDiffInterleavedCrossDecoderTest::VCDiffInterleavedCrossDecoderTest() { | |
| 4148 delta_file_header_.assign(kInterleavedFileHeader, | |
| 4149 sizeof(kInterleavedFileHeader)); | |
| 4150 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); | |
| 4151 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
| 4152 } | |
| 4153 | |
| 4154 TEST_F(VCDiffInterleavedCrossDecoderTest, Decode) { | |
| 4155 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4156 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 4157 delta_file_.size(), | |
| 4158 &output_)); | |
| 4159 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4160 EXPECT_EQ(expected_target_, output_); | |
| 4161 } | |
| 4162 | |
| 4163 TEST_F(VCDiffInterleavedCrossDecoderTest, DecodeWithChecksum) { | |
| 4164 ComputeAndAddChecksum(); | |
| 4165 InitializeDeltaFile(); | |
| 4166 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4167 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 4168 delta_file_.size(), | |
| 4169 &output_)); | |
| 4170 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4171 EXPECT_EQ(expected_target_, output_); | |
| 4172 } | |
| 4173 | |
| 4174 typedef VCDiffInterleavedCrossDecoderTest | |
| 4175 VCDiffInterleavedCrossDecoderTestByteByByte; | |
| 4176 | |
| 4177 TEST_F(VCDiffInterleavedCrossDecoderTestByteByByte, Decode) { | |
| 4178 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4179 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 4180 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 4181 } | |
| 4182 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4183 EXPECT_EQ(expected_target_, output_); | |
| 4184 } | |
| 4185 | |
| 4186 TEST_F(VCDiffInterleavedCrossDecoderTestByteByByte, DecodeWithChecksum) { | |
| 4187 ComputeAndAddChecksum(); | |
| 4188 InitializeDeltaFile(); | |
| 4189 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4190 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 4191 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 4192 } | |
| 4193 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4194 EXPECT_EQ(expected_target_, output_); | |
| 4195 } | |
| 4196 | |
| 4197 // Test using a custom code table and custom cache sizes with interleaved | |
| 4198 // format. | |
| 4199 class VCDiffCustomCodeTableDecoderTest : public VCDiffInterleavedDecoderTest { | |
| 4200 protected: | |
| 4201 static const char kFileHeader[]; | |
| 4202 static const char kWindowHeader[]; | |
| 4203 static const char kWindowBody[]; | |
| 4204 static const char kEncodedCustomCodeTable[]; | |
| 4205 | |
| 4206 VCDiffCustomCodeTableDecoderTest(); | |
| 4207 virtual ~VCDiffCustomCodeTableDecoderTest() {} | |
| 4208 }; | |
| 4209 | |
| 4210 const char VCDiffCustomCodeTableDecoderTest::kFileHeader[] = { | |
| 4211 0xD6, // 'V' | 0x80 | |
| 4212 0xC3, // 'C' | 0x80 | |
| 4213 0xC4, // 'D' | 0x80 | |
| 4214 'S', // SDCH version code | |
| 4215 0x02 // Hdr_Indicator: Use custom code table | |
| 4216 }; | |
| 4217 | |
| 4218 // Make a custom code table that includes exactly the instructions we need | |
| 4219 // to encode the first test's data without using any explicit length values. | |
| 4220 // Be careful not to replace any existing opcodes that have size 0, | |
| 4221 // to ensure that the custom code table is valid (can express all possible | |
| 4222 // values of inst (also known as instruction type) and mode with size 0.) | |
| 4223 // This encoding uses interleaved format, which is easier to read. | |
| 4224 // | |
| 4225 // Here are the changes to the standard code table: | |
| 4226 // ADD size 2 (opcode 3) => RUN size 2 (inst1[3] = VCD_RUN) | |
| 4227 // ADD size 16 (opcode 17) => ADD size 27 (size1[17] = 27) | |
| 4228 // ADD size 17 (opcode 18) => ADD size 61 (size1[18] = 61) | |
| 4229 // COPY mode 0 size 18 (opcode 34) => COPY mode 0 size 28 (size1[34] = 28) | |
| 4230 // COPY mode 1 size 18 (opcode 50) => COPY mode 1 size 44 (size1[50] = 44) | |
| 4231 // | |
| 4232 const char VCDiffCustomCodeTableDecoderTest::kEncodedCustomCodeTable[] = { | |
| 4233 0xD6, // 'V' | 0x80 | |
| 4234 0xC3, // 'C' | 0x80 | |
| 4235 0xC4, // 'D' | 0x80 | |
| 4236 'S', // SDCH version code | |
| 4237 0x00, // Hdr_Indicator: no custom code table, no compression | |
| 4238 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
| 4239 (sizeof(VCDiffCodeTableData) >> 7) | 0x80, // First byte of table length | |
| 4240 sizeof(VCDiffCodeTableData) & 0x7F, // Second byte of table length | |
| 4241 0x00, // Source segment position: start of default code table | |
| 4242 0x1F, // Length of the delta encoding | |
| 4243 (sizeof(VCDiffCodeTableData) >> 7) | 0x80, // First byte of table length | |
| 4244 sizeof(VCDiffCodeTableData) & 0x7F, // Second byte of table length | |
| 4245 0x00, // Delta_indicator (no compression) | |
| 4246 0x00, // length of data for ADDs and RUNs (unused) | |
| 4247 0x19, // length of interleaved section | |
| 4248 0x00, // length of addresses for COPYs (unused) | |
| 4249 0x05, // VCD_ADD size 4 | |
| 4250 // Data for ADD (length 4) | |
| 4251 VCD_RUN, VCD_ADD, VCD_ADD, VCD_RUN, | |
| 4252 0x13, // VCD_COPY mode VCD_SELF size 0 | |
| 4253 0x84, // Size of copy: upper bits (512 - 4 + 17 = 525) | |
| 4254 0x0D, // Size of copy: lower bits | |
| 4255 0x04, // Address of COPY | |
| 4256 0x03, // VCD_ADD size 2 | |
| 4257 // Data for ADD (length 2) | |
| 4258 0x1B, 0x3D, | |
| 4259 0x3F, // VCD_COPY mode VCD_NEAR(0) size 15 | |
| 4260 0x84, // Address of copy: upper bits (525 + 2 = 527) | |
| 4261 0x0F, // Address of copy: lower bits | |
| 4262 0x02, // VCD_ADD size 1 | |
| 4263 // Data for ADD (length 1) | |
| 4264 0x1C, | |
| 4265 0x4F, // VCD_COPY mode VCD_NEAR(1) size 15 | |
| 4266 0x10, // Address of copy | |
| 4267 0x02, // VCD_ADD size 1 | |
| 4268 // Data for ADD (length 1) | |
| 4269 0x2C, | |
| 4270 0x53, // VCD_COPY mode VCD_NEAR(2) size 0 | |
| 4271 0x87, // Size of copy: upper bits (256 * 4 - 51 = 973) | |
| 4272 0x4D, // Size of copy: lower bits | |
| 4273 0x10 // Address of copy | |
| 4274 }; | |
| 4275 | |
| 4276 // This is similar to VCDiffInterleavedDecoderTest, but uses the custom code | |
| 4277 // table to eliminate the need to explicitly encode instruction sizes. | |
| 4278 // Notice that NEAR(0) mode is used here where NEAR(1) mode was used in | |
| 4279 // VCDiffInterleavedDecoderTest. This is because the custom code table | |
| 4280 // has the size of the NEAR cache set to 1; only the most recent | |
| 4281 // COPY instruction is available. This will also be a test of | |
| 4282 // custom cache sizes. | |
| 4283 const char VCDiffCustomCodeTableDecoderTest::kWindowHeader[] = { | |
| 4284 VCD_SOURCE, // Win_Indicator: take source from dictionary | |
| 4285 FirstByteOfStringLength(kDictionary), // Source segment size | |
| 4286 SecondByteOfStringLength(kDictionary), | |
| 4287 0x00, // Source segment position: start of dictionary | |
| 4288 0x74, // Length of the delta encoding | |
| 4289 FirstByteOfStringLength(kExpectedTarget), // Size of the target window | |
| 4290 SecondByteOfStringLength(kExpectedTarget), | |
| 4291 0x00, // Delta_indicator (no compression) | |
| 4292 0x00, // length of data for ADDs and RUNs (unused) | |
| 4293 0x6E, // length of interleaved section | |
| 4294 0x00 // length of addresses for COPYs (unused) | |
| 4295 }; | |
| 4296 | |
| 4297 const char VCDiffCustomCodeTableDecoderTest::kWindowBody[] = { | |
| 4298 0x22, // VCD_COPY mode VCD_SELF, size 28 | |
| 4299 0x00, // Address of COPY: Start of dictionary | |
| 4300 0x12, // VCD_ADD size 61 | |
| 4301 // Data for ADD (length 61) | |
| 4302 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', | |
| 4303 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', | |
| 4304 'T', 'h', 'a', 't', ' ', | |
| 4305 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', | |
| 4306 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', | |
| 4307 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', | |
| 4308 0x32, // VCD_COPY mode VCD_HERE, size 44 | |
| 4309 0x58, // HERE mode address (27+61 back from here_address) | |
| 4310 0xBF, // VCD_ADD size 2 + VCD_COPY mode NEAR(0), size 5 | |
| 4311 // Data for ADDs: 2nd section (length 2) | |
| 4312 'h', 'r', | |
| 4313 0x2D, // NEAR(0) mode address (45 after prior address) | |
| 4314 0x0A, // VCD_ADD size 9 | |
| 4315 // Data for ADDs: 3rd section (length 9) | |
| 4316 'W', 'h', 'a', 't', ' ', | |
| 4317 'I', ' ', 't', 'e', | |
| 4318 0x03, // VCD_RUN size 2 | |
| 4319 // Data for RUN: 4th section (length 1) | |
| 4320 'l', | |
| 4321 0x11, // VCD_ADD size 27 | |
| 4322 // Data for ADD: 4th section (length 27) | |
| 4323 ' ', 'y', 'o', 'u', ' ', | |
| 4324 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', | |
| 4325 't', 'r', 'u', 'e', '.', '\"', '\n' | |
| 4326 }; | |
| 4327 | |
| 4328 VCDiffCustomCodeTableDecoderTest::VCDiffCustomCodeTableDecoderTest() { | |
| 4329 delta_file_header_.assign(kFileHeader, sizeof(kFileHeader)); | |
| 4330 delta_file_header_.push_back(0x01); // NEAR cache size (custom) | |
| 4331 delta_file_header_.push_back(0x06); // SAME cache size (custom) | |
| 4332 delta_file_header_.append(kEncodedCustomCodeTable, | |
| 4333 sizeof(kEncodedCustomCodeTable)); | |
| 4334 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); | |
| 4335 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); | |
| 4336 } | |
| 4337 | |
| 4338 TEST_F(VCDiffCustomCodeTableDecoderTest, CustomCodeTableEncodingMatches) { | |
| 4339 VCDiffCodeTableData custom_code_table( | |
| 4340 VCDiffCodeTableData::kDefaultCodeTableData); | |
| 4341 custom_code_table.inst1[3] = VCD_RUN; | |
| 4342 custom_code_table.size1[17] = 27; | |
| 4343 custom_code_table.size1[18] = 61; | |
| 4344 custom_code_table.size1[34] = 28; | |
| 4345 custom_code_table.size1[50] = 44; | |
| 4346 | |
| 4347 decoder_.StartDecoding( | |
| 4348 reinterpret_cast<const char*>( | |
| 4349 &VCDiffCodeTableData::kDefaultCodeTableData), | |
| 4350 sizeof(VCDiffCodeTableData::kDefaultCodeTableData)); | |
| 4351 EXPECT_TRUE(decoder_.DecodeChunk(kEncodedCustomCodeTable, | |
| 4352 sizeof(kEncodedCustomCodeTable), | |
| 4353 &output_)); | |
| 4354 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4355 EXPECT_EQ(sizeof(custom_code_table), output_.size()); | |
| 4356 const VCDiffCodeTableData* decoded_table = | |
| 4357 reinterpret_cast<const VCDiffCodeTableData*>(output_.data()); | |
| 4358 EXPECT_EQ(VCD_RUN, decoded_table->inst1[0]); | |
| 4359 EXPECT_EQ(VCD_RUN, decoded_table->inst1[3]); | |
| 4360 EXPECT_EQ(27, decoded_table->size1[17]); | |
| 4361 EXPECT_EQ(61, decoded_table->size1[18]); | |
| 4362 EXPECT_EQ(28, decoded_table->size1[34]); | |
| 4363 EXPECT_EQ(44, decoded_table->size1[50]); | |
| 4364 for (int i = 0; i < VCDiffCodeTableData::kCodeTableSize; ++i) { | |
| 4365 EXPECT_EQ(custom_code_table.inst1[i], decoded_table->inst1[i]); | |
| 4366 EXPECT_EQ(custom_code_table.inst2[i], decoded_table->inst2[i]); | |
| 4367 EXPECT_EQ(custom_code_table.size1[i], decoded_table->size1[i]); | |
| 4368 EXPECT_EQ(custom_code_table.size2[i], decoded_table->size2[i]); | |
| 4369 EXPECT_EQ(custom_code_table.mode1[i], decoded_table->mode1[i]); | |
| 4370 EXPECT_EQ(custom_code_table.mode2[i], decoded_table->mode2[i]); | |
| 4371 } | |
| 4372 } | |
| 4373 | |
| 4374 TEST_F(VCDiffCustomCodeTableDecoderTest, DecodeUsingCustomCodeTable) { | |
| 4375 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4376 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), | |
| 4377 delta_file_.size(), | |
| 4378 &output_)); | |
| 4379 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4380 EXPECT_EQ(expected_target_, output_); | |
| 4381 } | |
| 4382 | |
| 4383 TEST_F(VCDiffCustomCodeTableDecoderTest, IncompleteCustomCodeTable) { | |
| 4384 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4385 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), | |
| 4386 delta_file_header_.size() - 1, | |
| 4387 &output_)); | |
| 4388 EXPECT_FALSE(decoder_.FinishDecoding()); | |
| 4389 EXPECT_EQ("", output_); | |
| 4390 } | |
| 4391 | |
| 4392 typedef VCDiffCustomCodeTableDecoderTest | |
| 4393 VCDiffCustomCodeTableDecoderTestByteByByte; | |
| 4394 | |
| 4395 TEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, DecodeUsingCustomCodeTable) { | |
| 4396 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4397 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 4398 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 4399 } | |
| 4400 EXPECT_TRUE(decoder_.FinishDecoding()); | |
| 4401 EXPECT_EQ(expected_target_, output_); | |
| 4402 } | |
| 4403 | |
| 4404 TEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, IncompleteCustomCodeTable) { | |
| 4405 delta_file_.resize(delta_file_header_.size() - 1); | |
| 4406 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4407 for (size_t i = 0; i < delta_file_.size(); ++i) { | |
| 4408 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); | |
| 4409 } | |
| 4410 EXPECT_FALSE(decoder_.FinishDecoding()); | |
| 4411 EXPECT_EQ("", output_); | |
| 4412 } | |
| 4413 | |
| 4414 #ifdef GTEST_HAS_DEATH_TEST | |
| 4415 typedef VCDiffCustomCodeTableDecoderTest VCDiffCustomCodeTableDecoderDeathTest; | |
| 4416 | |
| 4417 TEST_F(VCDiffCustomCodeTableDecoderDeathTest, BadCustomCacheSizes) { | |
| 4418 delta_file_header_.assign(kFileHeader, sizeof(kFileHeader)); | |
| 4419 delta_file_header_.push_back(0x81); // NEAR cache size (top bit) | |
| 4420 delta_file_header_.push_back(0x10); // NEAR cache size (custom value 0x90) | |
| 4421 delta_file_header_.push_back(0x81); // SAME cache size (top bit) | |
| 4422 delta_file_header_.push_back(0x10); // SAME cache size (custom value 0x90) | |
| 4423 delta_file_header_.append(kEncodedCustomCodeTable, | |
| 4424 sizeof(kEncodedCustomCodeTable)); | |
| 4425 InitializeDeltaFile(); | |
| 4426 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); | |
| 4427 EXPECT_DEBUG_DEATH(EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), | |
| 4428 delta_file_.size(), | |
| 4429 &output_)), | |
| 4430 "cache"); | |
| 4431 EXPECT_EQ("", output_); | |
| 4432 } | |
| 4433 #endif // GTEST_HAS_DEATH_TEST | |
| 4434 | |
| 4435 } // namespace open_vcdiff | |
| 4436 } // unnamed namespace | |
| OLD | NEW |