1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright 2008 Google Inc.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Author: Lincoln Smith
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Licensed under the Apache License, Version 2.0 (the "License");
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// you may not use this file except in compliance with the License.
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// You may obtain a copy of the License at
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//      http://www.apache.org/licenses/LICENSE-2.0
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Unless required by applicable law or agreed to in writing, software
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// distributed under the License is distributed on an "AS IS" BASIS,
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// See the License for the specific language governing permissions and
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// limitations under the License.
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <config.h>
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "google/vcdecoder.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "codetable.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "vcdecoder_test.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "vcdiff_defs.h"  // VCD_SOURCE
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace open_vcdiff {
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use the interleaved file header with the standard encoding.  Should work.
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass VCDiffDecoderInterleavedAllowedButNotUsed
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : public VCDiffStandardDecoderTest {
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffDecoderInterleavedAllowedButNotUsed() {
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UseInterleavedFileHeader();
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~VCDiffDecoderInterleavedAllowedButNotUsed() { }
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffDecoderInterleavedAllowedButNotUsed, Decode) {
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size(),
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffDecoderInterleavedAllowedButNotUsed, DecodeWithChecksum) {
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ComputeAndAddChecksum();
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  InitializeDeltaFile();
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size(),
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef VCDiffDecoderInterleavedAllowedButNotUsed
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCDiffDecoderInterleavedAllowedButNotUsedByteByByte;
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffDecoderInterleavedAllowedButNotUsedByteByByte, Decode) {
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffDecoderInterleavedAllowedButNotUsedByteByByte,
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       DecodeWithChecksum) {
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ComputeAndAddChecksum();
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  InitializeDeltaFile();
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use the standard file header with the interleaved encoding.  Should fail.
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass VCDiffDecoderInterleavedUsedButNotSupported
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : public VCDiffInterleavedDecoderTest {
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffDecoderInterleavedUsedButNotSupported() {
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UseStandardFileHeader();
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~VCDiffDecoderInterleavedUsedButNotSupported() { }
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffDecoderInterleavedUsedButNotSupported, DecodeShouldFail) {
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    delta_file_.size(),
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    &output_));
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ("", output_);
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffDecoderInterleavedUsedButNotSupported,
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       DecodeByteByByteShouldFail) {
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool failed = false;
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      failed = true;
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(failed);
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The decoder should not create more target bytes than were expected.
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_GE(expected_target_.size(), output_.size());
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Divides up the standard encoding into eight separate delta file windows.
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Each delta instruction appears in its own window.
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass VCDiffStandardWindowDecoderTest : public VCDiffDecoderTest {
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const size_t kWindow2Size = 61;
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffStandardWindowDecoderTest();
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~VCDiffStandardWindowDecoderTest() {}
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kWindowBody[];
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst size_t VCDiffStandardWindowDecoderTest::kWindow2Size;
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffStandardWindowDecoderTest::kWindowBody[] = {
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 1:
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_SOURCE,  // Win_Indicator: take source from dictionary
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FirstByteOfStringLength(kDictionary),  // Source segment size
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SecondByteOfStringLength(kDictionary),
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Source segment position: start of dictionary
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x08,  // Length of the delta encoding
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1C,  // Size of the target window (28)
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // length of instructions section
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // length of addresses for COPYs
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No data for ADDs and RUNs
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Instructions and sizes (length 2)
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x13,  // VCD_COPY mode VCD_SELF, size 0
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1C,  // Size of COPY (28)
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Addresses for COPYs (length 1)
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Start of dictionary
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 2:
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Win_Indicator: No source segment (ADD only)
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x44,  // Length of the delta encoding
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    static_cast<char>(kWindow2Size),  // Size of the target window (61)
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x3D,  // length of data for ADDs and RUNs
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // length of instructions section
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD (length 61)
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ',
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n',
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'T', 'h', 'a', 't', ' ',
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ',
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ',
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n',
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Instructions and sizes (length 2)
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // VCD_ADD size 0
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x3D,  // Size of ADD (61)
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No addresses for COPYs
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 3:
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_TARGET,  // Win_Indicator: take source from decoded data
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x59,  // Source segment size: length of data decoded so far
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Source segment position: start of decoded data
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x08,  // Length of the delta encoding
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x2C,  // Size of the target window
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // length of instructions section
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // length of addresses for COPYs
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No data for ADDs and RUNs
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Instructions and sizes (length 2)
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x23,  // VCD_COPY mode VCD_HERE, size 0
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x2C,  // Size of COPY (44)
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Addresses for COPYs (length 1)
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x58,  // HERE mode address (27+61 back from here_address)
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 4:
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_TARGET,  // Win_Indicator: take source from decoded data
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x05,  // Source segment size: only 5 bytes needed for this COPY
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x2E,  // Source segment position: offset for COPY
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x09,  // Length of the delta encoding
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x07,  // Size of the target window
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // length of data for ADDs and RUNs
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // length of instructions section
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // length of addresses for COPYs
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD (length 2)
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'h', 'r',
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Instructions and sizes (length 1)
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xA7,  // VCD_ADD size 2 + VCD_COPY mode SELF size 5
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Addresses for COPYs (length 1)
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // SELF mode address (start of source segment)
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 5:
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Win_Indicator: No source segment (ADD only)
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x0F,  // Length of the delta encoding
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x09,  // Size of the target window
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x09,  // length of data for ADDs and RUNs
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // length of instructions section
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD (length 9)
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'W', 'h', 'a', 't', ' ', 'I', ' ', 't', 'e',
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Instructions and sizes (length 1)
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x0A,       // VCD_ADD size 9
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No addresses for COPYs
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 6:
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Win_Indicator: No source segment (RUN only)
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x08,  // Length of the delta encoding
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // Size of the target window
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // length of data for ADDs and RUNs
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // length of instructions section
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for RUN (length 1)
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'l',
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Instructions and sizes (length 2)
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // VCD_RUN size 0
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // Size of RUN (2)
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No addresses for COPYs
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 7:
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Win_Indicator: No source segment (ADD only)
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x22,  // Length of the delta encoding
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1B,  // Size of the target window
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1B,  // length of data for ADDs and RUNs
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // length of instructions section
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD: 4th section (length 27)
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ' ', 'y', 'o', 'u', ' ',
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ',
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    't', 'r', 'u', 'e', '.', '\"', '\n',
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Instructions and sizes (length 2)
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // VCD_ADD size 0
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1B,  // Size of ADD (27)
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No addresses for COPYs
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottVCDiffStandardWindowDecoderTest::VCDiffStandardWindowDecoderTest() {
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UseStandardFileHeader();
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTest, Decode) {
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size(),
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Bug 1287926: If DecodeChunk() stops in the middle of the window header,
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and the expected size of the current target window is smaller than the
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// cumulative target bytes decoded so far, an underflow occurs and the decoder
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// tries to allocate ~MAX_INT bytes.
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTest, DecodeBreakInFourthWindowHeader) {
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parse file header + first two windows.
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const size_t chunk_1_size = delta_file_header_.size() + 83;
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parse third window, plus everything up to "Size of the target window" field
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of fourth window, but do not parse complete header of fourth window.
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const size_t chunk_2_size = 12 + 5;
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK_EQ(VCD_TARGET, static_cast<unsigned char>(delta_file_[chunk_1_size]));
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK_EQ(0x00, static_cast<int>(delta_file_[chunk_1_size + chunk_2_size]));
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  string output_chunk1, output_chunk2, output_chunk3;
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0],
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   chunk_1_size,
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_chunk1));
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[chunk_1_size],
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   chunk_2_size,
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_chunk2));
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[chunk_1_size + chunk_2_size],
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size()
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       - (chunk_1_size + chunk_2_size),
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_chunk3));
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_chunk1 + output_chunk2 + output_chunk3);
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTest, DecodeChunkNoVcdTargetAllowed) {
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.SetAllowVcdTarget(false);
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parse file header + first two windows.
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const size_t chunk_1_size = delta_file_header_.size() + 83;
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The third window begins with Win_Indicator = VCD_TARGET which is not
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // allowed.
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK_EQ(VCD_TARGET, static_cast<unsigned char>(delta_file_[chunk_1_size]));
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], chunk_1_size, &output_));
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Just parsing one more byte (the VCD_TARGET) should result in an error.
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(decoder_.DecodeChunk(&delta_file_[chunk_1_size], 1, &output_));
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The target data for the first two windows should have been output.
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_.substr(0, 89), output_);
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTest, DecodeInTwoParts) {
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const size_t delta_file_size = delta_file_.size();
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 1; i < delta_file_size; i++) {
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    string output_chunk1, output_chunk2;
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0],
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     i,
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     &output_chunk1));
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i],
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     delta_file_size - i,
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     &output_chunk2));
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.FinishDecoding());
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(expected_target_, output_chunk1 + output_chunk2);
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTest, DecodeInThreeParts) {
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const size_t delta_file_size = delta_file_.size();
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 1; i < delta_file_size - 1; i++) {
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (size_t j = i + 1; j < delta_file_size; j++) {
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      string output_chunk1, output_chunk2, output_chunk3;
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0],
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       i,
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       &output_chunk1));
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i],
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       j - i,
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       &output_chunk2));
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[j],
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       delta_file_size - j,
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       &output_chunk3));
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(decoder_.FinishDecoding());
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ(expected_target_,
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                output_chunk1 + output_chunk2 + output_chunk3);
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// For the window test, the maximum target window size is much smaller than the
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// target file size.  (The largest window is Window 2, with 61 target bytes.)
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use the minimum values possible.
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTest, TargetMatchesWindowSizeLimit) {
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.SetMaximumTargetWindowSize(kWindow2Size);
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size(),
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTest, TargetMatchesFileSizeLimit) {
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.SetMaximumTargetFileSize(expected_target_.size());
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size(),
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTest, TargetExceedsWindowSizeLimit) {
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.SetMaximumTargetWindowSize(kWindow2Size - 1);
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    delta_file_.size(),
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    &output_));
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ("", output_);
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTest, TargetExceedsFileSizeLimit) {
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.SetMaximumTargetFileSize(expected_target_.size() - 1);
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    delta_file_.size(),
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    &output_));
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ("", output_);
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef VCDiffStandardWindowDecoderTest
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCDiffStandardWindowDecoderTestByteByByte;
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTestByteByByte, Decode) {
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTestByteByByte, DecodeExplicitVcdTarget) {
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.SetAllowVcdTarget(true);
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Windows 3 and 4 use the VCD_TARGET flag, so decoder should signal an error.
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardWindowDecoderTestByteByByte, DecodeNoVcdTarget) {
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.SetAllowVcdTarget(false);
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t i = 0;
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (; i < delta_file_.size(); ++i) {
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The failure should occur just at the position of the first VCD_TARGET.
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(delta_file_header_.size() + 83, i);
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The target data for the first two windows should have been output.
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_.substr(0, 89), output_);
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Divides up the interleaved encoding into eight separate delta file windows.
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass VCDiffInterleavedWindowDecoderTest
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : public VCDiffStandardWindowDecoderTest {
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffInterleavedWindowDecoderTest();
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~VCDiffInterleavedWindowDecoderTest() {}
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kWindowBody[];
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffInterleavedWindowDecoderTest::kWindowBody[] = {
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 1:
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_SOURCE,  // Win_Indicator: take source from dictionary
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FirstByteOfStringLength(kDictionary),  // Source segment size
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SecondByteOfStringLength(kDictionary),
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Source segment position: start of dictionary
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x08,  // Length of the delta encoding
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1C,  // Size of the target window (28)
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x03,  // length of instructions section
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x13,  // VCD_COPY mode VCD_SELF, size 0
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1C,  // Size of COPY (28)
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Start of dictionary
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 2:
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Win_Indicator: No source segment (ADD only)
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x44,  // Length of the delta encoding
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x3D,  // Size of the target window (61)
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x3F,  // length of instructions section
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // VCD_ADD size 0
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x3D,  // Size of ADD (61)
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ',
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n',
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'T', 'h', 'a', 't', ' ',
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ',
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ',
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n',
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 3:
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_TARGET,  // Win_Indicator: take source from decoded data
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x59,  // Source segment size: length of data decoded so far
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Source segment position: start of decoded data
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x08,  // Length of the delta encoding
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x2C,  // Size of the target window
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x03,  // length of instructions section
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x23,  // VCD_COPY mode VCD_HERE, size 0
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x2C,  // Size of COPY (44)
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x58,  // HERE mode address (27+61 back from here_address)
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 4:
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_TARGET,  // Win_Indicator: take source from decoded data
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x05,  // Source segment size: only 5 bytes needed for this COPY
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x2E,  // Source segment position: offset for COPY
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x09,  // Length of the delta encoding
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x07,  // Size of the target window
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x04,  // length of instructions section
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xA7,  // VCD_ADD size 2 + VCD_COPY mode SELF, size 5
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'h', 'r',
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // SELF mode address (start of source segment)
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 5:
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Win_Indicator: No source segment (ADD only)
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x0F,  // Length of the delta encoding
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x09,  // Size of the target window
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x0A,  // length of instructions section
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x0A,       // VCD_ADD size 9
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'W', 'h', 'a', 't', ' ', 'I', ' ', 't', 'e',
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 6:
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Win_Indicator: No source segment (RUN only)
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x08,  // Length of the delta encoding
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // Size of the target window
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x03,  // length of instructions section
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // VCD_RUN size 0
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // Size of RUN (2)
504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'l',
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Window 7:
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Win_Indicator: No source segment (ADD only)
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x22,  // Length of the delta encoding
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1B,  // Size of the target window
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1D,  // length of instructions section
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // VCD_ADD size 0
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1B,  // Size of ADD (27)
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ' ', 'y', 'o', 'u', ' ',
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ',
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    't', 'r', 'u', 'e', '.', '\"', '\n',
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottVCDiffInterleavedWindowDecoderTest::VCDiffInterleavedWindowDecoderTest() {
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UseInterleavedFileHeader();
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // delta_window_header_ is left blank.  All window headers and bodies are
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // lumped together in delta_window_body_.  This means that AddChecksum()
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // cannot be used to test the checksum feature.
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedWindowDecoderTest, Decode) {
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size(),
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedWindowDecoderTest, DecodeInTwoParts) {
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const size_t delta_file_size = delta_file_.size();
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 1; i < delta_file_size; i++) {
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    string output_chunk1, output_chunk2;
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0],
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     i,
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     &output_chunk1));
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i],
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     delta_file_size - i,
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     &output_chunk2));
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.FinishDecoding());
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(expected_target_, output_chunk1 + output_chunk2);
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedWindowDecoderTest, DecodeInThreeParts) {
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const size_t delta_file_size = delta_file_.size();
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 1; i < delta_file_size - 1; i++) {
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (size_t j = i + 1; j < delta_file_size; j++) {
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      string output_chunk1, output_chunk2, output_chunk3;
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0],
560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       i,
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       &output_chunk1));
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i],
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       j - i,
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       &output_chunk2));
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[j],
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       delta_file_size - j,
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       &output_chunk3));
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(decoder_.FinishDecoding());
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ(expected_target_,
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                output_chunk1 + output_chunk2 + output_chunk3);
571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef VCDiffInterleavedWindowDecoderTest
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCDiffInterleavedWindowDecoderTestByteByByte;
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedWindowDecoderTestByteByByte, Decode) {
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Windows 3 and 4 use the VCD_TARGET flag, so decoder should signal an error.
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedWindowDecoderTestByteByByte, DecodeNoVcdTarget) {
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.SetAllowVcdTarget(false);
590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t i = 0;
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (; i < delta_file_.size(); ++i) {
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The failure should occur just at the position of the first VCD_TARGET.
598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(delta_file_header_.size() + 83, i);
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The target data for the first two windows should have been output.
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_.substr(0, 89), output_);
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The original version of VCDiffDecoder did not allow the caller to modify the
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// contents of output_string between calls to DecodeChunk().  That restriction
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// has been removed.  Verify that the same result is still produced if the
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// output string is cleared after each call to DecodeChunk().  Use the window
607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// encoding because it refers back to the previously decoded target data, which
608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// is the feature that would fail if the restriction still applied.
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedWindowDecoderTest, OutputStringCanBeModified) {
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  string temp_output;
612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &temp_output));
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    output_.append(temp_output);
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    temp_output.clear();
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedWindowDecoderTest, OutputStringIsPreserved) {
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const string previous_data("Previous data");
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  output_ = previous_data;
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(previous_data + expected_target_, output_);
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A decode job that tests the ability to COPY across the boundary between
634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// source data and target data.
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass VCDiffStandardCrossDecoderTest : public VCDiffDecoderTest {
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kExpectedTarget[];
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kWindowHeader[];
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kWindowBody[];
640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffStandardCrossDecoderTest();
642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~VCDiffStandardCrossDecoderTest() {}
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffStandardCrossDecoderTest::kWindowHeader[] = {
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_SOURCE,  // Win_Indicator: take source from dictionary
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FirstByteOfStringLength(kDictionary),  // Source segment size
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SecondByteOfStringLength(kDictionary),
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Source segment position: start of dictionary
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x15,  // Length of the delta encoding
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    StringLengthAsByte(kExpectedTarget),  // Size of the target window
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x07,  // length of data for ADDs and RUNs
654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x06,  // length of instructions section
655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x03   // length of addresses for COPYs
656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffStandardCrossDecoderTest::kWindowBody[] = {
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD (length 7)
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'S', 'p', 'i', 'd', 'e', 'r', 's',
661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Instructions and sizes (length 6)
662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // VCD_ADD size 0
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x07,  // Size of ADD (7)
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x23,  // VCD_COPY mode VCD_HERE, size 0
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x19,  // Size of COPY (25)
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x14,  // VCD_COPY mode VCD_SELF, size 4
667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x25,  // VCD_COPY mode VCD_HERE, size 5
668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Addresses for COPYs (length 3)
669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x15,  // HERE mode address for 1st copy (21 back from here_address)
670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x06,  // SELF mode address for 2nd copy
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x14   // HERE mode address for 3rd copy
672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffStandardCrossDecoderTest::kExpectedTarget[] =
675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "Spiders in his hair.\n"
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "Spiders in the air.\n";
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottVCDiffStandardCrossDecoderTest::VCDiffStandardCrossDecoderTest() {
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UseStandardFileHeader();
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader));
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  expected_target_.assign(kExpectedTarget);
683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardCrossDecoderTest, Decode) {
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size(),
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef VCDiffStandardCrossDecoderTest VCDiffStandardCrossDecoderTestByteByByte;
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffStandardCrossDecoderTestByteByByte, Decode) {
697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The same decode job that tests the ability to COPY across the boundary
706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// between source data and target data, but using the interleaved format rather
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// than the standard format.
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass VCDiffInterleavedCrossDecoderTest
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : public VCDiffStandardCrossDecoderTest {
710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffInterleavedCrossDecoderTest();
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~VCDiffInterleavedCrossDecoderTest() {}
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kWindowHeader[];
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kWindowBody[];
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffInterleavedCrossDecoderTest::kWindowHeader[] = {
720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_SOURCE,  // Win_Indicator: take source from dictionary
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FirstByteOfStringLength(kDictionary),  // Source segment size
722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SecondByteOfStringLength(kDictionary),
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Source segment position: start of dictionary
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x15,  // Length of the delta encoding
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    StringLengthAsByte(kExpectedTarget),  // Size of the target window
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs
728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x10,  // length of instructions section
729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffInterleavedCrossDecoderTest::kWindowBody[] = {
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x01,  // VCD_ADD size 0
734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x07,  // Size of ADD (7)
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD (length 7)
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'S', 'p', 'i', 'd', 'e', 'r', 's',
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x23,  // VCD_COPY mode VCD_HERE, size 0
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x19,  // Size of COPY (25)
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x15,  // HERE mode address for 1st copy (21 back from here_address)
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x14,  // VCD_COPY mode VCD_SELF, size 4
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x06,  // SELF mode address for 2nd copy
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x25,  // VCD_COPY mode VCD_HERE, size 5
743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x14   // HERE mode address for 3rd copy
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottVCDiffInterleavedCrossDecoderTest::VCDiffInterleavedCrossDecoderTest() {
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UseInterleavedFileHeader();
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader));
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedCrossDecoderTest, Decode) {
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size(),
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedCrossDecoderTest, DecodeWithChecksum) {
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ComputeAndAddChecksum();
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  InitializeDeltaFile();
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size(),
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef VCDiffInterleavedCrossDecoderTest
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCDiffInterleavedCrossDecoderTestByteByByte;
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedCrossDecoderTestByteByByte, Decode) {
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffInterleavedCrossDecoderTestByteByByte, DecodeWithChecksum) {
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ComputeAndAddChecksum();
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  InitializeDeltaFile();
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Test using a custom code table and custom cache sizes with interleaved
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// format.
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass VCDiffCustomCodeTableDecoderTest : public VCDiffInterleavedDecoderTest {
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kFileHeader[];
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kWindowHeader[];
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kWindowBody[];
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char kEncodedCustomCodeTable[];
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffCustomCodeTableDecoderTest();
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~VCDiffCustomCodeTableDecoderTest() {}
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffCustomCodeTableDecoderTest::kFileHeader[] = {
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xD6,  // 'V' | 0x80
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xC3,  // 'C' | 0x80
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xC4,  // 'D' | 0x80
812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'S',   // SDCH version code
813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02   // Hdr_Indicator: Use custom code table
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Make a custom code table that includes exactly the instructions we need
817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to encode the first test's data without using any explicit length values.
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Be careful not to replace any existing opcodes that have size 0,
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to ensure that the custom code table is valid (can express all possible
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// values of inst (also known as instruction type) and mode with size 0.)
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This encoding uses interleaved format, which is easier to read.
822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Here are the changes to the standard code table:
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ADD size 2 (opcode 3) => RUN size 2 (inst1[3] = VCD_RUN)
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ADD size 16 (opcode 17) => ADD size 27 (size1[17] = 27)
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ADD size 17 (opcode 18) => ADD size 61 (size1[18] = 61)
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// COPY mode 0 size 18 (opcode 34) => COPY mode 0 size 28 (size1[34] = 28)
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// COPY mode 1 size 18 (opcode 50) => COPY mode 1 size 44 (size1[50] = 44)
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffCustomCodeTableDecoderTest::kEncodedCustomCodeTable[] = {
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xD6,  // 'V' | 0x80
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xC3,  // 'C' | 0x80
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xC4,  // 'D' | 0x80
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'S',   // SDCH version code
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Hdr_Indicator: no custom code table, no compression
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_SOURCE,  // Win_Indicator: take source from dictionary
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    (sizeof(VCDiffCodeTableData) >> 7) | 0x80,  // First byte of table length
838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    sizeof(VCDiffCodeTableData) & 0x7F,  // Second byte of table length
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Source segment position: start of default code table
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1F,  // Length of the delta encoding
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    (sizeof(VCDiffCodeTableData) >> 7) | 0x80,  // First byte of table length
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    sizeof(VCDiffCodeTableData) & 0x7F,  // Second byte of table length
843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs (unused)
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x19,  // length of interleaved section
846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of addresses for COPYs (unused)
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x05,  // VCD_ADD size 4
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD (length 4)
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_RUN, VCD_ADD, VCD_ADD, VCD_RUN,
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x13,  // VCD_COPY mode VCD_SELF size 0
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x84,  // Size of copy: upper bits (512 - 4 + 17 = 525)
852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x0D,  // Size of copy: lower bits
853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x04,  // Address of COPY
854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x03,  // VCD_ADD size 2
855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD (length 2)
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1B, 0x3D,
857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x3F,  // VCD_COPY mode VCD_NEAR(0) size 15
858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x84,  // Address of copy: upper bits (525 + 2 = 527)
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x0F,  // Address of copy: lower bits
860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // VCD_ADD size 1
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD (length 1)
862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x1C,
863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x4F,  // VCD_COPY mode VCD_NEAR(1) size 15
864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x10,  // Address of copy
865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x02,  // VCD_ADD size 1
866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD (length 1)
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x2C,
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x53,  // VCD_COPY mode VCD_NEAR(2) size 0
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x87,  // Size of copy: upper bits (256 * 4 - 51 = 973)
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x4D,  // Size of copy: lower bits
871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x10   // Address of copy
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This is similar to VCDiffInterleavedDecoderTest, but uses the custom code
875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// table to eliminate the need to explicitly encode instruction sizes.
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Notice that NEAR(0) mode is used here where NEAR(1) mode was used in
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// VCDiffInterleavedDecoderTest.  This is because the custom code table
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// has the size of the NEAR cache set to 1; only the most recent
879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// COPY instruction is available.  This will also be a test of
880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// custom cache sizes.
881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffCustomCodeTableDecoderTest::kWindowHeader[] = {
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCD_SOURCE,  // Win_Indicator: take source from dictionary
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FirstByteOfStringLength(kDictionary),  // Source segment size
884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SecondByteOfStringLength(kDictionary),
885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Source segment position: start of dictionary
886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x74,  // Length of the delta encoding
887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FirstByteOfStringLength(kExpectedTarget),  // Size of the target window
888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SecondByteOfStringLength(kExpectedTarget),
889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Delta_indicator (no compression)
890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // length of data for ADDs and RUNs (unused)
891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x6E,  // length of interleaved section
892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00   // length of addresses for COPYs (unused)
893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char VCDiffCustomCodeTableDecoderTest::kWindowBody[] = {
896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x22,  // VCD_COPY mode VCD_SELF, size 28
897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Address of COPY: Start of dictionary
898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x12,  // VCD_ADD size 61
899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD (length 61)
900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ',
901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n',
902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'T', 'h', 'a', 't', ' ',
903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ',
904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ',
905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n',
906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x32,  // VCD_COPY mode VCD_HERE, size 44
907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x58,  // HERE mode address (27+61 back from here_address)
908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xBF,  // VCD_ADD size 2 + VCD_COPY mode NEAR(0), size 5
909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADDs: 2nd section (length 2)
910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'h', 'r',
911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x2D,  // NEAR(0) mode address (45 after prior address)
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x0A,  // VCD_ADD size 9
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADDs: 3rd section (length 9)
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'W', 'h', 'a', 't', ' ',
915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'I', ' ', 't', 'e',
916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x03,  // VCD_RUN size 2
917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for RUN: 4th section (length 1)
918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    'l',
919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x11,  // VCD_ADD size 27
920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Data for ADD: 4th section (length 27)
921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ' ', 'y', 'o', 'u', ' ',
922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ',
923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    't', 'r', 'u', 'e', '.', '\"', '\n'
924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottVCDiffCustomCodeTableDecoderTest::VCDiffCustomCodeTableDecoderTest() {
927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.assign(kFileHeader, sizeof(kFileHeader));
928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.push_back(0x01);  // NEAR cache size (custom)
929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.push_back(0x06);  // SAME cache size (custom)
930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.append(kEncodedCustomCodeTable,
931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            sizeof(kEncodedCustomCodeTable));
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader));
933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffCustomCodeTableDecoderTest, CustomCodeTableEncodingMatches) {
937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffCodeTableData custom_code_table(
938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCDiffCodeTableData::kDefaultCodeTableData);
939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  custom_code_table.inst1[3] = VCD_RUN;
940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  custom_code_table.size1[17] = 27;
941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  custom_code_table.size1[18] = 61;
942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  custom_code_table.size1[34] = 28;
943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  custom_code_table.size1[50] = 44;
944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reinterpret_cast<const char*>(
947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &VCDiffCodeTableData::kDefaultCodeTableData),
948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sizeof(VCDiffCodeTableData::kDefaultCodeTableData));
949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(kEncodedCustomCodeTable,
950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   sizeof(kEncodedCustomCodeTable),
951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(sizeof(custom_code_table), output_.size());
954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const VCDiffCodeTableData* decoded_table =
955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reinterpret_cast<const VCDiffCodeTableData*>(output_.data());
956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_RUN, decoded_table->inst1[0]);
957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_RUN, decoded_table->inst1[3]);
958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(27, decoded_table->size1[17]);
959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(61, decoded_table->size1[18]);
960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(28, decoded_table->size1[34]);
961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(44, decoded_table->size1[50]);
962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < VCDiffCodeTableData::kCodeTableSize; ++i) {
963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(custom_code_table.inst1[i], decoded_table->inst1[i]);
964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(custom_code_table.inst2[i], decoded_table->inst2[i]);
965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(custom_code_table.size1[i], decoded_table->size1[i]);
966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(custom_code_table.size2[i], decoded_table->size2[i]);
967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(custom_code_table.mode1[i], decoded_table->mode1[i]);
968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(custom_code_table.mode2[i], decoded_table->mode2[i]);
969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffCustomCodeTableDecoderTest, DecodeUsingCustomCodeTable) {
973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_.size(),
976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffCustomCodeTableDecoderTest, IncompleteCustomCodeTable) {
982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(),
984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   delta_file_header_.size() - 1,
985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   &output_));
986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(decoder_.FinishDecoding());
987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ("", output_);
988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef VCDiffCustomCodeTableDecoderTest
991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCDiffCustomCodeTableDecoderTestByteByByte;
992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, DecodeUsingCustomCodeTable) {
994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, IncompleteCustomCodeTable) {
1003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_.resize(delta_file_header_.size() - 1);
1004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
1006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
1007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(decoder_.FinishDecoding());
1009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ("", output_);
1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, CustomTableNoVcdTarget) {
1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.SetAllowVcdTarget(false);
1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < delta_file_.size(); ++i) {
1016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(decoder_.FinishDecoding());
1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(expected_target_, output_);
1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef GTEST_HAS_DEATH_TEST
1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef VCDiffCustomCodeTableDecoderTest VCDiffCustomCodeTableDecoderDeathTest;
1024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffCustomCodeTableDecoderDeathTest, BadCustomCacheSizes) {
1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.assign(kFileHeader, sizeof(kFileHeader));
1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.push_back(0x81);  // NEAR cache size (top bit)
1028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.push_back(0x10);  // NEAR cache size (custom value 0x90)
1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.push_back(0x81);  // SAME cache size (top bit)
1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.push_back(0x10);  // SAME cache size (custom value 0x90)
1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.append(kEncodedCustomCodeTable,
1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            sizeof(kEncodedCustomCodeTable));
1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  InitializeDeltaFile();
1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_DEBUG_DEATH(EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                       delta_file_.size(),
1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                       &output_)),
1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     "cache");
1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ("", output_);
1040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(VCDiffCustomCodeTableDecoderDeathTest, BadCustomCacheSizesNoVcdTarget) {
1043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.SetAllowVcdTarget(false);
1044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.assign(kFileHeader, sizeof(kFileHeader));
1045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.push_back(0x81);  // NEAR cache size (top bit)
1046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.push_back(0x10);  // NEAR cache size (custom value 0x90)
1047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.push_back(0x81);  // SAME cache size (top bit)
1048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.push_back(0x10);  // SAME cache size (custom value 0x90)
1049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delta_file_header_.append(kEncodedCustomCodeTable,
1050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            sizeof(kEncodedCustomCodeTable));
1051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  InitializeDeltaFile();
1052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_DEBUG_DEATH(EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
1054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                       delta_file_.size(),
1055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                       &output_)),
1056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     "cache");
1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ("", output_);
1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // GTEST_HAS_DEATH_TEST
1061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1062c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace open_vcdiff
1063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // unnamed namespace
1064