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