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_.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