openvcdiff | baf44ea | 2009-04-09 19:20:49 +0000 | [diff] [blame] | 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 |