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 
     23 namespace open_vcdiff {
     24 namespace {
     25 
     26 
     27 // Decode an encoding that uses a RUN instruction to allocate 64MB.
     28 class VCDiffLargeTargetTest : public VCDiffDecoderTest {
     29  protected:
     30   VCDiffLargeTargetTest();
     31   virtual ~VCDiffLargeTargetTest() {}
     32 
     33   static const char kLargeRunWindow[];
     34 };
     35 
     36 const char VCDiffLargeTargetTest::kLargeRunWindow[] = {
     37     0x00,  // Win_Indicator: no source segment
     38     0x0E,  // Length of the delta encoding
     39     0xA0,  // Size of the target window (0x4000000)
     40     0x80,  // Size of the target window cont'd
     41     0x80,  // Size of the target window cont'd
     42     0x00,  // Size of the target window cont'd
     43     0x00,  // Delta_indicator (no compression)
     44     0x00,  // length of data for ADDs and RUNs
     45     0x06,  // length of instructions section
     46     0x00,  // length of addresses for COPYs
     47     // Interleaved segment
     48     0x00,  // VCD_RUN size 0
     49     0xA0,  // Size of RUN (0x4000000)
     50     0x80,  // Size of RUN cont'd
     51     0x80,  // Size of RUN cont'd
     52     0x00,  // Size of RUN cont'd
     53     0xBE,  // Data for RUN
     54 };
     55 
     56 VCDiffLargeTargetTest::VCDiffLargeTargetTest() {
     57   UseInterleavedFileHeader();
     58 }
     59 
     60 // Ensure that, with allow_vcd_target set to false, we can decode any number of
     61 // 64MB windows without running out of memory.
     62 TEST_F(VCDiffLargeTargetTest, Decode) {
     63   // 50 x 64MB = 3.2GB, which should be too large if memory usage accumulates
     64   // during each iteration.
     65   const int kIterations = 50;
     66   decoder_.SetAllowVcdTarget(false);
     67   decoder_.SetMaximumTargetFileSize(0x4000000UL * 50);
     68   decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
     69   EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(),
     70                                    delta_file_header_.size(),
     71                                    &output_));
     72   EXPECT_EQ("", output_);
     73   for (int i = 0; i < kIterations; i++) {
     74     EXPECT_TRUE(decoder_.DecodeChunk(kLargeRunWindow, sizeof(kLargeRunWindow),
     75                                      &output_));
     76     EXPECT_EQ(0x4000000U, output_.size());
     77     EXPECT_EQ(static_cast<char>(0xBE), output_[0]);
     78     EXPECT_EQ(static_cast<char>(0xBE),
     79               output_[output_.size() / 2]);  // middle element
     80     EXPECT_EQ(static_cast<char>(0xBE),
     81               output_[output_.size() - 1]);  // last element
     82     output_.clear();
     83   }
     84   EXPECT_TRUE(decoder_.FinishDecoding());
     85 }
     86 
     87 // If we don't increase the maximum target file size first, the same test should
     88 // produce an error.
     89 TEST_F(VCDiffLargeTargetTest, DecodeReachesMaxFileSize) {
     90   decoder_.SetAllowVcdTarget(false);
     91   decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
     92   EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(),
     93                                    delta_file_header_.size(),
     94                                    &output_));
     95   EXPECT_EQ("", output_);
     96   // The default maximum target file size is 64MB, which just matches the target
     97   // data produced by a single iteration.
     98   EXPECT_TRUE(decoder_.DecodeChunk(kLargeRunWindow, sizeof(kLargeRunWindow),
     99                                    &output_));
    100   EXPECT_EQ(0x4000000U, output_.size());
    101   EXPECT_EQ(static_cast<char>(0xBE), output_[0]);
    102   EXPECT_EQ(static_cast<char>(0xBE),
    103             output_[output_.size() / 2]);  // middle element
    104   EXPECT_EQ(static_cast<char>(0xBE),
    105             output_[output_.size() - 1]);  // last element
    106   output_.clear();
    107   // Trying to decode a second window should exceed the target file size limit.
    108   EXPECT_FALSE(decoder_.DecodeChunk(kLargeRunWindow, sizeof(kLargeRunWindow),
    109                                     &output_));
    110 }
    111 
    112 }  // unnamed namespace
    113 }  // namespace open_vcdiff
    114