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