1311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Copyright 2008 Google Inc.
2311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Author: Lincoln Smith
3311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff//
4311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Licensed under the Apache License, Version 2.0 (the "License");
5311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// you may not use this file except in compliance with the License.
6311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// You may obtain a copy of the License at
7311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff//
8311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff//      http://www.apache.org/licenses/LICENSE-2.0
9311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff//
10311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Unless required by applicable law or agreed to in writing, software
11311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// distributed under the License is distributed on an "AS IS" BASIS,
12311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// See the License for the specific language governing permissions and
14311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// limitations under the License.
15311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
16311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <config.h>
17311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "google/vcdecoder.h"
1828db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff#include <stdlib.h>  // free, posix_memalign
1928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff#include <string.h>  // memcpy
20311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <string>
21311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "testing.h"
22311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "varint_bigendian.h"
23311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "vcdecoder_test.h"
24311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "vcdiff_defs.h"  // VCD_SOURCE
25311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
26311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_MALLOC_H
27311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <malloc.h>
28311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_MALLOC_H
29311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
30311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_SYS_MMAN_H
31732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com#if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
32732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com#undef  _XOPEN_SOURCE
33311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#define _XOPEN_SOURCE 600  // posix_memalign
34732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com#endif
35311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <sys/mman.h>  // mprotect
36311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_SYS_MMAN_H
37311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
38311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_UNISTD_H
39311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <unistd.h>  // getpagesize
40311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_UNISTD_H
41311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
42311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffnamespace open_vcdiff {
43311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
44311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Test headers, valid and invalid.
45311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
46311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, DecodeHeaderOnly) {
47311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
48311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(),
49311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_file_header_.size(),
50311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &output_));
51311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
52311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
53311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
54311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
55311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, PartialHeaderNotEnough) {
56311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
57311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(),
58311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_file_header_.size() - 2,
59311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &output_));
60311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.FinishDecoding());
61311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
62311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
63311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
64311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, BadMagicNumber) {
65311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[1] = 'Q' | 0x80;
66311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
67311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
68311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
69311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
70311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
71311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
72311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
73311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, BadVersionNumber) {
74311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[3] = 0x01;
75311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
76311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
77311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
78311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
79311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
80311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
81311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
82311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, SecondaryCompressionNotSupported) {
83311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[4] = 0x01;
84311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
85311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
86311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
87311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
88311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
89311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
90311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
91311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, Decode) {
92311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
93311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
94311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_file_.size(),
95311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &output_));
96311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
97732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(expected_target_.c_str(), output_);
98311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
99311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
100311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, DecodeWithChecksum) {
101311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ComputeAndAddChecksum();
102311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  InitializeDeltaFile();
103311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
104311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
105311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_file_.size(),
106311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &output_));
107311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
108732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(expected_target_.c_str(), output_);
109311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
110311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
111311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, ChecksumDoesNotMatch) {
112311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  AddChecksum(0xBADBAD);
113311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  InitializeDeltaFile();
114311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
115311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
116311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
117311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
118311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
119311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
120311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
121311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, ChecksumIsInvalid64BitVarint) {
122311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  static const char kInvalidVarint[] = { 0x81, 0x80, 0x80, 0x80, 0x80, 0x80,
123311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                         0x80, 0x80, 0x80, 0x00 };
124311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_window_header_[0] |= VCD_CHECKSUM;
125311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_window_header_.append(kInvalidVarint, sizeof(kInvalidVarint));
126311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Adjust delta window size to include size of invalid Varint.
127311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string size_of_invalid_varint;
128311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VarintBE<int32_t>::AppendToString(
129311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      static_cast<int32_t>(delta_window_header_[4] + sizeof(kInvalidVarint)),
130311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      &size_of_invalid_varint);
131311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_window_header_.replace(4, 1, size_of_invalid_varint);
132311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  InitializeDeltaFile();
133311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
134311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
135311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
136311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
137311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
138311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
139311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
140311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Remove one byte from the length of the chunk to process, and
141311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// verify that an error is returned for FinishDecoding().
142311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, FinishAfterDecodingPartialWindow) {
143311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
144311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
145311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_file_.size() - 1,
146311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &output_));
147311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.FinishDecoding());
148311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
149311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
150311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
151311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
152311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, FinishAfterDecodingPartialWindowHeader) {
153311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
154311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
155311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_file_header_.size()
156311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                       + delta_window_header_.size() - 1,
157311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &output_));
158311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.FinishDecoding());
159311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
160311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
161311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
162311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
16328db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiffTEST_F(VCDiffInterleavedDecoderTest, TargetMatchesWindowSizeLimit) {
16428db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.SetMaximumTargetWindowSize(expected_target_.size());
16528db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
16628db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
16728db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff                                   delta_file_.size(),
16828db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff                                   &output_));
16928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
170732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(expected_target_.c_str(), output_);
17128db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff}
17228db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff
17328db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiffTEST_F(VCDiffInterleavedDecoderTest, TargetMatchesFileSizeLimit) {
17428db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.SetMaximumTargetFileSize(expected_target_.size());
17528db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
17628db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
17728db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff                                   delta_file_.size(),
17828db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff                                   &output_));
17928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
180732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(expected_target_.c_str(), output_);
18128db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff}
18228db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff
18328db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiffTEST_F(VCDiffInterleavedDecoderTest, TargetExceedsWindowSizeLimit) {
18428db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.SetMaximumTargetWindowSize(expected_target_.size() - 1);
18528db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
18628db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
18728db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff                                    delta_file_.size(),
18828db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff                                    &output_));
18928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_EQ("", output_);
19028db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff}
19128db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff
19228db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiffTEST_F(VCDiffInterleavedDecoderTest, TargetExceedsFileSizeLimit) {
19328db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.SetMaximumTargetFileSize(expected_target_.size() - 1);
19428db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
19528db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
19628db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff                                    delta_file_.size(),
19728db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff                                    &output_));
19828db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_EQ("", output_);
19928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff}
20028db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff
201311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Fuzz bits to make sure decoder does not violently crash.
202311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// This test has no expected behavior except that no crashes should occur.
203311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// In some cases, changing bits will still decode to the correct target;
204311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// for example, changing unused bits within a bitfield.
205311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, FuzzBits) {
206311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  while (FuzzOneByteInDeltaFile()) {
207311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
208311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (decoder_.DecodeChunk(delta_file_.data(),
209311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                             delta_file_.size(),
210311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                             &output_)) {
211311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      decoder_.FinishDecoding();
212311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
213311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    InitializeDeltaFile();
214311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    output_.clear();
215311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
216311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
217311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
218311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// If a checksum is present, then fuzzing any of the bits may produce an error,
219311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// but it should not result in an incorrect target being produced without
220311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// an error.
221311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, FuzzBitsWithChecksum) {
222311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ComputeAndAddChecksum();
223311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  InitializeDeltaFile();
224311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  while (FuzzOneByteInDeltaFile()) {
225311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
226311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (decoder_.DecodeChunk(delta_file_.data(),
227311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                             delta_file_.size(),
228311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                             &output_)) {
229311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      if (decoder_.FinishDecoding()) {
230311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff        // Decoding succeeded.  Make sure the correct target was produced.
231732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com        EXPECT_EQ(expected_target_.c_str(), output_);
232311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      }
233311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    } else {
234311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ("", output_);
235311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
236311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    InitializeDeltaFile();
237311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    output_.clear();
238311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
239311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
240311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
241311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopyMoreThanExpectedTarget) {
242311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0C] =
243311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      FirstByteOfStringLength(kExpectedTarget);
244311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0D] =
245311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      SecondByteOfStringLength(kExpectedTarget) + 1;
246311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
247311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
248311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
249311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
250311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
251311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
252311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
253311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopySizeZero) {
254311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0C] = 0;
255311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
256311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
257311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
258311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
259311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
260311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
261311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
262311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopySizeTooLargeByOne) {
263311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ++delta_file_[delta_file_header_.size() + 0x0C];
264311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
265311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
266311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
267311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
268311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
269311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
270311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
271311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopySizeTooSmallByOne) {
272311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  --delta_file_[delta_file_header_.size() + 0x0C];
273311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
274311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
275311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
276311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
277311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
278311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
279311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
280311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopySizeMaxInt) {
281311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteMaxVarintAtOffset(0x0C, 1);
282311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
283311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
284311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
285311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
286311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
287311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
288311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
289311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopySizeNegative) {
290311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteNegativeVarintAtOffset(0x0C, 1);
291311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
292311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
293311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
294311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
295311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
296311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
297311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
298311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopySizeInvalid) {
299311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteInvalidVarintAtOffset(0x0C, 1);
300311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
301311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
302311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
303311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
304311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
305311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
306311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
307311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopyAddressBeyondHereAddress) {
308311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0D] =
309311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      FirstByteOfStringLength(kDictionary);
310311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0E] =
311311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      SecondByteOfStringLength(kDictionary);
312311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
313311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
314311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
315311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
316311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
317311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
318311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
319311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopyAddressMaxInt) {
320311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteMaxVarintAtOffset(0x0D, 1);
321311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
322311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
323311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
324311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
325311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
326311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
327311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
328311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopyAddressNegative) {
329311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteNegativeVarintAtOffset(0x0D, 1);
330311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
331311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
332311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
333311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
334311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
335311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
336311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
337311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, CopyAddressInvalid) {
338311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteInvalidVarintAtOffset(0x0D, 1);
339311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
340311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
341311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
342311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
343311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
344311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
345311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
346311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, AddMoreThanExpectedTarget) {
347311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0F] =
348311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      FirstByteOfStringLength(kExpectedTarget);
349311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x10] =
350311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      SecondByteOfStringLength(kExpectedTarget) + 1;
351311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
352311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
353311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
354311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
355311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
356311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
357311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
358311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, AddSizeZero) {
359311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0F] = 0;
360311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
361311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
362311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
363311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
364311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
365311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
366311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
367311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, AddSizeTooLargeByOne) {
368311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ++delta_file_[delta_file_header_.size() + 0x0F];
369311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
370311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
371311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
372311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
373311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
374311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
375311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
376311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, AddSizeTooSmallByOne) {
377311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  --delta_file_[delta_file_header_.size() + 0x0F];
378311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
379311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
380311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
381311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
382311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
383311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
384311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
385311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, AddSizeMaxInt) {
386311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteMaxVarintAtOffset(0x0F, 1);
387311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
388311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
389311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
390311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
391311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
392311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
393311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
394311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, AddSizeNegative) {
395311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteNegativeVarintAtOffset(0x0F, 1);
396311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
397311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
398311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
399311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
400311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
401311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
402311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
403311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, AddSizeInvalid) {
404311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteInvalidVarintAtOffset(0x0F, 1);
405311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
406311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
407311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
408311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
409311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
410311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
411311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
412311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, RunMoreThanExpectedTarget) {
413311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x5F] =
414311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      FirstByteOfStringLength(kExpectedTarget);
415311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x60] =
416311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      SecondByteOfStringLength(kExpectedTarget) + 1;
417311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
418311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
419311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
420311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
421311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
422311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
423311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
424311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, RunSizeZero) {
425311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x5F] = 0;
426311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
427311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
428311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
429311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
430311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
431311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
432311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
433311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, RunSizeTooLargeByOne) {
434311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ++delta_file_[delta_file_header_.size() + 0x5F];
435311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
436311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
437311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
438311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
439311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
440311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
441311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
442311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, RunSizeTooSmallByOne) {
443311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  --delta_file_[delta_file_header_.size() + 0x5F];
444311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
445311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
446311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
447311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
448311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
449311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
450311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
451311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, RunSizeMaxInt) {
452311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteMaxVarintAtOffset(0x5F, 1);
453311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
454311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
455311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
456311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
457311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
458311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
459311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
460311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, RunSizeNegative) {
461311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteNegativeVarintAtOffset(0x5F, 1);
462311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
463311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
464311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
465311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
466311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
467311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
468311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
469311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, RunSizeInvalid) {
470311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteInvalidVarintAtOffset(0x5F, 1);
471311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
472311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
473311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    delta_file_.size(),
474311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    &output_));
475311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
476311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
477311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
478311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#if defined(HAVE_MPROTECT) && \
479311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff   (defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN))
480311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, ShouldNotReadPastEndOfBuffer) {
481311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Allocate two memory pages.
482311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const int page_size = getpagesize();
483311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void* two_pages = NULL;
484311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_POSIX_MEMALIGN
485311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  posix_memalign(&two_pages, page_size, 2 * page_size);
486311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#else  // !HAVE_POSIX_MEMALIGN
487311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  two_pages = memalign(page_size, 2 * page_size);
488311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_POSIX_MEMALIGN
489311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* const first_page = reinterpret_cast<char*>(two_pages);
490311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* const second_page = first_page + page_size;
491311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
492311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Place the delta string at the end of the first page.
493311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* delta_with_guard = second_page - delta_file_.size();
494311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  memcpy(delta_with_guard, delta_file_.data(), delta_file_.size());
495311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
496311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Make the second page unreadable.
497311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  mprotect(second_page, page_size, PROT_NONE);
498311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
499311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Now perform the decode operation, which will cause a segmentation fault
500311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // if it reads past the end of the buffer.
501311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
502311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_with_guard,
503311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_file_.size(),
504311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &output_));
505311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
506732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(expected_target_.c_str(), output_);
507311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
508311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Undo the mprotect.
509311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  mprotect(second_page, page_size, PROT_READ|PROT_WRITE);
510311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  free(two_pages);
511311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
512311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
513311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTest, ShouldNotReadPastBeginningOfBuffer) {
514311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Allocate two memory pages.
515311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const int page_size = getpagesize();
516311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void* two_pages = NULL;
517311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_POSIX_MEMALIGN
518311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  posix_memalign(&two_pages, page_size, 2 * page_size);
519311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#else  // !HAVE_POSIX_MEMALIGN
520311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  two_pages = memalign(page_size, 2 * page_size);
521311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_POSIX_MEMALIGN
522311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* const first_page = reinterpret_cast<char*>(two_pages);
523311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* const second_page = first_page + page_size;
524311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
525311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Make the first page unreadable.
526311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  mprotect(first_page, page_size, PROT_NONE);
527311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
528311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Place the delta string at the beginning of the second page.
529311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* delta_with_guard = second_page;
530311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  memcpy(delta_with_guard, delta_file_.data(), delta_file_.size());
531311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
532311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Now perform the decode operation, which will cause a segmentation fault
533311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // if it reads past the beginning of the buffer.
534311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
535311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_with_guard,
536311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_file_.size(),
537311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &output_));
538311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
539732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(expected_target_.c_str(), output_);
540311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
541311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Undo the mprotect.
542311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  mprotect(first_page, page_size, PROT_READ|PROT_WRITE);
543311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  free(two_pages);
544311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
545311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_MPROTECT && (HAVE_MEMALIGN || HAVE_POSIX_MEMALIGN)
546311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
547311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// These are the same tests as for VCDiffInterleavedDecoderTest, with the added
548311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// complication that instead of calling DecodeChunk() once with the entire data
549311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// set, DecodeChunk() is called once for each byte of input.  This is intended
550311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// to shake out any bugs with rewind and resume while parsing chunked data.
551311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
552311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdifftypedef VCDiffInterleavedDecoderTest VCDiffInterleavedDecoderTestByteByByte;
553311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
554311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Test headers, valid and invalid.
555311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
556311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, DecodeHeaderOnly) {
557311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
558311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_header_.size(); ++i) {
559311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_header_[i], 1, &output_));
560311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
561311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
562311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
563311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
564311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
565311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, PartialHeaderNotEnough) {
566311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_.resize(delta_file_header_.size() - 2);
567311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
568311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
569311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
570311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
571311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(decoder_.FinishDecoding());
572311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
573311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
574311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
575311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, BadMagicNumber) {
576311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[1] = 'Q' | 0x80;
577311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
578311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
579311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
580311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
581311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
582311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(1U, i);
583311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
584311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
585311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
586311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
587311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
588311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
589311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
590311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
591311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, BadVersionNumber) {
592311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[3] = 0x01;
593311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
594311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
595311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
596311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
597311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
598311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
599311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(3U, i);
600311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
601311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
602311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
603311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
604311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
605311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
606311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
607311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte,
608311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff       SecondaryCompressionNotSupported) {
609311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[4] = 0x01;
610311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
611311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
612311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
613311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
614311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
615311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
616311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(4U, i);
617311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
618311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
619311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
620311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
621311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
622311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
623311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
624311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, Decode) {
625311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
626311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
627311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
628311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
629311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
630732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(expected_target_.c_str(), output_);
631311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
632311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
633311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, DecodeWithChecksum) {
634311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ComputeAndAddChecksum();
635311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  InitializeDeltaFile();
636311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
637311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
638311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
639311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
640311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
641732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(expected_target_.c_str(), output_);
642311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
643311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
644311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, ChecksumDoesNotMatch) {
645311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  AddChecksum(0xBADBAD);
646311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  InitializeDeltaFile();
647311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
648311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
649311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
650311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
651311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
652311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail after decoding the entire delta file
653311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_.size() - 1, i);
654311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
655311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
656311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
657311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
658311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
659311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
660311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
661311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
662311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, ChecksumIsInvalid64BitVarint) {
663311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  static const char kInvalidVarint[] = { 0x81, 0x80, 0x80, 0x80, 0x80, 0x80,
664311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                         0x80, 0x80, 0x80, 0x00 };
665311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_window_header_[0] |= VCD_CHECKSUM;
666311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_window_header_.append(kInvalidVarint, sizeof(kInvalidVarint));
667311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Adjust delta window size to include size of invalid Varint.
668311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string size_of_invalid_varint;
669311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VarintBE<int32_t>::AppendToString(
670311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      static_cast<int32_t>(delta_window_header_[4] + sizeof(kInvalidVarint)),
671311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      &size_of_invalid_varint);
672311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_window_header_.replace(4, 1, size_of_invalid_varint);
673311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  InitializeDeltaFile();
674311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
675311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
676311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
677311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
678311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
679311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail while trying to interpret the checksum.
680311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + delta_window_header_.size() - 2, i);
681311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
682311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
683311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
684311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
685311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
686311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
687311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
688311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
68928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, TargetMatchesWindowSizeLimit) {
69028db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.SetMaximumTargetWindowSize(expected_target_.size());
69128db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
69228db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
69328db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
69428db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  }
69528db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
696732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(expected_target_.c_str(), output_);
69728db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff}
69828db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff
69928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, TargetMatchesFileSizeLimit) {
70028db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.SetMaximumTargetFileSize(expected_target_.size());
70128db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
70228db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
70328db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff    EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
70428db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  }
70528db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
706732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(expected_target_.c_str(), output_);
70728db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff}
70828db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff
70928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, TargetExceedsWindowSizeLimit) {
71028db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.SetMaximumTargetWindowSize(expected_target_.size() - 1);
71128db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
71228db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  bool failed = false;
71328db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
71428db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
71528db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff      failed = true;
71628db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff      break;
71728db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff    }
71828db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  }
71928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_TRUE(failed);
72028db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_EQ("", output_);
72128db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff}
72228db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff
72328db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, TargetExceedsFileSizeLimit) {
72428db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.SetMaximumTargetFileSize(expected_target_.size() - 1);
72528db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
72628db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  bool failed = false;
72728db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
72828db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
72928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff      failed = true;
73028db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff      break;
73128db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff    }
73228db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  }
73328db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_TRUE(failed);
73428db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  EXPECT_EQ("", output_);
73528db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff}
73628db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff
737311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Fuzz bits to make sure decoder does not violently crash.
738311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// This test has no expected behavior except that no crashes should occur.
739311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// In some cases, changing bits will still decode to the correct target;
740311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// for example, changing unused bits within a bitfield.
741311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, FuzzBits) {
742311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  while (FuzzOneByteInDeltaFile()) {
743311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
744311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    bool failed = false;
745311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    for (size_t i = 0; i < delta_file_.size(); ++i) {
746311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
747311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff        failed = true;
748311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff        break;
749311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      }
750311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
751311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!failed) {
752311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      decoder_.FinishDecoding();
753311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
754311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    InitializeDeltaFile();
755311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    output_.clear();
756311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
757311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
758311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
759311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// If a checksum is present, then fuzzing any of the bits may produce an error,
760311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// but it should not result in an incorrect target being produced without
761311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// an error.
762311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, FuzzBitsWithChecksum) {
763311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ComputeAndAddChecksum();
764311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  InitializeDeltaFile();
765311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  while (FuzzOneByteInDeltaFile()) {
766311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
767311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    bool failed = false;
768311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    for (size_t i = 0; i < delta_file_.size(); ++i) {
769311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
770311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff        failed = true;
771311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff        break;
772311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      }
773311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
774311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!failed) {
775311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      if (decoder_.FinishDecoding()) {
776311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff        // Decoding succeeded.  Make sure the correct target was produced.
777732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com        EXPECT_EQ(expected_target_.c_str(), output_);
778311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      }
779311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
780311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // The decoder should not create more target bytes than were expected.
781311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_GE(expected_target_.size(), output_.size());
782311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    InitializeDeltaFile();
783311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    output_.clear();
784311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
785311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
786311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
787311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte,
788311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff       CopyInstructionsShouldFailIfNoSourceSegment) {
789311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Replace the Win_Indicator and the source size and source offset with a
790311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // single 0 byte (a Win_Indicator for a window with no source segment.)
791311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_window_header_.replace(0, 4, "\0", 1);
792311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  InitializeDeltaFile();
793311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
794311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
795311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
796311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
797311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
798311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // The first COPY instruction should fail.
799311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + delta_window_header_.size() + 2, i);
800311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
801311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
802311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
803311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
804311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ("", output_);
805311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
806311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
807311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyMoreThanExpectedTarget) {
808311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0C] =
809311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      FirstByteOfStringLength(kExpectedTarget);
810311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0D] =
811311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      SecondByteOfStringLength(kExpectedTarget) + 1;
812311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
813311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
814311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
815311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
816311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
817311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
818311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x0D, i);
819311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
820311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
821311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
822311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
823311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
824311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
825311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
826311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
827311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// A COPY instruction with an explicit size of 0 is not illegal according to the
828311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// standard, although it is inefficient and should not be generated by any
829311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// reasonable encoder.  Changing the size of a COPY instruction to zero will
830311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// cause a failure because the generated target window size will not match the
831311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// expected target size.
832311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeZero) {
833311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0C] = 0;
834311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
835311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
836311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
837311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
838311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
839311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
840311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
841311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
842311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
843311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
844311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
845311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
846311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
847311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeTooLargeByOne) {
848311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ++delta_file_[delta_file_header_.size() + 0x0C];
849311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
850311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
851311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
852311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
853311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
854311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
855311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
856311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
857311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
858311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
859311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
860311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
861311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
862311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeTooSmallByOne) {
863311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  --delta_file_[delta_file_header_.size() + 0x0C];
864311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
865311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
866311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
867311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
868311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
869311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
870311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
871311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
872311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
873311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
874311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
875311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
876311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
877311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeMaxInt) {
878311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteMaxVarintAtOffset(0x0C, 1);
879311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
880311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
881311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
882311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
883311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
884311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
885311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x10, i);
886311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
887311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
888311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
889311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
890311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
891311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
892311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
893311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
894311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeNegative) {
895311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteNegativeVarintAtOffset(0x0C, 1);
896311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
897311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
898311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
899311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
900311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
901311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
902f1dd933c4e47a65889b4bba2a5f58b12aac53383openvcdiff@gmail.com      EXPECT_EQ(delta_file_header_.size() + 0x0F, i);
903311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
904311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
905311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
906311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
907311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
908311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
909311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
910311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
911311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopySizeInvalid) {
912311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteInvalidVarintAtOffset(0x0C, 1);
913311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
914311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
915311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
916311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
917311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
918311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
919311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x10, i);
920311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
921311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
922311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
923311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
924311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
925311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
926311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
927311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
928311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressBeyondHereAddress) {
929311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0D] =
930311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      FirstByteOfStringLength(kDictionary);
931311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0E] =
932311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      SecondByteOfStringLength(kDictionary);
933311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
934311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
935311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
936311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
937311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
938311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
939311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x0E, i);
940311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
941311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
942311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
943311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
944311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
945311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
946311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
947311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
948311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressMaxInt) {
949311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteMaxVarintAtOffset(0x0D, 1);
950311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
951311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
952311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
953311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
954311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
955311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
956311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x11, i);
957311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
958311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
959311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
960311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
961311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
962311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
963311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
964311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
965311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressNegative) {
966311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteNegativeVarintAtOffset(0x0D, 1);
967311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
968311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
969311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
970311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
971311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
972311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
973f1dd933c4e47a65889b4bba2a5f58b12aac53383openvcdiff@gmail.com      EXPECT_EQ(delta_file_header_.size() + 0x10, i);
974311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
975311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
976311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
977311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
978311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
979311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
980311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
981311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
982311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, CopyAddressInvalid) {
983311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteInvalidVarintAtOffset(0x0D, 1);
984311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
985311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
986311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
987311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
988311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
989311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
990311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x11, i);
991311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
992311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
993311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
994311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
995311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
996311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
997311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
998311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
999311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, AddMoreThanExpectedTarget) {
1000311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0F] =
1001311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      FirstByteOfStringLength(kExpectedTarget);
1002311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x10] =
1003311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      SecondByteOfStringLength(kExpectedTarget) + 1;
1004311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1005311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1006311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1007311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1008311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1009311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
1010311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x10, i);
1011311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1012311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1013311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1014311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1015311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1016311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1017311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1018311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1019311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// An ADD instruction with an explicit size of 0 is not illegal according to the
1020311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// standard, although it is inefficient and should not be generated by any
1021311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// reasonable encoder.  Changing the size of an ADD instruction to zero will
1022311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// cause a failure because the generated target window size will not match the
1023311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// expected target size.
1024311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeZero) {
1025311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x0F] = 0;
1026311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1027311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1028311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1029311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1030311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1031311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1032311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1033311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1034311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1035311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1036311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1037311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1038311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1039311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeTooLargeByOne) {
1040311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ++delta_file_[delta_file_header_.size() + 0x0F];
1041311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1042311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1043311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1044311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1045311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1046311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1047311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1048311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1049311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1050311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1051311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1052311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1053311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1054311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeTooSmallByOne) {
1055311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  --delta_file_[delta_file_header_.size() + 0x0F];
1056311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1057311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1058311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1059311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1060311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1061311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1062311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1063311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1064311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1065311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1066311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1067311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1068311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1069311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeMaxInt) {
1070311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteMaxVarintAtOffset(0x0F, 1);
1071311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1072311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1073311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1074311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1075311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1076311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
1077311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x13, i);
1078311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1079311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1080311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1081311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1082311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1083311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1084311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1085311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1086311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeNegative) {
1087311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteNegativeVarintAtOffset(0x0F, 1);
1088311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1089311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1090311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1091311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1092311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1093311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
1094f1dd933c4e47a65889b4bba2a5f58b12aac53383openvcdiff@gmail.com      EXPECT_EQ(delta_file_header_.size() + 0x12, i);
1095311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1096311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1097311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1098311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1099311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1100311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1101311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1102311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1103311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, AddSizeInvalid) {
1104311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteInvalidVarintAtOffset(0x0F, 1);
1105311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1106311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1107311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1108311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1109311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1110311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
1111311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x13, i);
1112311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1113311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1114311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1115311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1116311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1117311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1118311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1119311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1120311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, RunMoreThanExpectedTarget) {
1121311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x5F] =
1122311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      FirstByteOfStringLength(kExpectedTarget);
1123311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x60] =
1124311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      SecondByteOfStringLength(kExpectedTarget) + 1;
1125311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1126311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1127311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1128311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1129311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1130311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
1131311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x60, i);
1132311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1133311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1134311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1135311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1136311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1137311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1138311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1139311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1140311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// A RUN instruction with an explicit size of 0 is not illegal according to the
1141311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// standard, although it is inefficient and should not be generated by any
1142311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// reasonable encoder.  Changing the size of a RUN instruction to zero will
1143311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// cause a failure because the generated target window size will not match the
1144311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// expected target size.
1145311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeZero) {
1146311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta_file_[delta_file_header_.size() + 0x5F] = 0;
1147311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1148311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1149311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1150311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1151311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1152311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1153311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1154311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1155311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1156311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1157311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1158311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1159311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1160311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeTooLargeByOne) {
1161311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ++delta_file_[delta_file_header_.size() + 0x5F];
1162311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1163311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1164311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1165311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1166311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1167311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1168311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1169311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1170311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1171311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1172311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1173311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1174311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1175311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeTooSmallByOne) {
1176311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  --delta_file_[delta_file_header_.size() + 0x5F];
1177311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1178311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1179311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1180311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1181311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1182311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1183311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1184311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1185311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1186311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1187311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1188311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1189311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1190311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeMaxInt) {
1191311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteMaxVarintAtOffset(0x5F, 1);
1192311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1193311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1194311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1195311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1196311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1197311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
1198311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x63, i);
1199311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1200311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1201311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1202311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1203311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1204311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1205311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1206311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1207311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeNegative) {
1208311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteNegativeVarintAtOffset(0x5F, 1);
1209311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1210311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1211311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1212311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1213311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1214311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
1215f1dd933c4e47a65889b4bba2a5f58b12aac53383openvcdiff@gmail.com      EXPECT_EQ(delta_file_header_.size() + 0x62, i);
1216311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1217311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1218311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1219311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1220311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1221311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1222311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1223311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1224311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffInterleavedDecoderTestByteByByte, RunSizeInvalid) {
1225311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  WriteInvalidVarintAtOffset(0x5F, 1);
1226311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
1227311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  bool failed = false;
1228311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t i = 0; i < delta_file_.size(); ++i) {
1229311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
1230311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      failed = true;
1231311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      // It should fail at the position that was altered
1232311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      EXPECT_EQ(delta_file_header_.size() + 0x63, i);
1233311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      break;
1234311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
1235311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1236311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(failed);
1237311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // The decoder should not create more target bytes than were expected.
1238311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(expected_target_.size(), output_.size());
1239311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1240311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1241311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}  // namespace open_vcdiff
1242