• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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();
~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 
VCDiffLargeTargetTest()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.
TEST_F(VCDiffLargeTargetTest,Decode)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.
TEST_F(VCDiffLargeTargetTest,DecodeReachesMaxFileSize)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