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