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 <string> 19 #include "codetable.h" 20 #include "testing.h" 21 #include "vcdecoder_test.h" 22 #include "vcdiff_defs.h" // VCD_SOURCE 23 24 namespace open_vcdiff { 25 namespace { 26 27 // Use the interleaved file header with the standard encoding. Should work. 28 class VCDiffDecoderInterleavedAllowedButNotUsed 29 : public VCDiffStandardDecoderTest { 30 public: 31 VCDiffDecoderInterleavedAllowedButNotUsed() { 32 UseInterleavedFileHeader(); 33 } 34 virtual ~VCDiffDecoderInterleavedAllowedButNotUsed() { } 35 }; 36 37 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsed, Decode) { 38 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 39 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), 40 delta_file_.size(), 41 &output_)); 42 EXPECT_TRUE(decoder_.FinishDecoding()); 43 EXPECT_EQ(expected_target_.c_str(), output_); 44 } 45 46 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsed, DecodeWithChecksum) { 47 ComputeAndAddChecksum(); 48 InitializeDeltaFile(); 49 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 50 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), 51 delta_file_.size(), 52 &output_)); 53 EXPECT_TRUE(decoder_.FinishDecoding()); 54 EXPECT_EQ(expected_target_.c_str(), output_); 55 } 56 57 typedef VCDiffDecoderInterleavedAllowedButNotUsed 58 VCDiffDecoderInterleavedAllowedButNotUsedByteByByte; 59 60 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsedByteByByte, Decode) { 61 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 62 for (size_t i = 0; i < delta_file_.size(); ++i) { 63 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 64 } 65 EXPECT_TRUE(decoder_.FinishDecoding()); 66 EXPECT_EQ(expected_target_.c_str(), output_); 67 } 68 69 TEST_F(VCDiffDecoderInterleavedAllowedButNotUsedByteByByte, 70 DecodeWithChecksum) { 71 ComputeAndAddChecksum(); 72 InitializeDeltaFile(); 73 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 74 for (size_t i = 0; i < delta_file_.size(); ++i) { 75 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 76 } 77 EXPECT_TRUE(decoder_.FinishDecoding()); 78 EXPECT_EQ(expected_target_.c_str(), output_); 79 } 80 81 // Use the standard file header with the interleaved encoding. Should fail. 82 class VCDiffDecoderInterleavedUsedButNotSupported 83 : public VCDiffInterleavedDecoderTest { 84 public: 85 VCDiffDecoderInterleavedUsedButNotSupported() { 86 UseStandardFileHeader(); 87 } 88 virtual ~VCDiffDecoderInterleavedUsedButNotSupported() { } 89 }; 90 91 TEST_F(VCDiffDecoderInterleavedUsedButNotSupported, DecodeShouldFail) { 92 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 93 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), 94 delta_file_.size(), 95 &output_)); 96 EXPECT_EQ("", output_); 97 } 98 99 TEST_F(VCDiffDecoderInterleavedUsedButNotSupported, 100 DecodeByteByByteShouldFail) { 101 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 102 bool failed = false; 103 for (size_t i = 0; i < delta_file_.size(); ++i) { 104 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { 105 failed = true; 106 break; 107 } 108 } 109 EXPECT_TRUE(failed); 110 // The decoder should not create more target bytes than were expected. 111 EXPECT_GE(expected_target_.size(), output_.size()); 112 } 113 114 // Divides up the standard encoding into eight separate delta file windows. 115 // Each delta instruction appears in its own window. 116 class VCDiffStandardWindowDecoderTest : public VCDiffDecoderTest { 117 protected: 118 static const size_t kWindow2Size = 61; 119 120 VCDiffStandardWindowDecoderTest(); 121 virtual ~VCDiffStandardWindowDecoderTest() {} 122 123 private: 124 static const char kWindowBody[]; 125 }; 126 127 const size_t VCDiffStandardWindowDecoderTest::kWindow2Size; 128 129 const char VCDiffStandardWindowDecoderTest::kWindowBody[] = { 130 // Window 1: 131 VCD_SOURCE, // Win_Indicator: take source from dictionary 132 FirstByteOfStringLength(kDictionary), // Source segment size 133 SecondByteOfStringLength(kDictionary), 134 0x00, // Source segment position: start of dictionary 135 0x08, // Length of the delta encoding 136 0x1C, // Size of the target window (28) 137 0x00, // Delta_indicator (no compression) 138 0x00, // length of data for ADDs and RUNs 139 0x02, // length of instructions section 140 0x01, // length of addresses for COPYs 141 // No data for ADDs and RUNs 142 // Instructions and sizes (length 2) 143 0x13, // VCD_COPY mode VCD_SELF, size 0 144 0x1C, // Size of COPY (28) 145 // Addresses for COPYs (length 1) 146 0x00, // Start of dictionary 147 // Window 2: 148 0x00, // Win_Indicator: No source segment (ADD only) 149 0x44, // Length of the delta encoding 150 static_cast<char>(kWindow2Size), // Size of the target window (61) 151 0x00, // Delta_indicator (no compression) 152 0x3D, // length of data for ADDs and RUNs 153 0x02, // length of instructions section 154 0x00, // length of addresses for COPYs 155 // Data for ADD (length 61) 156 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', 157 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', 158 'T', 'h', 'a', 't', ' ', 159 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', 160 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', 161 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', 162 // Instructions and sizes (length 2) 163 0x01, // VCD_ADD size 0 164 0x3D, // Size of ADD (61) 165 // No addresses for COPYs 166 // Window 3: 167 VCD_TARGET, // Win_Indicator: take source from decoded data 168 0x59, // Source segment size: length of data decoded so far 169 0x00, // Source segment position: start of decoded data 170 0x08, // Length of the delta encoding 171 0x2C, // Size of the target window 172 0x00, // Delta_indicator (no compression) 173 0x00, // length of data for ADDs and RUNs 174 0x02, // length of instructions section 175 0x01, // length of addresses for COPYs 176 // No data for ADDs and RUNs 177 // Instructions and sizes (length 2) 178 0x23, // VCD_COPY mode VCD_HERE, size 0 179 0x2C, // Size of COPY (44) 180 // Addresses for COPYs (length 1) 181 0x58, // HERE mode address (27+61 back from here_address) 182 // Window 4: 183 VCD_TARGET, // Win_Indicator: take source from decoded data 184 0x05, // Source segment size: only 5 bytes needed for this COPY 185 0x2E, // Source segment position: offset for COPY 186 0x09, // Length of the delta encoding 187 0x07, // Size of the target window 188 0x00, // Delta_indicator (no compression) 189 0x02, // length of data for ADDs and RUNs 190 0x01, // length of instructions section 191 0x01, // length of addresses for COPYs 192 // Data for ADD (length 2) 193 'h', 'r', 194 // Instructions and sizes (length 1) 195 0xA7, // VCD_ADD size 2 + VCD_COPY mode SELF size 5 196 // Addresses for COPYs (length 1) 197 0x00, // SELF mode address (start of source segment) 198 // Window 5: 199 0x00, // Win_Indicator: No source segment (ADD only) 200 0x0F, // Length of the delta encoding 201 0x09, // Size of the target window 202 0x00, // Delta_indicator (no compression) 203 0x09, // length of data for ADDs and RUNs 204 0x01, // length of instructions section 205 0x00, // length of addresses for COPYs 206 // Data for ADD (length 9) 207 'W', 'h', 'a', 't', ' ', 'I', ' ', 't', 'e', 208 // Instructions and sizes (length 1) 209 0x0A, // VCD_ADD size 9 210 // No addresses for COPYs 211 // Window 6: 212 0x00, // Win_Indicator: No source segment (RUN only) 213 0x08, // Length of the delta encoding 214 0x02, // Size of the target window 215 0x00, // Delta_indicator (no compression) 216 0x01, // length of data for ADDs and RUNs 217 0x02, // length of instructions section 218 0x00, // length of addresses for COPYs 219 // Data for RUN (length 1) 220 'l', 221 // Instructions and sizes (length 2) 222 0x00, // VCD_RUN size 0 223 0x02, // Size of RUN (2) 224 // No addresses for COPYs 225 // Window 7: 226 0x00, // Win_Indicator: No source segment (ADD only) 227 0x22, // Length of the delta encoding 228 0x1B, // Size of the target window 229 0x00, // Delta_indicator (no compression) 230 0x1B, // length of data for ADDs and RUNs 231 0x02, // length of instructions section 232 0x00, // length of addresses for COPYs 233 // Data for ADD: 4th section (length 27) 234 ' ', 'y', 'o', 'u', ' ', 235 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', 236 't', 'r', 'u', 'e', '.', '\"', '\n', 237 // Instructions and sizes (length 2) 238 0x01, // VCD_ADD size 0 239 0x1B, // Size of ADD (27) 240 // No addresses for COPYs 241 }; 242 243 VCDiffStandardWindowDecoderTest::VCDiffStandardWindowDecoderTest() { 244 UseStandardFileHeader(); 245 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); 246 } 247 248 TEST_F(VCDiffStandardWindowDecoderTest, Decode) { 249 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 250 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), 251 delta_file_.size(), 252 &output_)); 253 EXPECT_TRUE(decoder_.FinishDecoding()); 254 EXPECT_EQ(expected_target_.c_str(), output_); 255 } 256 257 // Bug 1287926: If DecodeChunk() stops in the middle of the window header, 258 // and the expected size of the current target window is smaller than the 259 // cumulative target bytes decoded so far, an underflow occurs and the decoder 260 // tries to allocate ~MAX_INT bytes. 261 TEST_F(VCDiffStandardWindowDecoderTest, DecodeBreakInFourthWindowHeader) { 262 // Parse file header + first two windows. 263 const size_t chunk_1_size = delta_file_header_.size() + 83; 264 // Parse third window, plus everything up to "Size of the target window" field 265 // of fourth window, but do not parse complete header of fourth window. 266 const size_t chunk_2_size = 12 + 5; 267 CHECK_EQ(VCD_TARGET, static_cast<unsigned char>(delta_file_[chunk_1_size])); 268 CHECK_EQ(0x00, static_cast<int>(delta_file_[chunk_1_size + chunk_2_size])); 269 string output_chunk1, output_chunk2, output_chunk3; 270 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 271 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], 272 chunk_1_size, 273 &output_chunk1)); 274 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[chunk_1_size], 275 chunk_2_size, 276 &output_chunk2)); 277 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[chunk_1_size + chunk_2_size], 278 delta_file_.size() 279 - (chunk_1_size + chunk_2_size), 280 &output_chunk3)); 281 EXPECT_TRUE(decoder_.FinishDecoding()); 282 EXPECT_EQ(expected_target_.c_str(), 283 output_chunk1 + output_chunk2 + output_chunk3); 284 } 285 286 TEST_F(VCDiffStandardWindowDecoderTest, DecodeChunkNoVcdTargetAllowed) { 287 decoder_.SetAllowVcdTarget(false); 288 // Parse file header + first two windows. 289 const size_t chunk_1_size = delta_file_header_.size() + 83; 290 // The third window begins with Win_Indicator = VCD_TARGET which is not 291 // allowed. 292 CHECK_EQ(VCD_TARGET, static_cast<unsigned char>(delta_file_[chunk_1_size])); 293 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 294 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], chunk_1_size, &output_)); 295 // Just parsing one more byte (the VCD_TARGET) should result in an error. 296 EXPECT_FALSE(decoder_.DecodeChunk(&delta_file_[chunk_1_size], 1, &output_)); 297 // The target data for the first two windows should have been output. 298 EXPECT_EQ(expected_target_.substr(0, 89).c_str(), output_); 299 } 300 301 TEST_F(VCDiffStandardWindowDecoderTest, DecodeInTwoParts) { 302 const size_t delta_file_size = delta_file_.size(); 303 for (size_t i = 1; i < delta_file_size; i++) { 304 string output_chunk1, output_chunk2; 305 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 306 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], 307 i, 308 &output_chunk1)); 309 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 310 delta_file_size - i, 311 &output_chunk2)); 312 EXPECT_TRUE(decoder_.FinishDecoding()); 313 EXPECT_EQ(expected_target_.c_str(), output_chunk1 + output_chunk2); 314 } 315 } 316 317 TEST_F(VCDiffStandardWindowDecoderTest, DecodeInThreeParts) { 318 const size_t delta_file_size = delta_file_.size(); 319 for (size_t i = 1; i < delta_file_size - 1; i++) { 320 for (size_t j = i + 1; j < delta_file_size; j++) { 321 string output_chunk1, output_chunk2, output_chunk3; 322 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 323 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], 324 i, 325 &output_chunk1)); 326 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 327 j - i, 328 &output_chunk2)); 329 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[j], 330 delta_file_size - j, 331 &output_chunk3)); 332 EXPECT_TRUE(decoder_.FinishDecoding()); 333 EXPECT_EQ(expected_target_.c_str(), 334 output_chunk1 + output_chunk2 + output_chunk3); 335 } 336 } 337 } 338 339 // For the window test, the maximum target window size is much smaller than the 340 // target file size. (The largest window is Window 2, with 61 target bytes.) 341 // Use the minimum values possible. 342 TEST_F(VCDiffStandardWindowDecoderTest, TargetMatchesWindowSizeLimit) { 343 decoder_.SetMaximumTargetWindowSize(kWindow2Size); 344 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 345 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), 346 delta_file_.size(), 347 &output_)); 348 EXPECT_TRUE(decoder_.FinishDecoding()); 349 EXPECT_EQ(expected_target_.c_str(), output_); 350 } 351 352 TEST_F(VCDiffStandardWindowDecoderTest, TargetMatchesFileSizeLimit) { 353 decoder_.SetMaximumTargetFileSize(expected_target_.size()); 354 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 355 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), 356 delta_file_.size(), 357 &output_)); 358 EXPECT_TRUE(decoder_.FinishDecoding()); 359 EXPECT_EQ(expected_target_.c_str(), output_); 360 } 361 362 TEST_F(VCDiffStandardWindowDecoderTest, TargetExceedsWindowSizeLimit) { 363 decoder_.SetMaximumTargetWindowSize(kWindow2Size - 1); 364 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 365 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), 366 delta_file_.size(), 367 &output_)); 368 EXPECT_EQ("", output_); 369 } 370 371 TEST_F(VCDiffStandardWindowDecoderTest, TargetExceedsFileSizeLimit) { 372 decoder_.SetMaximumTargetFileSize(expected_target_.size() - 1); 373 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 374 EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), 375 delta_file_.size(), 376 &output_)); 377 EXPECT_EQ("", output_); 378 } 379 380 typedef VCDiffStandardWindowDecoderTest 381 VCDiffStandardWindowDecoderTestByteByByte; 382 383 TEST_F(VCDiffStandardWindowDecoderTestByteByByte, Decode) { 384 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 385 for (size_t i = 0; i < delta_file_.size(); ++i) { 386 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 387 } 388 EXPECT_TRUE(decoder_.FinishDecoding()); 389 EXPECT_EQ(expected_target_.c_str(), output_); 390 } 391 392 TEST_F(VCDiffStandardWindowDecoderTestByteByByte, DecodeExplicitVcdTarget) { 393 decoder_.SetAllowVcdTarget(true); 394 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 395 for (size_t i = 0; i < delta_file_.size(); ++i) { 396 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 397 } 398 EXPECT_TRUE(decoder_.FinishDecoding()); 399 EXPECT_EQ(expected_target_.c_str(), output_); 400 } 401 402 // Windows 3 and 4 use the VCD_TARGET flag, so decoder should signal an error. 403 TEST_F(VCDiffStandardWindowDecoderTestByteByByte, DecodeNoVcdTarget) { 404 decoder_.SetAllowVcdTarget(false); 405 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 406 size_t i = 0; 407 for (; i < delta_file_.size(); ++i) { 408 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { 409 break; 410 } 411 } 412 // The failure should occur just at the position of the first VCD_TARGET. 413 EXPECT_EQ(delta_file_header_.size() + 83, i); 414 // The target data for the first two windows should have been output. 415 EXPECT_EQ(expected_target_.substr(0, 89).c_str(), output_); 416 } 417 418 // Divides up the interleaved encoding into eight separate delta file windows. 419 class VCDiffInterleavedWindowDecoderTest 420 : public VCDiffStandardWindowDecoderTest { 421 protected: 422 VCDiffInterleavedWindowDecoderTest(); 423 virtual ~VCDiffInterleavedWindowDecoderTest() {} 424 private: 425 static const char kWindowBody[]; 426 }; 427 428 const char VCDiffInterleavedWindowDecoderTest::kWindowBody[] = { 429 // Window 1: 430 VCD_SOURCE, // Win_Indicator: take source from dictionary 431 FirstByteOfStringLength(kDictionary), // Source segment size 432 SecondByteOfStringLength(kDictionary), 433 0x00, // Source segment position: start of dictionary 434 0x08, // Length of the delta encoding 435 0x1C, // Size of the target window (28) 436 0x00, // Delta_indicator (no compression) 437 0x00, // length of data for ADDs and RUNs 438 0x03, // length of instructions section 439 0x00, // length of addresses for COPYs 440 0x13, // VCD_COPY mode VCD_SELF, size 0 441 0x1C, // Size of COPY (28) 442 0x00, // Start of dictionary 443 // Window 2: 444 0x00, // Win_Indicator: No source segment (ADD only) 445 0x44, // Length of the delta encoding 446 0x3D, // Size of the target window (61) 447 0x00, // Delta_indicator (no compression) 448 0x00, // length of data for ADDs and RUNs 449 0x3F, // length of instructions section 450 0x00, // length of addresses for COPYs 451 0x01, // VCD_ADD size 0 452 0x3D, // Size of ADD (61) 453 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', 454 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', 455 'T', 'h', 'a', 't', ' ', 456 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', 457 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', 458 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', 459 // Window 3: 460 VCD_TARGET, // Win_Indicator: take source from decoded data 461 0x59, // Source segment size: length of data decoded so far 462 0x00, // Source segment position: start of decoded data 463 0x08, // Length of the delta encoding 464 0x2C, // Size of the target window 465 0x00, // Delta_indicator (no compression) 466 0x00, // length of data for ADDs and RUNs 467 0x03, // length of instructions section 468 0x00, // length of addresses for COPYs 469 0x23, // VCD_COPY mode VCD_HERE, size 0 470 0x2C, // Size of COPY (44) 471 0x58, // HERE mode address (27+61 back from here_address) 472 // Window 4: 473 VCD_TARGET, // Win_Indicator: take source from decoded data 474 0x05, // Source segment size: only 5 bytes needed for this COPY 475 0x2E, // Source segment position: offset for COPY 476 0x09, // Length of the delta encoding 477 0x07, // Size of the target window 478 0x00, // Delta_indicator (no compression) 479 0x00, // length of data for ADDs and RUNs 480 0x04, // length of instructions section 481 0x00, // length of addresses for COPYs 482 0xA7, // VCD_ADD size 2 + VCD_COPY mode SELF, size 5 483 'h', 'r', 484 0x00, // SELF mode address (start of source segment) 485 // Window 5: 486 0x00, // Win_Indicator: No source segment (ADD only) 487 0x0F, // Length of the delta encoding 488 0x09, // Size of the target window 489 0x00, // Delta_indicator (no compression) 490 0x00, // length of data for ADDs and RUNs 491 0x0A, // length of instructions section 492 0x00, // length of addresses for COPYs 493 0x0A, // VCD_ADD size 9 494 'W', 'h', 'a', 't', ' ', 'I', ' ', 't', 'e', 495 // Window 6: 496 0x00, // Win_Indicator: No source segment (RUN only) 497 0x08, // Length of the delta encoding 498 0x02, // Size of the target window 499 0x00, // Delta_indicator (no compression) 500 0x00, // length of data for ADDs and RUNs 501 0x03, // length of instructions section 502 0x00, // length of addresses for COPYs 503 0x00, // VCD_RUN size 0 504 0x02, // Size of RUN (2) 505 'l', 506 // Window 7: 507 0x00, // Win_Indicator: No source segment (ADD only) 508 0x22, // Length of the delta encoding 509 0x1B, // Size of the target window 510 0x00, // Delta_indicator (no compression) 511 0x00, // length of data for ADDs and RUNs 512 0x1D, // length of instructions section 513 0x00, // length of addresses for COPYs 514 0x01, // VCD_ADD size 0 515 0x1B, // Size of ADD (27) 516 ' ', 'y', 'o', 'u', ' ', 517 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', 518 't', 'r', 'u', 'e', '.', '\"', '\n', 519 }; 520 521 VCDiffInterleavedWindowDecoderTest::VCDiffInterleavedWindowDecoderTest() { 522 UseInterleavedFileHeader(); 523 // delta_window_header_ is left blank. All window headers and bodies are 524 // lumped together in delta_window_body_. This means that AddChecksum() 525 // cannot be used to test the checksum feature. 526 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); 527 } 528 529 TEST_F(VCDiffInterleavedWindowDecoderTest, Decode) { 530 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 531 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), 532 delta_file_.size(), 533 &output_)); 534 EXPECT_TRUE(decoder_.FinishDecoding()); 535 EXPECT_EQ(expected_target_.c_str(), output_); 536 } 537 538 TEST_F(VCDiffInterleavedWindowDecoderTest, DecodeInTwoParts) { 539 const size_t delta_file_size = delta_file_.size(); 540 for (size_t i = 1; i < delta_file_size; i++) { 541 string output_chunk1, output_chunk2; 542 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 543 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], 544 i, 545 &output_chunk1)); 546 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 547 delta_file_size - i, 548 &output_chunk2)); 549 EXPECT_TRUE(decoder_.FinishDecoding()); 550 EXPECT_EQ(expected_target_.c_str(), output_chunk1 + output_chunk2); 551 } 552 } 553 554 TEST_F(VCDiffInterleavedWindowDecoderTest, DecodeInThreeParts) { 555 const size_t delta_file_size = delta_file_.size(); 556 for (size_t i = 1; i < delta_file_size - 1; i++) { 557 for (size_t j = i + 1; j < delta_file_size; j++) { 558 string output_chunk1, output_chunk2, output_chunk3; 559 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 560 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], 561 i, 562 &output_chunk1)); 563 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 564 j - i, 565 &output_chunk2)); 566 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[j], 567 delta_file_size - j, 568 &output_chunk3)); 569 EXPECT_TRUE(decoder_.FinishDecoding()); 570 EXPECT_EQ(expected_target_.c_str(), 571 output_chunk1 + output_chunk2 + output_chunk3); 572 } 573 } 574 } 575 576 typedef VCDiffInterleavedWindowDecoderTest 577 VCDiffInterleavedWindowDecoderTestByteByByte; 578 579 TEST_F(VCDiffInterleavedWindowDecoderTestByteByByte, Decode) { 580 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 581 for (size_t i = 0; i < delta_file_.size(); ++i) { 582 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 583 } 584 EXPECT_TRUE(decoder_.FinishDecoding()); 585 EXPECT_EQ(expected_target_.c_str(), output_); 586 } 587 588 // Windows 3 and 4 use the VCD_TARGET flag, so decoder should signal an error. 589 TEST_F(VCDiffInterleavedWindowDecoderTestByteByByte, DecodeNoVcdTarget) { 590 decoder_.SetAllowVcdTarget(false); 591 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 592 size_t i = 0; 593 for (; i < delta_file_.size(); ++i) { 594 if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) { 595 break; 596 } 597 } 598 // The failure should occur just at the position of the first VCD_TARGET. 599 EXPECT_EQ(delta_file_header_.size() + 83, i); 600 // The target data for the first two windows should have been output. 601 EXPECT_EQ(expected_target_.substr(0, 89).c_str(), output_); 602 } 603 604 // The original version of VCDiffDecoder did not allow the caller to modify the 605 // contents of output_string between calls to DecodeChunk(). That restriction 606 // has been removed. Verify that the same result is still produced if the 607 // output string is cleared after each call to DecodeChunk(). Use the window 608 // encoding because it refers back to the previously decoded target data, which 609 // is the feature that would fail if the restriction still applied. 610 // 611 TEST_F(VCDiffInterleavedWindowDecoderTest, OutputStringCanBeModified) { 612 string temp_output; 613 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 614 for (size_t i = 0; i < delta_file_.size(); ++i) { 615 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &temp_output)); 616 output_.append(temp_output); 617 temp_output.clear(); 618 } 619 EXPECT_TRUE(decoder_.FinishDecoding()); 620 EXPECT_EQ(expected_target_.c_str(), output_); 621 } 622 623 TEST_F(VCDiffInterleavedWindowDecoderTest, OutputStringIsPreserved) { 624 const string previous_data("Previous data"); 625 output_ = previous_data; 626 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 627 for (size_t i = 0; i < delta_file_.size(); ++i) { 628 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 629 } 630 EXPECT_TRUE(decoder_.FinishDecoding()); 631 EXPECT_EQ((previous_data + expected_target_).c_str(), output_); 632 } 633 634 // A decode job that tests the ability to COPY across the boundary between 635 // source data and target data. 636 class VCDiffStandardCrossDecoderTest : public VCDiffDecoderTest { 637 protected: 638 static const char kExpectedTarget[]; 639 static const char kWindowHeader[]; 640 static const char kWindowBody[]; 641 642 VCDiffStandardCrossDecoderTest(); 643 virtual ~VCDiffStandardCrossDecoderTest() {} 644 }; 645 646 const char VCDiffStandardCrossDecoderTest::kWindowHeader[] = { 647 VCD_SOURCE, // Win_Indicator: take source from dictionary 648 FirstByteOfStringLength(kDictionary), // Source segment size 649 SecondByteOfStringLength(kDictionary), 650 0x00, // Source segment position: start of dictionary 651 0x15, // Length of the delta encoding 652 StringLengthAsByte(kExpectedTarget), // Size of the target window 653 0x00, // Delta_indicator (no compression) 654 0x07, // length of data for ADDs and RUNs 655 0x06, // length of instructions section 656 0x03 // length of addresses for COPYs 657 }; 658 659 const char VCDiffStandardCrossDecoderTest::kWindowBody[] = { 660 // Data for ADD (length 7) 661 'S', 'p', 'i', 'd', 'e', 'r', 's', 662 // Instructions and sizes (length 6) 663 0x01, // VCD_ADD size 0 664 0x07, // Size of ADD (7) 665 0x23, // VCD_COPY mode VCD_HERE, size 0 666 0x19, // Size of COPY (25) 667 0x14, // VCD_COPY mode VCD_SELF, size 4 668 0x25, // VCD_COPY mode VCD_HERE, size 5 669 // Addresses for COPYs (length 3) 670 0x15, // HERE mode address for 1st copy (21 back from here_address) 671 0x06, // SELF mode address for 2nd copy 672 0x14 // HERE mode address for 3rd copy 673 }; 674 675 const char VCDiffStandardCrossDecoderTest::kExpectedTarget[] = 676 "Spiders in his hair.\n" 677 "Spiders in the air.\n"; 678 679 VCDiffStandardCrossDecoderTest::VCDiffStandardCrossDecoderTest() { 680 UseStandardFileHeader(); 681 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); 682 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); 683 expected_target_.assign(kExpectedTarget); 684 } 685 686 TEST_F(VCDiffStandardCrossDecoderTest, Decode) { 687 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 688 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), 689 delta_file_.size(), 690 &output_)); 691 EXPECT_TRUE(decoder_.FinishDecoding()); 692 EXPECT_EQ(expected_target_.c_str(), output_); 693 } 694 695 typedef VCDiffStandardCrossDecoderTest VCDiffStandardCrossDecoderTestByteByByte; 696 697 TEST_F(VCDiffStandardCrossDecoderTestByteByByte, Decode) { 698 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 699 for (size_t i = 0; i < delta_file_.size(); ++i) { 700 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 701 } 702 EXPECT_TRUE(decoder_.FinishDecoding()); 703 EXPECT_EQ(expected_target_.c_str(), output_); 704 } 705 706 // The same decode job that tests the ability to COPY across the boundary 707 // between source data and target data, but using the interleaved format rather 708 // than the standard format. 709 class VCDiffInterleavedCrossDecoderTest 710 : public VCDiffStandardCrossDecoderTest { 711 protected: 712 VCDiffInterleavedCrossDecoderTest(); 713 virtual ~VCDiffInterleavedCrossDecoderTest() {} 714 715 private: 716 static const char kWindowHeader[]; 717 static const char kWindowBody[]; 718 }; 719 720 const char VCDiffInterleavedCrossDecoderTest::kWindowHeader[] = { 721 VCD_SOURCE, // Win_Indicator: take source from dictionary 722 FirstByteOfStringLength(kDictionary), // Source segment size 723 SecondByteOfStringLength(kDictionary), 724 0x00, // Source segment position: start of dictionary 725 0x15, // Length of the delta encoding 726 StringLengthAsByte(kExpectedTarget), // Size of the target window 727 0x00, // Delta_indicator (no compression) 728 0x00, // length of data for ADDs and RUNs 729 0x10, // length of instructions section 730 0x00, // length of addresses for COPYs 731 }; 732 733 const char VCDiffInterleavedCrossDecoderTest::kWindowBody[] = { 734 0x01, // VCD_ADD size 0 735 0x07, // Size of ADD (7) 736 // Data for ADD (length 7) 737 'S', 'p', 'i', 'd', 'e', 'r', 's', 738 0x23, // VCD_COPY mode VCD_HERE, size 0 739 0x19, // Size of COPY (25) 740 0x15, // HERE mode address for 1st copy (21 back from here_address) 741 0x14, // VCD_COPY mode VCD_SELF, size 4 742 0x06, // SELF mode address for 2nd copy 743 0x25, // VCD_COPY mode VCD_HERE, size 5 744 0x14 // HERE mode address for 3rd copy 745 }; 746 747 VCDiffInterleavedCrossDecoderTest::VCDiffInterleavedCrossDecoderTest() { 748 UseInterleavedFileHeader(); 749 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); 750 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); 751 } 752 753 TEST_F(VCDiffInterleavedCrossDecoderTest, Decode) { 754 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 755 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), 756 delta_file_.size(), 757 &output_)); 758 EXPECT_TRUE(decoder_.FinishDecoding()); 759 EXPECT_EQ(expected_target_.c_str(), output_); 760 } 761 762 TEST_F(VCDiffInterleavedCrossDecoderTest, DecodeWithChecksum) { 763 ComputeAndAddChecksum(); 764 InitializeDeltaFile(); 765 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 766 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), 767 delta_file_.size(), 768 &output_)); 769 EXPECT_TRUE(decoder_.FinishDecoding()); 770 EXPECT_EQ(expected_target_.c_str(), output_); 771 } 772 773 typedef VCDiffInterleavedCrossDecoderTest 774 VCDiffInterleavedCrossDecoderTestByteByByte; 775 776 TEST_F(VCDiffInterleavedCrossDecoderTestByteByByte, Decode) { 777 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 778 for (size_t i = 0; i < delta_file_.size(); ++i) { 779 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 780 } 781 EXPECT_TRUE(decoder_.FinishDecoding()); 782 EXPECT_EQ(expected_target_.c_str(), output_); 783 } 784 785 TEST_F(VCDiffInterleavedCrossDecoderTestByteByByte, DecodeWithChecksum) { 786 ComputeAndAddChecksum(); 787 InitializeDeltaFile(); 788 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 789 for (size_t i = 0; i < delta_file_.size(); ++i) { 790 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 791 } 792 EXPECT_TRUE(decoder_.FinishDecoding()); 793 EXPECT_EQ(expected_target_.c_str(), output_); 794 } 795 796 // Test using a custom code table and custom cache sizes with interleaved 797 // format. 798 class VCDiffCustomCodeTableDecoderTest : public VCDiffInterleavedDecoderTest { 799 protected: 800 static const char kFileHeader[]; 801 static const char kWindowHeader[]; 802 static const char kWindowBody[]; 803 static const char kEncodedCustomCodeTable[]; 804 805 VCDiffCustomCodeTableDecoderTest(); 806 virtual ~VCDiffCustomCodeTableDecoderTest() {} 807 }; 808 809 const char VCDiffCustomCodeTableDecoderTest::kFileHeader[] = { 810 0xD6, // 'V' | 0x80 811 0xC3, // 'C' | 0x80 812 0xC4, // 'D' | 0x80 813 'S', // SDCH version code 814 0x02 // Hdr_Indicator: Use custom code table 815 }; 816 817 // Make a custom code table that includes exactly the instructions we need 818 // to encode the first test's data without using any explicit length values. 819 // Be careful not to replace any existing opcodes that have size 0, 820 // to ensure that the custom code table is valid (can express all possible 821 // values of inst (also known as instruction type) and mode with size 0.) 822 // This encoding uses interleaved format, which is easier to read. 823 // 824 // Here are the changes to the standard code table: 825 // ADD size 2 (opcode 3) => RUN size 2 (inst1[3] = VCD_RUN) 826 // ADD size 16 (opcode 17) => ADD size 27 (size1[17] = 27) 827 // ADD size 17 (opcode 18) => ADD size 61 (size1[18] = 61) 828 // COPY mode 0 size 18 (opcode 34) => COPY mode 0 size 28 (size1[34] = 28) 829 // COPY mode 1 size 18 (opcode 50) => COPY mode 1 size 44 (size1[50] = 44) 830 // 831 const char VCDiffCustomCodeTableDecoderTest::kEncodedCustomCodeTable[] = { 832 0xD6, // 'V' | 0x80 833 0xC3, // 'C' | 0x80 834 0xC4, // 'D' | 0x80 835 'S', // SDCH version code 836 0x00, // Hdr_Indicator: no custom code table, no compression 837 VCD_SOURCE, // Win_Indicator: take source from dictionary 838 (sizeof(VCDiffCodeTableData) >> 7) | 0x80, // First byte of table length 839 sizeof(VCDiffCodeTableData) & 0x7F, // Second byte of table length 840 0x00, // Source segment position: start of default code table 841 0x1F, // Length of the delta encoding 842 (sizeof(VCDiffCodeTableData) >> 7) | 0x80, // First byte of table length 843 sizeof(VCDiffCodeTableData) & 0x7F, // Second byte of table length 844 0x00, // Delta_indicator (no compression) 845 0x00, // length of data for ADDs and RUNs (unused) 846 0x19, // length of interleaved section 847 0x00, // length of addresses for COPYs (unused) 848 0x05, // VCD_ADD size 4 849 // Data for ADD (length 4) 850 VCD_RUN, VCD_ADD, VCD_ADD, VCD_RUN, 851 0x13, // VCD_COPY mode VCD_SELF size 0 852 0x84, // Size of copy: upper bits (512 - 4 + 17 = 525) 853 0x0D, // Size of copy: lower bits 854 0x04, // Address of COPY 855 0x03, // VCD_ADD size 2 856 // Data for ADD (length 2) 857 0x1B, 0x3D, 858 0x3F, // VCD_COPY mode VCD_NEAR(0) size 15 859 0x84, // Address of copy: upper bits (525 + 2 = 527) 860 0x0F, // Address of copy: lower bits 861 0x02, // VCD_ADD size 1 862 // Data for ADD (length 1) 863 0x1C, 864 0x4F, // VCD_COPY mode VCD_NEAR(1) size 15 865 0x10, // Address of copy 866 0x02, // VCD_ADD size 1 867 // Data for ADD (length 1) 868 0x2C, 869 0x53, // VCD_COPY mode VCD_NEAR(2) size 0 870 0x87, // Size of copy: upper bits (256 * 4 - 51 = 973) 871 0x4D, // Size of copy: lower bits 872 0x10 // Address of copy 873 }; 874 875 // This is similar to VCDiffInterleavedDecoderTest, but uses the custom code 876 // table to eliminate the need to explicitly encode instruction sizes. 877 // Notice that NEAR(0) mode is used here where NEAR(1) mode was used in 878 // VCDiffInterleavedDecoderTest. This is because the custom code table 879 // has the size of the NEAR cache set to 1; only the most recent 880 // COPY instruction is available. This will also be a test of 881 // custom cache sizes. 882 const char VCDiffCustomCodeTableDecoderTest::kWindowHeader[] = { 883 VCD_SOURCE, // Win_Indicator: take source from dictionary 884 FirstByteOfStringLength(kDictionary), // Source segment size 885 SecondByteOfStringLength(kDictionary), 886 0x00, // Source segment position: start of dictionary 887 0x74, // Length of the delta encoding 888 FirstByteOfStringLength(kExpectedTarget), // Size of the target window 889 SecondByteOfStringLength(kExpectedTarget), 890 0x00, // Delta_indicator (no compression) 891 0x00, // length of data for ADDs and RUNs (unused) 892 0x6E, // length of interleaved section 893 0x00 // length of addresses for COPYs (unused) 894 }; 895 896 const char VCDiffCustomCodeTableDecoderTest::kWindowBody[] = { 897 0x22, // VCD_COPY mode VCD_SELF, size 28 898 0x00, // Address of COPY: Start of dictionary 899 0x12, // VCD_ADD size 61 900 // Data for ADD (length 61) 901 ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ', 902 'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n', 903 'T', 'h', 'a', 't', ' ', 904 'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', 905 'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ', 906 't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n', 907 0x32, // VCD_COPY mode VCD_HERE, size 44 908 0x58, // HERE mode address (27+61 back from here_address) 909 0xBF, // VCD_ADD size 2 + VCD_COPY mode NEAR(0), size 5 910 // Data for ADDs: 2nd section (length 2) 911 'h', 'r', 912 0x2D, // NEAR(0) mode address (45 after prior address) 913 0x0A, // VCD_ADD size 9 914 // Data for ADDs: 3rd section (length 9) 915 'W', 'h', 'a', 't', ' ', 916 'I', ' ', 't', 'e', 917 0x03, // VCD_RUN size 2 918 // Data for RUN: 4th section (length 1) 919 'l', 920 0x11, // VCD_ADD size 27 921 // Data for ADD: 4th section (length 27) 922 ' ', 'y', 'o', 'u', ' ', 923 't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ', 924 't', 'r', 'u', 'e', '.', '\"', '\n' 925 }; 926 927 VCDiffCustomCodeTableDecoderTest::VCDiffCustomCodeTableDecoderTest() { 928 delta_file_header_.assign(kFileHeader, sizeof(kFileHeader)); 929 delta_file_header_.push_back(0x01); // NEAR cache size (custom) 930 delta_file_header_.push_back(0x06); // SAME cache size (custom) 931 delta_file_header_.append(kEncodedCustomCodeTable, 932 sizeof(kEncodedCustomCodeTable)); 933 delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader)); 934 delta_window_body_.assign(kWindowBody, sizeof(kWindowBody)); 935 } 936 937 TEST_F(VCDiffCustomCodeTableDecoderTest, CustomCodeTableEncodingMatches) { 938 VCDiffCodeTableData custom_code_table( 939 VCDiffCodeTableData::kDefaultCodeTableData); 940 custom_code_table.inst1[3] = VCD_RUN; 941 custom_code_table.size1[17] = 27; 942 custom_code_table.size1[18] = 61; 943 custom_code_table.size1[34] = 28; 944 custom_code_table.size1[50] = 44; 945 946 decoder_.StartDecoding( 947 reinterpret_cast<const char*>( 948 &VCDiffCodeTableData::kDefaultCodeTableData), 949 sizeof(VCDiffCodeTableData::kDefaultCodeTableData)); 950 EXPECT_TRUE(decoder_.DecodeChunk(kEncodedCustomCodeTable, 951 sizeof(kEncodedCustomCodeTable), 952 &output_)); 953 EXPECT_TRUE(decoder_.FinishDecoding()); 954 EXPECT_EQ(sizeof(custom_code_table), output_.size()); 955 const VCDiffCodeTableData* decoded_table = 956 reinterpret_cast<const VCDiffCodeTableData*>(output_.data()); 957 EXPECT_EQ(VCD_RUN, decoded_table->inst1[0]); 958 EXPECT_EQ(VCD_RUN, decoded_table->inst1[3]); 959 EXPECT_EQ(27, decoded_table->size1[17]); 960 EXPECT_EQ(61, decoded_table->size1[18]); 961 EXPECT_EQ(28, decoded_table->size1[34]); 962 EXPECT_EQ(44, decoded_table->size1[50]); 963 for (int i = 0; i < VCDiffCodeTableData::kCodeTableSize; ++i) { 964 EXPECT_EQ(custom_code_table.inst1[i], decoded_table->inst1[i]); 965 EXPECT_EQ(custom_code_table.inst2[i], decoded_table->inst2[i]); 966 EXPECT_EQ(custom_code_table.size1[i], decoded_table->size1[i]); 967 EXPECT_EQ(custom_code_table.size2[i], decoded_table->size2[i]); 968 EXPECT_EQ(custom_code_table.mode1[i], decoded_table->mode1[i]); 969 EXPECT_EQ(custom_code_table.mode2[i], decoded_table->mode2[i]); 970 } 971 } 972 973 TEST_F(VCDiffCustomCodeTableDecoderTest, DecodeUsingCustomCodeTable) { 974 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 975 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(), 976 delta_file_.size(), 977 &output_)); 978 EXPECT_TRUE(decoder_.FinishDecoding()); 979 EXPECT_EQ(expected_target_.c_str(), output_); 980 } 981 982 TEST_F(VCDiffCustomCodeTableDecoderTest, IncompleteCustomCodeTable) { 983 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 984 EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), 985 delta_file_header_.size() - 1, 986 &output_)); 987 EXPECT_FALSE(decoder_.FinishDecoding()); 988 EXPECT_EQ("", output_); 989 } 990 991 typedef VCDiffCustomCodeTableDecoderTest 992 VCDiffCustomCodeTableDecoderTestByteByByte; 993 994 TEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, DecodeUsingCustomCodeTable) { 995 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 996 for (size_t i = 0; i < delta_file_.size(); ++i) { 997 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 998 } 999 EXPECT_TRUE(decoder_.FinishDecoding()); 1000 EXPECT_EQ(expected_target_.c_str(), output_); 1001 } 1002 1003 TEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, IncompleteCustomCodeTable) { 1004 delta_file_.resize(delta_file_header_.size() - 1); 1005 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 1006 for (size_t i = 0; i < delta_file_.size(); ++i) { 1007 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 1008 } 1009 EXPECT_FALSE(decoder_.FinishDecoding()); 1010 EXPECT_EQ("", output_); 1011 } 1012 1013 TEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, CustomTableNoVcdTarget) { 1014 decoder_.SetAllowVcdTarget(false); 1015 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 1016 for (size_t i = 0; i < delta_file_.size(); ++i) { 1017 EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_)); 1018 } 1019 EXPECT_TRUE(decoder_.FinishDecoding()); 1020 EXPECT_EQ(expected_target_.c_str(), output_); 1021 } 1022 1023 #ifdef GTEST_HAS_DEATH_TEST 1024 typedef VCDiffCustomCodeTableDecoderTest VCDiffCustomCodeTableDecoderDeathTest; 1025 1026 TEST_F(VCDiffCustomCodeTableDecoderDeathTest, BadCustomCacheSizes) { 1027 delta_file_header_.assign(kFileHeader, sizeof(kFileHeader)); 1028 delta_file_header_.push_back(0x81); // NEAR cache size (top bit) 1029 delta_file_header_.push_back(0x10); // NEAR cache size (custom value 0x90) 1030 delta_file_header_.push_back(0x81); // SAME cache size (top bit) 1031 delta_file_header_.push_back(0x10); // SAME cache size (custom value 0x90) 1032 delta_file_header_.append(kEncodedCustomCodeTable, 1033 sizeof(kEncodedCustomCodeTable)); 1034 InitializeDeltaFile(); 1035 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 1036 EXPECT_DEBUG_DEATH(EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), 1037 delta_file_.size(), 1038 &output_)), 1039 "cache"); 1040 EXPECT_EQ("", output_); 1041 } 1042 1043 TEST_F(VCDiffCustomCodeTableDecoderDeathTest, BadCustomCacheSizesNoVcdTarget) { 1044 decoder_.SetAllowVcdTarget(false); 1045 delta_file_header_.assign(kFileHeader, sizeof(kFileHeader)); 1046 delta_file_header_.push_back(0x81); // NEAR cache size (top bit) 1047 delta_file_header_.push_back(0x10); // NEAR cache size (custom value 0x90) 1048 delta_file_header_.push_back(0x81); // SAME cache size (top bit) 1049 delta_file_header_.push_back(0x10); // SAME cache size (custom value 0x90) 1050 delta_file_header_.append(kEncodedCustomCodeTable, 1051 sizeof(kEncodedCustomCodeTable)); 1052 InitializeDeltaFile(); 1053 decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 1054 EXPECT_DEBUG_DEATH(EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(), 1055 delta_file_.size(), 1056 &output_)), 1057 "cache"); 1058 EXPECT_EQ("", output_); 1059 } 1060 1061 #endif // GTEST_HAS_DEATH_TEST 1062 1063 } // namespace open_vcdiff 1064 } // unnamed namespace 1065