1baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// Copyright 2008 Google Inc. 2baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// Author: Lincoln Smith 3baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// 4baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// Licensed under the Apache License, Version 2.0 (the "License"); 5baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// you may not use this file except in compliance with the License. 6baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// You may obtain a copy of the License at 7baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// 8baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// http://www.apache.org/licenses/LICENSE-2.0 9baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// 10baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// Unless required by applicable law or agreed to in writing, software 11baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// distributed under the License is distributed on an "AS IS" BASIS, 12baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// See the License for the specific language governing permissions and 14baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// limitations under the License. 15baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 16baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff#include <config.h> 17baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff#include "google/vcdecoder.h" 18baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff#include <string> 19baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff#include "codetable.h" 20baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff#include "testing.h" 21baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff#include "vcdecoder_test.h" 22baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 23baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiffnamespace open_vcdiff { 24baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiffnamespace { 25baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 26baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 27baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// Decode an encoding that uses a RUN instruction to allocate 64MB. 28baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiffclass VCDiffLargeTargetTest : public VCDiffDecoderTest { 29baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff protected: 30baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff VCDiffLargeTargetTest(); 31baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff virtual ~VCDiffLargeTargetTest() {} 32baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 33baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff static const char kLargeRunWindow[]; 34baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff}; 35baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 36baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiffconst char VCDiffLargeTargetTest::kLargeRunWindow[] = { 37baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x00, // Win_Indicator: no source segment 38baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x0E, // Length of the delta encoding 39baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0xA0, // Size of the target window (0x4000000) 40baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x80, // Size of the target window cont'd 41baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x80, // Size of the target window cont'd 42baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x00, // Size of the target window cont'd 43baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x00, // Delta_indicator (no compression) 44baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x00, // length of data for ADDs and RUNs 45baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x06, // length of instructions section 46baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x00, // length of addresses for COPYs 47baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff // Interleaved segment 48baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x00, // VCD_RUN size 0 49baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0xA0, // Size of RUN (0x4000000) 50baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x80, // Size of RUN cont'd 51baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x80, // Size of RUN cont'd 52baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0x00, // Size of RUN cont'd 53baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 0xBE, // Data for RUN 54baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff}; 55baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 56baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiffVCDiffLargeTargetTest::VCDiffLargeTargetTest() { 57baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff UseInterleavedFileHeader(); 58baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff} 59baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 60baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// Ensure that, with allow_vcd_target set to false, we can decode any number of 61baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// 64MB windows without running out of memory. 62baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiffTEST_F(VCDiffLargeTargetTest, Decode) { 63baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff // 50 x 64MB = 3.2GB, which should be too large if memory usage accumulates 64baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff // during each iteration. 65baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff const int kIterations = 50; 66baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff decoder_.SetAllowVcdTarget(false); 67baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff decoder_.SetMaximumTargetFileSize(0x4000000UL * 50); 68baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 69baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), 70baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff delta_file_header_.size(), 71baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff &output_)); 72baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_EQ("", output_); 73baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff for (int i = 0; i < kIterations; i++) { 74baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_TRUE(decoder_.DecodeChunk(kLargeRunWindow, sizeof(kLargeRunWindow), 75baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff &output_)); 76baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_EQ(0x4000000U, output_.size()); 77baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_EQ(static_cast<char>(0xBE), output_[0]); 78baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_EQ(static_cast<char>(0xBE), 79baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff output_[output_.size() / 2]); // middle element 80baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_EQ(static_cast<char>(0xBE), 81baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff output_[output_.size() - 1]); // last element 82baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff output_.clear(); 83baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff } 84baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_TRUE(decoder_.FinishDecoding()); 85baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff} 86baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 87baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// If we don't increase the maximum target file size first, the same test should 88baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// produce an error. 89baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiffTEST_F(VCDiffLargeTargetTest, DecodeReachesMaxFileSize) { 90baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff decoder_.SetAllowVcdTarget(false); 91baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff decoder_.StartDecoding(dictionary_.data(), dictionary_.size()); 92baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(), 93baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff delta_file_header_.size(), 94baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff &output_)); 95baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_EQ("", output_); 96baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff // The default maximum target file size is 64MB, which just matches the target 97baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff // data produced by a single iteration. 98baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_TRUE(decoder_.DecodeChunk(kLargeRunWindow, sizeof(kLargeRunWindow), 99baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff &output_)); 100baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_EQ(0x4000000U, output_.size()); 101baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_EQ(static_cast<char>(0xBE), output_[0]); 102baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_EQ(static_cast<char>(0xBE), 103baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff output_[output_.size() / 2]); // middle element 104baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_EQ(static_cast<char>(0xBE), 105baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff output_[output_.size() - 1]); // last element 106baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff output_.clear(); 107baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff // Trying to decode a second window should exceed the target file size limit. 108baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff EXPECT_FALSE(decoder_.DecodeChunk(kLargeRunWindow, sizeof(kLargeRunWindow), 109baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff &output_)); 110baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff} 111baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff 112baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff} // unnamed namespace 113baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff} // namespace open_vcdiff 114