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/vcencoder.h"
1828db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff#include <stdlib.h>  // free, posix_memalign
1928db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff#include <string.h>  // memcpy
20311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <algorithm>
21311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <string>
22311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <vector>
23311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "blockhash.h"
24311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "checksum.h"
25311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "testing.h"
26311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "varint_bigendian.h"
27311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "google/vcdecoder.h"
28311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "vcdiff_defs.h"
29311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
30311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_EXT_ROPE
31311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <ext/rope>
32311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include "output_string_crope.h"
33311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffusing __gnu_cxx::crope;
34311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_EXT_ROPE
35311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
36311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_MALLOC_H
37311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <malloc.h>
38311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_MALLOC_H
39311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
40311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_SYS_MMAN_H
41732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com#if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
42732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com#undef  _XOPEN_SOURCE
43311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#define _XOPEN_SOURCE 600  // posix_memalign
44732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com#endif
45311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <sys/mman.h>  // mprotect
46311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_SYS_MMAN_H
47311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
48311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_UNISTD_H
49311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#include <unistd.h>  // getpagesize
50311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_UNISTD_H
51311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
52311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffnamespace open_vcdiff {
53311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffnamespace {
54311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
55311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffstatic const size_t kFileHeaderSize = sizeof(DeltaFileHeader);
56311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
57311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// This is to check the maximum possible encoding size
58311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// if using a single ADD instruction, so assume that the
59311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// dictionary size, the length of the ADD data, the size
60311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// of the target window, and the length of the delta window
61311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// are all two-byte Varints, that is, 128 <= length < 4096.
62311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// This figure includes three extra bytes for a zero-sized
63311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// ADD instruction with a two-byte Varint explicit size.
64311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Any additional COPY & ADD instructions must reduce
65311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// the length of the encoding from this maximum.
66311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffstatic const size_t kWindowHeaderSize = 21;
67311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
68311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffclass VerifyEncodedBytesTest : public testing::Test {
69311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff public:
7028db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff  typedef std::string string;
7128db8079f707ebdf43ce62cdfd96eb39c8f889e0openvcdiff
72311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VerifyEncodedBytesTest() : delta_index_(0) { }
73311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  virtual ~VerifyEncodedBytesTest() { }
74311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
75311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void ExpectByte(unsigned char b) {
76311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_EQ(b, static_cast<unsigned char>(delta_[delta_index_]));
77311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ++delta_index_;
78311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
79311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
80311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void ExpectString(const char* s) {
81311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    const size_t size = strlen(s);  // don't include terminating NULL char
82732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com    EXPECT_EQ(s, string(delta_data() + delta_index_, size));
83311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    delta_index_ += size;
84311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
85311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
86311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void ExpectNoMoreBytes() {
87311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_EQ(delta_index_, delta_size());
88311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
89311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
90311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void ExpectSize(size_t size) {
91311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    const char* delta_size_pos = &delta_[delta_index_];
92311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_EQ(size,
93311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff              static_cast<size_t>(
94311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                  VarintBE<int32_t>::Parse(delta_data() + delta_size(),
95311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                           &delta_size_pos)));
96311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    delta_index_ = delta_size_pos - delta_data();
97311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
98311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
99311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void ExpectChecksum(VCDChecksum checksum) {
100311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    const char* delta_checksum_pos = &delta_[delta_index_];
101311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_EQ(checksum,
102311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff              static_cast<VCDChecksum>(
103311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                  VarintBE<int64_t>::Parse(delta_data() + delta_size(),
104311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                           &delta_checksum_pos)));
105311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    delta_index_ = delta_checksum_pos - delta_data();
106311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
107311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
108311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const string& delta_as_const() const { return delta_; }
109311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string* delta() { return &delta_; }
110311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
111311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const char* delta_data() const { return delta_as_const().data(); }
112311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  size_t delta_size() const { return delta_as_const().size(); }
113311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
114311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff private:
115311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string delta_;
116311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  size_t delta_index_;
117311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff};
118311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
119311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffclass VCDiffEncoderTest : public VerifyEncodedBytesTest {
120311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff protected:
121311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  static const char kDictionary[];
122311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  static const char kTarget[];
123732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  static const char kJSONDiff[];
124311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
125311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffEncoderTest();
126311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  virtual ~VCDiffEncoderTest() { }
127311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
128732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  void TestWithFixedChunkSize(VCDiffStreamingEncoder *encoder,
129732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com                              VCDiffStreamingDecoder *decoder,
130732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com                              size_t chunk_size);
131311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void TestWithEncodedChunkVector(size_t chunk_size);
132311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
133311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  HashedDictionary hashed_dictionary_;
134311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingEncoder encoder_;
135311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingDecoder decoder_;
136311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffEncoder simple_encoder_;
137311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffDecoder simple_decoder_;
138732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  VCDiffStreamingEncoder json_encoder_;
139311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
140311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string result_target_;
141311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff};
142311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
143311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffconst char VCDiffEncoderTest::kDictionary[] =
144311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "\"Just the place for a Snark!\" the Bellman cried,\n"
145311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "As he landed his crew with care;\n"
146311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "Supporting each man on the top of the tide\n"
147311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "By a finger entwined in his hair.\n";
148311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
149311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffconst char VCDiffEncoderTest::kTarget[] =
150311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "\"Just the place for a Snark! I have said it twice:\n"
151311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "That alone should encourage the crew.\n"
152311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "Just the place for a Snark! I have said it thrice:\n"
153311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "What I tell you three times is true.\"\n";
154311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
155732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.comconst char VCDiffEncoderTest::kJSONDiff[] =
156732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com    "[\"\\\"Just the place for a Snark! I have said it twice:\\n"
157732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com    "That alone should encourage the crew.\\n\","
158732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com    "161,44,"
159732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com    "\"hrice:\\nWhat I tell you three times is true.\\\"\\n\",]";
160732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com
161311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffVCDiffEncoderTest::VCDiffEncoderTest()
162311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    : hashed_dictionary_(kDictionary, sizeof(kDictionary)),
163311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      encoder_(&hashed_dictionary_,
164311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff               VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM,
165311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff               /* look_for_target_matches = */ true),
166732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com      simple_encoder_(kDictionary, sizeof(kDictionary)),
167732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com      json_encoder_(&hashed_dictionary_,
168732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com                    VCD_FORMAT_JSON,
169732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com                    /* look_for_target_matches = */ true) {
170311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(hashed_dictionary_.Init());
171311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
172311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
173311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeBeforeStartEncoding) {
174311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
175311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
176311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
177311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, FinishBeforeStartEncoding) {
178311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_FALSE(encoder_.FinishEncoding(delta()));
179311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
180311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
181311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeNothing) {
182311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  HashedDictionary nothing_dictionary("", 0);
183311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(nothing_dictionary.Init());
184311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingEncoder nothing_encoder(&nothing_dictionary,
185311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                         VCD_STANDARD_FORMAT,
186311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                         false);
187311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(nothing_encoder.StartEncoding(delta()));
188311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(nothing_encoder.FinishEncoding(delta()));
189311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding("", 0);
190311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
191311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_size(),
192311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &result_target_));
193311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
194311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(result_target_.empty());
195311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
196311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
197732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.comTEST_F(VCDiffEncoderTest, EncodeNothingJSON) {
198732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  HashedDictionary nothing_dictionary("", 0);
199732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_TRUE(nothing_dictionary.Init());
200732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  VCDiffStreamingEncoder nothing_encoder(&nothing_dictionary,
201732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com                                         VCD_FORMAT_JSON,
202732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com                                         false);
203732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_TRUE(nothing_encoder.StartEncoding(delta()));
204732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_TRUE(nothing_encoder.FinishEncoding(delta()));
205732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ("", delta_as_const());
206732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com}
207732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com
208311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// A NULL dictionary pointer is legal as long as the dictionary size is 0.
209311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeNullDictionaryPtr) {
210311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  HashedDictionary null_dictionary(NULL, 0);
211311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(null_dictionary.Init());
212311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingEncoder null_encoder(&null_dictionary,
213311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                      VCD_STANDARD_FORMAT,
214311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                      false);
215311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(null_encoder.StartEncoding(delta()));
216311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(null_encoder.EncodeChunk(kTarget, strlen(kTarget), delta()));
217311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(null_encoder.FinishEncoding(delta()));
218311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
219311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_size());
220311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(NULL, 0);
221311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
222311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_size(),
223311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &result_target_));
224311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
225311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
226311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
227311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
228311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeSimple) {
229311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_encoder_.Encode(kTarget, strlen(kTarget), delta()));
230311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
231311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_size());
232311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
233311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     sizeof(kDictionary),
234311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     delta_as_const(),
235311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     &result_target_));
236311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
237311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
238311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
239311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeInterleaved) {
240311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  simple_encoder_.SetFormatFlags(VCD_FORMAT_INTERLEAVED);
241311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_encoder_.Encode(kTarget, strlen(kTarget), delta()));
242311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
243311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_size());
244311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
245311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     sizeof(kDictionary),
246311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     delta_as_const(),
247311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     &result_target_));
248311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
249311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
250311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
251311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeInterleavedChecksum) {
252311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  simple_encoder_.SetFormatFlags(VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM);
253311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_encoder_.Encode(kTarget,
254311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     strlen(kTarget),
255311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     delta()));
256311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
257311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_size());
258311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
259311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     sizeof(kDictionary),
260311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     delta_as_const(),
261311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     &result_target_));
262311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
263311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
264311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
265311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeSingleChunk) {
266311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.StartEncoding(delta()));
267311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
268311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.FinishEncoding(delta()));
269311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
270311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_size());
271311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(kDictionary, sizeof(kDictionary));
272311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
273311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_size(),
274311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &result_target_));
275311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
276311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
277311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
278311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
279732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.comTEST_F(VCDiffEncoderTest, EncodeSimpleJSON) {
280732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_TRUE(json_encoder_.StartEncoding(delta()));
281732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_TRUE(json_encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
282732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_TRUE(json_encoder_.FinishEncoding(delta()));
283732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ(kJSONDiff, delta_as_const());
284732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com}
285732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com
286311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeSeparate) {
287311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string delta_start, delta_encode, delta_finish;
288311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.StartEncoding(&delta_start));
289311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.EncodeChunk(kTarget, strlen(kTarget), &delta_encode));
290311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.FinishEncoding(&delta_finish));
291311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
292311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_start.size() + delta_encode.size() + delta_finish.size());
293311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(kDictionary, sizeof(kDictionary));
294311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_start.data(),
295311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_start.size(),
296311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &result_target_));
297311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_encode.data(),
298311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_encode.size(),
299311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &result_target_));
300311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_finish.data(),
301311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_finish.size(),
302311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &result_target_));
303311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
304311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
305311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
306311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
307311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_EXT_ROPE
308311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Test that the crope class can be used in place of a string for encoding
309311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// and decoding.
310311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeCrope) {
311311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  crope delta_crope, result_crope;
312311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.StartEncoding(&delta_crope));
313311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.EncodeChunk(kTarget, strlen(kTarget), &delta_crope));
314311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.FinishEncoding(&delta_crope));
315311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
316311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_crope.size());
317311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(kDictionary, sizeof(kDictionary));
318311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // crope can't guarantee that its characters are contiguous, so the decoding
319311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // has to be done byte-by-byte.
320311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (crope::const_iterator it = delta_crope.begin();
321311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff       it != delta_crope.end(); it++) {
322311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    const char this_char = *it;
323311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_TRUE(decoder_.DecodeChunk(&this_char, 1, &result_crope));
324311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
325311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
326311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  crope expected_target(kTarget);
327311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(expected_target, result_crope);
328311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
329311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_EXT_ROPE
330311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
331732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com// Test the encoding and decoding with a fixed chunk size.
332732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com// If decoder is null, only test the encoding.
333732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.comvoid VCDiffEncoderTest::TestWithFixedChunkSize(VCDiffStreamingEncoder *encoder,
334732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com                                               VCDiffStreamingDecoder *decoder,
335732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com                                               size_t chunk_size) {
336311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  delta()->clear();
337732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_TRUE(encoder->StartEncoding(delta()));
338311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t chunk_start_index = 0;
339311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff       chunk_start_index < strlen(kTarget);
340311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff       chunk_start_index += chunk_size) {
341311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    size_t this_chunk_size = chunk_size;
342311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    const size_t bytes_available = strlen(kTarget) - chunk_start_index;
343311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (this_chunk_size > bytes_available) {
344311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      this_chunk_size = bytes_available;
345311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
346732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com    EXPECT_TRUE(encoder->EncodeChunk(&kTarget[chunk_start_index],
347311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     this_chunk_size,
348311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     delta()));
349311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
350732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_TRUE(encoder->FinishEncoding(delta()));
351311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const size_t num_windows = (strlen(kTarget) / chunk_size) + 1;
352311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const size_t size_of_windows =
353311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      strlen(kTarget) + (kWindowHeaderSize * num_windows);
354311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(kFileHeaderSize + size_of_windows, delta_size());
355311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  result_target_.clear();
356732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com
357732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  if (!decoder) return;
358732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com
359732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  decoder->StartDecoding(kDictionary, sizeof(kDictionary));
360311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t chunk_start_index = 0;
361311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff       chunk_start_index < delta_size();
362311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff       chunk_start_index += chunk_size) {
363311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    size_t this_chunk_size = chunk_size;
364311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    const size_t bytes_available = delta_size() - chunk_start_index;
365311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (this_chunk_size > bytes_available) {
366311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      this_chunk_size = bytes_available;
367311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
368732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com    EXPECT_TRUE(decoder->DecodeChunk(delta_data() + chunk_start_index,
369311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     this_chunk_size,
370311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     &result_target_));
371311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
372732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_TRUE(decoder->FinishDecoding());
373311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
374311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
375311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
376311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeFixedChunkSizes) {
377311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // These specific chunk sizes have failed in the past
378732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  TestWithFixedChunkSize(&encoder_, &decoder_, 6);
379732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  TestWithFixedChunkSize(&encoder_, &decoder_, 45);
380732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  TestWithFixedChunkSize(&encoder_, &decoder_, 60);
381311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
382311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Now loop through all possible chunk sizes
383311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t chunk_size = 1; chunk_size < strlen(kTarget); ++chunk_size) {
384732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com    TestWithFixedChunkSize(&encoder_, &decoder_, chunk_size);
385311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
386311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
387311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
388732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.comTEST_F(VCDiffEncoderTest, EncodeFixedChunkSizesJSON) {
389732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  // There is no JSON decoder; these diffs are created by hand.
390732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  TestWithFixedChunkSize(&json_encoder_, NULL, 6);
391732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ("[\"\\\"Just \",\"the pl\",\"ace fo\",\"r a Sn\",\"ark! I\","
392732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "\" have \",\"said i\",\"t twic\",\"e:\\nTha\",\"t alon\","
393732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "\"e shou\",\"ld enc\",\"ourage\",\" the c\",\"rew.\\nJ\","
394732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "\"ust th\",\"e plac\",\"e for \",\"a Snar\",\"k! I h\","
395732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "\"ave sa\",\"id it \",\"thrice\",\":\\nWhat\",\" I tel\","
396732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "\"l you \",\"three \",\"times \",\"is tru\",\"e.\\\"\\n\",]",
397732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            delta_as_const());
398732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  TestWithFixedChunkSize(&json_encoder_, NULL, 45);
399732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ("[\"\\\"Just the place for a Snark! I have said it t\","
400732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "\"wice:\\nThat alone should encourage the crew.\\nJ\","
401732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "\"ust the place for a Snark! I have said it thr\",\"ice:\\n"
402732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "What I tell you three times is true.\\\"\\n\",]",
403732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            delta_as_const());
404732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  TestWithFixedChunkSize(&json_encoder_, NULL, 60);
405732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com  EXPECT_EQ("[\"\\\"Just the place for a Snark! I have said it twice:\\n"
406732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "That alon\",\"e should encourage the crew.\\n"
407732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "Just the place for a Snark! I h\",\"ave said it thrice:\\n"
408732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            "What I tell you three times is true.\\\"\\n\",]",
409732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com            delta_as_const());
410732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com}
411732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com
412732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com
413baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// If --allow_vcd_target=false is specified, the decoder will throw away some of
414baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// the internally-stored decoded target beyond the current window.  Try
415baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// different numbers of encoded window sizes to make sure that this behavior
416baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff// does not affect the results.
417baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeFixedChunkSizesNoVcdTarget) {
418baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff  decoder_.SetAllowVcdTarget(false);
419baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff  // Loop through all possible chunk sizes
420baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff  for (size_t chunk_size = 1; chunk_size < strlen(kTarget); ++chunk_size) {
421732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.com    TestWithFixedChunkSize(&encoder_, &decoder_, chunk_size);
422baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff  }
423baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff}
424baf44ead8ad43d5c600b7f89420905a7397489fbopenvcdiff
425311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Splits the text to be encoded into fixed-size chunks.  Encodes each
426311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// chunk and puts it into a vector of strings.  Then decodes each string
427311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// in the vector and appends the result into result_target_.
428311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffvoid VCDiffEncoderTest::TestWithEncodedChunkVector(size_t chunk_size) {
429311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  std::vector<string> encoded_chunks;
430311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string this_encoded_chunk;
431311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  size_t total_chunk_size = 0;
432311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.StartEncoding(&this_encoded_chunk));
433311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  encoded_chunks.push_back(this_encoded_chunk);
434311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  total_chunk_size += this_encoded_chunk.size();
435311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t chunk_start_index = 0;
436311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff       chunk_start_index < strlen(kTarget);
437311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff       chunk_start_index += chunk_size) {
438311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    size_t this_chunk_size = chunk_size;
439311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    const size_t bytes_available = strlen(kTarget) - chunk_start_index;
440311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    if (this_chunk_size > bytes_available) {
441311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      this_chunk_size = bytes_available;
442311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    }
443311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    this_encoded_chunk.clear();
444311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_TRUE(encoder_.EncodeChunk(&kTarget[chunk_start_index],
445311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     this_chunk_size,
446311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     &this_encoded_chunk));
447311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    encoded_chunks.push_back(this_encoded_chunk);
448311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    total_chunk_size += this_encoded_chunk.size();
449311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
450311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  this_encoded_chunk.clear();
451311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.FinishEncoding(&this_encoded_chunk));
452311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  encoded_chunks.push_back(this_encoded_chunk);
453311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  total_chunk_size += this_encoded_chunk.size();
454311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const size_t num_windows = (strlen(kTarget) / chunk_size) + 1;
455311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const size_t size_of_windows =
456311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      strlen(kTarget) + (kWindowHeaderSize * num_windows);
457311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(kFileHeaderSize + size_of_windows, total_chunk_size);
458311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  result_target_.clear();
459311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(kDictionary, sizeof(kDictionary));
460311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (std::vector<string>::iterator it = encoded_chunks.begin();
461311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff       it != encoded_chunks.end(); ++it) {
462311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    EXPECT_TRUE(decoder_.DecodeChunk(it->data(), it->size(), &result_target_));
463311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
464311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
465311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
466311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
467311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
468311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, EncodeDecodeStreamOfChunks) {
469311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Loop through all possible chunk sizes
470311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  for (size_t chunk_size = 1; chunk_size < strlen(kTarget); ++chunk_size) {
471311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    TestWithEncodedChunkVector(chunk_size);
472311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
473311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
474311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
475311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Verify that HashedDictionary stores a copy of the dictionary text,
476311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// rather than just storing a pointer to it.  If the dictionary buffer
477311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// is overwritten after creating a HashedDictionary from it, it shouldn't
478311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// affect an encoder that uses that HashedDictionary.
479311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, DictionaryBufferOverwritten) {
480311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string dictionary_copy(kDictionary, sizeof(kDictionary));
481311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  HashedDictionary hd_copy(dictionary_copy.data(), dictionary_copy.size());
482311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(hd_copy.Init());
483311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingEncoder copy_encoder(&hd_copy,
484311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                      VCD_FORMAT_INTERLEAVED
485311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                          | VCD_FORMAT_CHECKSUM,
486311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                      /* look_for_target_matches = */ true);
487311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Produce a reference version of the encoded text.
488311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string delta_before;
489311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(copy_encoder.StartEncoding(&delta_before));
490311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(copy_encoder.EncodeChunk(kTarget,
491311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                       strlen(kTarget),
492311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                       &delta_before));
493311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(copy_encoder.FinishEncoding(&delta_before));
494311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
495311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_before.size());
496311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
497311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Overwrite the dictionary text with all 'Q' characters.
498311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  dictionary_copy.replace(0,
499311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                          dictionary_copy.size(),
500311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                          dictionary_copy.size(),
501311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                          'Q');
502311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // When the encoder is used on the same target text after overwriting
503311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // the dictionary, it should produce the same encoded output.
504311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string delta_after;
505311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(copy_encoder.StartEncoding(&delta_after));
506311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(copy_encoder.EncodeChunk(kTarget, strlen(kTarget), &delta_after));
507311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(copy_encoder.FinishEncoding(&delta_after));
508311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(delta_before, delta_after);
509311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
510311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
511311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Binary data test part 1: The dictionary and target data should not
512311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// be treated as NULL-terminated.  An embedded NULL should be handled like
513311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// any other byte of data.
514311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, DictionaryHasEmbeddedNULLs) {
515311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const char embedded_null_dictionary_text[] =
516311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      { 0x00, 0xFF, 0xFE, 0xFD, 0x00, 0xFD, 0xFE, 0xFF, 0x00, 0x03 };
517311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const char embedded_null_target[] =
518311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      { 0xFD, 0x00, 0xFD, 0xFE, 0x03, 0x00, 0x01, 0x00 };
519311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  CHECK_EQ(10, sizeof(embedded_null_dictionary_text));
520311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  CHECK_EQ(8, sizeof(embedded_null_target));
521311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  HashedDictionary embedded_null_dictionary(embedded_null_dictionary_text,
522311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      sizeof(embedded_null_dictionary_text));
523311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(embedded_null_dictionary.Init());
524311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingEncoder embedded_null_encoder(&embedded_null_dictionary,
525311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM,
526311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      /* look_for_target_matches = */ true);
527311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(embedded_null_encoder.StartEncoding(delta()));
528311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(embedded_null_encoder.EncodeChunk(embedded_null_target,
529311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                                sizeof(embedded_null_target),
530311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                                delta()));
531311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(embedded_null_encoder.FinishEncoding(delta()));
532311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(embedded_null_dictionary_text,
533311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                         sizeof(embedded_null_dictionary_text));
534311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
535311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_size(),
536311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &result_target_));
537311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
538311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(sizeof(embedded_null_target), result_target_.size());
539311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(string(embedded_null_target,
540311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                   sizeof(embedded_null_target)),
541311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            result_target_);
542311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
543311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
544311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Binary data test part 2: An embedded CR or LF should be handled like
545311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// any other byte of data.  No text-processing of the data should occur.
546311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, DictionaryHasEmbeddedNewlines) {
547311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const char embedded_null_dictionary_text[] =
548311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      { 0x0C, 0xFF, 0xFE, 0x0C, 0x00, 0x0A, 0xFE, 0xFF, 0x00, 0x0A };
549311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const char embedded_null_target[] =
550311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      { 0x0C, 0x00, 0x0A, 0xFE, 0x03, 0x00, 0x0A, 0x00 };
551311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  CHECK_EQ(10, sizeof(embedded_null_dictionary_text));
552311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  CHECK_EQ(8, sizeof(embedded_null_target));
553311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  HashedDictionary embedded_null_dictionary(embedded_null_dictionary_text,
554311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      sizeof(embedded_null_dictionary_text));
555311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(embedded_null_dictionary.Init());
556311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingEncoder embedded_null_encoder(&embedded_null_dictionary,
557311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM,
558311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      /* look_for_target_matches = */ true);
559311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(embedded_null_encoder.StartEncoding(delta()));
560311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(embedded_null_encoder.EncodeChunk(embedded_null_target,
561311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                                sizeof(embedded_null_target),
562311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                                delta()));
563311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(embedded_null_encoder.FinishEncoding(delta()));
564311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding(embedded_null_dictionary_text,
565311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                         sizeof(embedded_null_dictionary_text));
566311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
567311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_size(),
568311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &result_target_));
569311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
570311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(sizeof(embedded_null_target), result_target_.size());
571311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(string(embedded_null_target,
572311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                   sizeof(embedded_null_target)),
573311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            result_target_);
574311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
575311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
576311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, UsingWideCharacters) {
577311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const wchar_t wchar_dictionary_text[] =
578311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      L"\"Just the place for a Snark!\" the Bellman cried,\n"
579311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      L"As he landed his crew with care;\n"
580311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      L"Supporting each man on the top of the tide\n"
581311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      L"By a finger entwined in his hair.\n";
582311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
583311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const wchar_t wchar_target[] =
584311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      L"\"Just the place for a Snark! I have said it twice:\n"
585311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      L"That alone should encourage the crew.\n"
586311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      L"Just the place for a Snark! I have said it thrice:\n"
587311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      L"What I tell you three times is true.\"\n";
588311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
589311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  HashedDictionary wchar_dictionary((const char*) wchar_dictionary_text,
590311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                    sizeof(wchar_dictionary_text));
591311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(wchar_dictionary.Init());
592311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingEncoder wchar_encoder(&wchar_dictionary,
593311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                       VCD_FORMAT_INTERLEAVED
594311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                           | VCD_FORMAT_CHECKSUM,
595311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                       /* look_for_target_matches = */ false);
596311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(wchar_encoder.StartEncoding(delta()));
597311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(wchar_encoder.EncodeChunk((const char*) wchar_target,
598311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                        sizeof(wchar_target),
599311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                        delta()));
600311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(wchar_encoder.FinishEncoding(delta()));
601311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  decoder_.StartDecoding((const char*) wchar_dictionary_text,
602311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                         sizeof(wchar_dictionary_text));
603311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.DecodeChunk(delta_data(),
604311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   delta_size(),
605311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                   &result_target_));
606311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(decoder_.FinishDecoding());
607311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const wchar_t* result_as_wchar = (const wchar_t*) result_target_.data();
608311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(wcslen(wchar_target), wcslen(result_as_wchar));
609311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(0, wcscmp(wchar_target, result_as_wchar));
610311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
611311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
612311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#if defined(HAVE_MPROTECT) && \
613311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff   (defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN))
614311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// Bug 1220602: Make sure the encoder doesn't read past the end of the input
615311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff// buffer.
616311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, ShouldNotReadPastEndOfBuffer) {
617311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const size_t target_size = strlen(kTarget);
618311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
619311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Allocate two memory pages.
620311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const int page_size = getpagesize();
621311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void* two_pages = NULL;
622311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_POSIX_MEMALIGN
623311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  posix_memalign(&two_pages, page_size, 2 * page_size);
624311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#else  // !HAVE_POSIX_MEMALIGN
625311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  two_pages = memalign(page_size, 2 * page_size);
626311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_POSIX_MEMALIGN
627311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* const first_page = reinterpret_cast<char*>(two_pages);
628311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* const second_page = first_page + page_size;
629311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
630311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Place the target string at the end of the first page.
631311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* const target_with_guard = second_page - target_size;
632311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  memcpy(target_with_guard, kTarget, target_size);
633311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
634311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Make the second page unreadable.
635311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  mprotect(second_page, page_size, PROT_NONE);
636311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
637311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Now perform the encode operation, which will cause a segmentation fault
638311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // if it reads past the end of the buffer.
639311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.StartEncoding(delta()));
640311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.EncodeChunk(target_with_guard, target_size, delta()));
641311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.FinishEncoding(delta()));
642311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
643311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Undo the mprotect.
644311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  mprotect(second_page, page_size, PROT_READ|PROT_WRITE);
645311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  free(two_pages);
646311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
647311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
648311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffEncoderTest, ShouldNotReadPastBeginningOfBuffer) {
649311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const size_t target_size = strlen(kTarget);
650311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
651311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Allocate two memory pages.
652311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const int page_size = getpagesize();
653311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void* two_pages = NULL;
654311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#ifdef HAVE_POSIX_MEMALIGN
655311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  posix_memalign(&two_pages, page_size, 2 * page_size);
656311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#else  // !HAVE_POSIX_MEMALIGN
657311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  two_pages = memalign(page_size, 2 * page_size);
658311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_POSIX_MEMALIGN
659311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* const first_page = reinterpret_cast<char*>(two_pages);
660311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* const second_page = first_page + page_size;
661311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
662311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Make the first page unreadable.
663311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  mprotect(first_page, page_size, PROT_NONE);
664311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
665311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Place the target string at the beginning of the second page.
666311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  char* const target_with_guard = second_page;
667311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  memcpy(target_with_guard, kTarget, target_size);
668311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
669311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Now perform the encode operation, which will cause a segmentation fault
670311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // if it reads past the beginning of the buffer.
671311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.StartEncoding(delta()));
672311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.EncodeChunk(target_with_guard, target_size, delta()));
673311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.FinishEncoding(delta()));
674311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
675311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // Undo the mprotect.
676311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  mprotect(first_page, page_size, PROT_READ|PROT_WRITE);
677311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  free(two_pages);
678311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
679311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff#endif  // HAVE_MPROTECT && (HAVE_MEMALIGN || HAVE_POSIX_MEMALIGN)
680311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
681732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.comclass VCDiffHTML1Test : public VerifyEncodedBytesTest {
682311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff protected:
683311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  static const char kDictionary[];
684311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  static const char kTarget[];
685d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  static const char kRedundantTarget[];
686311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
687311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffHTML1Test();
688311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  virtual ~VCDiffHTML1Test() { }
689311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
690311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void SimpleEncode();
691311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void StreamingEncode();
692311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
693311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  HashedDictionary hashed_dictionary_;
694311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingEncoder encoder_;
695311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingDecoder decoder_;
696311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffEncoder simple_encoder_;
697311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffDecoder simple_decoder_;
698311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
699311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string result_target_;
700311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff};
701311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
702311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffconst char VCDiffHTML1Test::kDictionary[] =
703311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "<html><font color=red>This part from the dict</font><br>";
704311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
705311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffconst char VCDiffHTML1Test::kTarget[] =
706311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "<html><font color=red>This part from the dict</font><br>\n"
707311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    "And this part is not...</html>";
708311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
709d18457863096b3685e56f5a8919959f6afbdb121openvcdiffconst char VCDiffHTML1Test::kRedundantTarget[] =
710d18457863096b3685e56f5a8919959f6afbdb121openvcdiff    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
711d18457863096b3685e56f5a8919959f6afbdb121openvcdiff    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
712d18457863096b3685e56f5a8919959f6afbdb121openvcdiff    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
713d18457863096b3685e56f5a8919959f6afbdb121openvcdiff    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";  // 256
714d18457863096b3685e56f5a8919959f6afbdb121openvcdiff
715311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffVCDiffHTML1Test::VCDiffHTML1Test()
716311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    : hashed_dictionary_(kDictionary, sizeof(kDictionary)),
717311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      encoder_(&hashed_dictionary_,
718311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff               VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM,
719311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff               /* look_for_target_matches = */ true),
720311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      simple_encoder_(kDictionary, sizeof(kDictionary)) {
721311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(hashed_dictionary_.Init());
722311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
723311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
724311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffvoid VCDiffHTML1Test::SimpleEncode() {
725311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_encoder_.Encode(kTarget, strlen(kTarget), delta()));
726311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
727311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_size());
728311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
729311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     sizeof(kDictionary),
730311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     delta_as_const(),
731311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     &result_target_));
732311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
733311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
734311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
735311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffvoid VCDiffHTML1Test::StreamingEncode() {
736311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.StartEncoding(delta()));
737311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
738311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.FinishEncoding(delta()));
739311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
740311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
741311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffHTML1Test, CheckOutputOfSimpleEncoder) {
742311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  SimpleEncode();
743311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // These values do not depend on the block size used for encoding
744311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0xD6);  // 'V' | 0x80
745311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0xC3);  // 'C' | 0x80
746311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0xC4);  // 'D' | 0x80
747311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0x00);  // Simple encoder never uses interleaved format
748311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0x00);  // Hdr_Indicator
749311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(VCD_SOURCE);  // Win_Indicator: VCD_SOURCE (dictionary)
750311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(sizeof(kDictionary));  // Dictionary length
751311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0x00);  // Source segment position: start of dictionary
752d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  if (BlockHash::kBlockSize < 16) {
753311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // A medium block size will catch the "his part " match.
754311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x22);  // Length of the delta encoding
755311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));  // Size of the target window
756311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Delta_indicator (no compression)
757311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x16);  // Length of the data section
758311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x05);  // Length of the instructions section
759311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x02);  // Length of the address section
760311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Data section
761311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectString("\nAnd t");      // Data for 1st ADD
762311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectString("is not...</html>");  // Data for 2nd ADD
763311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Instructions section
764311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x73);  // COPY size 0 mode VCD_SAME(0)
765311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x38);  // COPY size (56)
766311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x07);  // ADD size 6
767311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x19);  // COPY size 9 mode VCD_SELF
768311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x11);  // ADD size 16
769311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Address section
770311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // COPY address (0) mode VCD_SAME(0)
771311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x17);  // COPY address (23) mode VCD_SELF
772311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  } else if (BlockHash::kBlockSize <= 56) {
773311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Any block size up to 56 will catch the matching prefix string.
774311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x29);  // Length of the delta encoding
775311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));  // Size of the target window
776311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Delta_indicator (no compression)
777311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x1F);  // Length of the data section
778311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x04);  // Length of the instructions section
779311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x01);  // Length of the address section
780311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectString("\nAnd this part is not...</html>");  // Data for ADD
781311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Instructions section
782311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x73);  // COPY size 0 mode VCD_SAME(0)
783311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x38);  // COPY size (56)
784311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x01);  // ADD size 0
785311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x1F);  // Size of ADD (31)
786311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Address section
787311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // COPY address (0) mode VCD_SAME(0)
788311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  } else {
789311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // The matching string is 56 characters long, and the block size is
790311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // 64 or greater, so no match should be found.
791311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget) + 7);  // Delta encoding len
792311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));  // Size of the target window
793311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Delta_indicator (no compression)
794311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));  // Length of the data section
795311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x02);  // Length of the instructions section
796311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Length of the address section
797311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Data section
798311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectString(kTarget);
799311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x01);  // ADD size 0
800311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));
801311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
802311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectNoMoreBytes();
803311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
804311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
805d18457863096b3685e56f5a8919959f6afbdb121openvcdiffTEST_F(VCDiffHTML1Test, SimpleEncoderPerformsTargetMatching) {
806d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  EXPECT_TRUE(simple_encoder_.Encode(kRedundantTarget,
807d18457863096b3685e56f5a8919959f6afbdb121openvcdiff                                     strlen(kRedundantTarget),
808d18457863096b3685e56f5a8919959f6afbdb121openvcdiff                                     delta()));
809d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  EXPECT_GE(strlen(kRedundantTarget) + kFileHeaderSize + kWindowHeaderSize,
810d18457863096b3685e56f5a8919959f6afbdb121openvcdiff            delta_size());
811d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
812d18457863096b3685e56f5a8919959f6afbdb121openvcdiff                                     sizeof(kDictionary),
813d18457863096b3685e56f5a8919959f6afbdb121openvcdiff                                     delta_as_const(),
814d18457863096b3685e56f5a8919959f6afbdb121openvcdiff                                     &result_target_));
815d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  EXPECT_EQ(kRedundantTarget, result_target_);
816d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  // These values do not depend on the block size used for encoding
817d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0xD6);  // 'V' | 0x80
818d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0xC3);  // 'C' | 0x80
819d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0xC4);  // 'D' | 0x80
820d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x00);  // Simple encoder never uses interleaved format
821d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x00);  // Hdr_Indicator
822d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(VCD_SOURCE);  // Win_Indicator: VCD_SOURCE (dictionary)
823d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(sizeof(kDictionary));  // Dictionary length
824d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x00);  // Source segment position: start of dictionary
825d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x0C);  // Length of the delta encoding
826d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectSize(strlen(kRedundantTarget));  // Size of the target window
827d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x00);  // Delta_indicator (no compression)
828d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x01);  // Length of the data section
829d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x04);  // Length of the instructions section
830d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x01);  // Length of the address section
831d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  // Data section
832d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectString("A");      // Data for ADD
833d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  // Instructions section
834d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x02);  // ADD size 1
835d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x23);  // COPY size 0 mode VCD_HERE
836d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectSize(strlen(kRedundantTarget) - 1);  // COPY size 255
837d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  // Address section
838d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x01);  // COPY address (1) mode VCD_HERE
839d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectNoMoreBytes();
840d18457863096b3685e56f5a8919959f6afbdb121openvcdiff}
841d18457863096b3685e56f5a8919959f6afbdb121openvcdiff
842d18457863096b3685e56f5a8919959f6afbdb121openvcdiffTEST_F(VCDiffHTML1Test, SimpleEncoderWithoutTargetMatching) {
843d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  simple_encoder_.SetTargetMatching(false);
844d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  EXPECT_TRUE(simple_encoder_.Encode(kRedundantTarget,
845d18457863096b3685e56f5a8919959f6afbdb121openvcdiff                                     strlen(kRedundantTarget),
846d18457863096b3685e56f5a8919959f6afbdb121openvcdiff                                     delta()));
847d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  EXPECT_GE(strlen(kRedundantTarget) + kFileHeaderSize + kWindowHeaderSize,
848d18457863096b3685e56f5a8919959f6afbdb121openvcdiff            delta_size());
849d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
850d18457863096b3685e56f5a8919959f6afbdb121openvcdiff                                     sizeof(kDictionary),
851d18457863096b3685e56f5a8919959f6afbdb121openvcdiff                                     delta_as_const(),
852d18457863096b3685e56f5a8919959f6afbdb121openvcdiff                                     &result_target_));
853d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  EXPECT_EQ(kRedundantTarget, result_target_);
854d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  // These values do not depend on the block size used for encoding
855d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0xD6);  // 'V' | 0x80
856d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0xC3);  // 'C' | 0x80
857d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0xC4);  // 'D' | 0x80
858d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x00);  // Simple encoder never uses interleaved format
859d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x00);  // Hdr_Indicator
860d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(VCD_SOURCE);  // Win_Indicator: VCD_SOURCE (dictionary)
861d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(sizeof(kDictionary));  // Dictionary length
862d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x00);  // Source segment position: start of dictionary
863d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectSize(strlen(kRedundantTarget) + 0x0A);  // Length of the delta encoding
864d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectSize(strlen(kRedundantTarget));  // Size of the target window
865d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x00);  // Delta_indicator (no compression)
866d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectSize(strlen(kRedundantTarget));  // Length of the data section
867d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x03);  // Length of the instructions section
868d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x00);  // Length of the address section
869d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  // Data section
870d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectString(kRedundantTarget);      // Data for ADD
871d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  // Instructions section
872d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectByte(0x01);  // ADD size 0
873d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectSize(strlen(kRedundantTarget));  // ADD size
874d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  // Address section empty
875d18457863096b3685e56f5a8919959f6afbdb121openvcdiff  ExpectNoMoreBytes();
876d18457863096b3685e56f5a8919959f6afbdb121openvcdiff}
877d18457863096b3685e56f5a8919959f6afbdb121openvcdiff
878732fff248e662ec47aa27c124632f406f27b6c8dopenvcdiff@gmail.comclass VCDiffHTML2Test : public VerifyEncodedBytesTest {
879311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff protected:
880311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  static const char kDictionary[];
881311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  static const char kTarget[];
882311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
883311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffHTML2Test();
884311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  virtual ~VCDiffHTML2Test() { }
885311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
886311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void SimpleEncode();
887311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  void StreamingEncode();
888311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
889311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  HashedDictionary hashed_dictionary_;
890311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingEncoder encoder_;
891311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffStreamingDecoder decoder_;
892311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffEncoder simple_encoder_;
893311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  VCDiffDecoder simple_decoder_;
894311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
895311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  string result_target_;
896311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff};
897311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
898311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffconst char VCDiffHTML2Test::kDictionary[] = "10\nThis is a test";
899311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
900311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffconst char VCDiffHTML2Test::kTarget[] = "This is a test!!!\n";
901311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
902311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffVCDiffHTML2Test::VCDiffHTML2Test()
903311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    : hashed_dictionary_(kDictionary, sizeof(kDictionary)),
904311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      encoder_(&hashed_dictionary_,
905311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff               VCD_FORMAT_INTERLEAVED | VCD_FORMAT_CHECKSUM,
906311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff               /* look_for_target_matches = */ true),
907311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff      simple_encoder_(kDictionary, sizeof(kDictionary)) {
908311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(hashed_dictionary_.Init());
909311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
910311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
911311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffvoid VCDiffHTML2Test::SimpleEncode() {
912311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_encoder_.Encode(kTarget, strlen(kTarget), delta()));
913311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
914311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_size());
915311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
916311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     sizeof(kDictionary),
917311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     delta_as_const(),
918311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     &result_target_));
919311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
920311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
921311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
922311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffvoid VCDiffHTML2Test::StreamingEncode() {
923311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.StartEncoding(delta()));
924311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(encoder_.EncodeChunk(kTarget, strlen(kTarget), delta()));
925311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_GE(strlen(kTarget) + kFileHeaderSize + kWindowHeaderSize,
926311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff            delta_size());
927311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_TRUE(simple_decoder_.Decode(kDictionary,
928311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     sizeof(kDictionary),
929311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     delta_as_const(),
930311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff                                     &result_target_));
931311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  EXPECT_EQ(kTarget, result_target_);
932311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
933311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
934311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffHTML2Test, VerifyOutputOfSimpleEncoder) {
935311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  SimpleEncode();
936311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // These values do not depend on the block size used for encoding
937311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0xD6);  // 'V' | 0x80
938311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0xC3);  // 'C' | 0x80
939311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0xC4);  // 'D' | 0x80
940311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0x00);  // Simple encoder never uses interleaved format
941311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0x00);  // Hdr_Indicator
942311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(VCD_SOURCE);  // Win_Indicator: VCD_SOURCE (dictionary)
943311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(sizeof(kDictionary));  // Dictionary length
944311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0x00);  // Source segment position: start of dictionary
945311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  if (BlockHash::kBlockSize <= 8) {
946311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(12);  // Length of the delta encoding
947311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));  // Size of the target window
948311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Delta_indicator (no compression)
949311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x04);  // Length of the data section
950311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x02);  // Length of the instructions section
951311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x01);  // Length of the address section
952311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte('!');
953311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte('!');
954311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte('!');
955311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte('\n');
956311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x1E);  // COPY size 14 mode VCD_SELF
957311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x05);  // ADD size 4
958311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x03);  // COPY address (3) mode VCD_SELF
959311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  } else {
960311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Larger block sizes will not catch any matches.
961311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget) + 7);  // Delta encoding len
962311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));  // Size of the target window
963311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Delta_indicator (no compression)
964311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));  // Length of the data section
965311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x02);  // Length of the instructions section
966311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Length of the address section
967311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Data section
968311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectString(kTarget);
969311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x01);  // ADD size 0
970311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));
971311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
972311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectNoMoreBytes();
973311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
974311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
975311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiffTEST_F(VCDiffHTML2Test, VerifyOutputWithChecksum) {
976311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  StreamingEncode();
977311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  const VCDChecksum html2_checksum = ComputeAdler32(kTarget, strlen(kTarget));
978311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  CHECK_EQ(5, VarintBE<int64_t>::Length(html2_checksum));
979311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  // These values do not depend on the block size used for encoding
980311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0xD6);  // 'V' | 0x80
981311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0xC3);  // 'C' | 0x80
982311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0xC4);  // 'D' | 0x80
983311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte('S');  // Format extensions
984311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0x00);  // Hdr_Indicator
985311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(VCD_SOURCE | VCD_CHECKSUM);  // Win_Indicator
986311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(sizeof(kDictionary));  // Dictionary length
987311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectByte(0x00);  // Source segment position: start of dictionary
988311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  if (BlockHash::kBlockSize <= 8) {
989311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(17);  // Length of the delta encoding
990311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));  // Size of the target window
991311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Delta_indicator (no compression)
992311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Length of the data section
993311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x07);  // Length of the instructions section
994311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Length of the address section
995311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectChecksum(html2_checksum);
996311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x1E);  // COPY size 14 mode VCD_SELF
997311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x03);  // COPY address (3) mode VCD_SELF
998311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x05);  // ADD size 4
999311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte('!');
1000311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte('!');
1001311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte('!');
1002311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte('\n');
1003311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  } else {
1004311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Larger block sizes will not catch any matches.
1005311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget) + 12);  // Delta encoding len
1006311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));  // Size of the target window
1007311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Delta_indicator (no compression)
1008311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Length of the data section
1009311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(0x02 + strlen(kTarget));  // Interleaved
1010311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x00);  // Length of the address section
1011311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectChecksum(html2_checksum);
1012311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    // Data section
1013311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectByte(0x01);  // ADD size 0
1014311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectSize(strlen(kTarget));
1015311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff    ExpectString(kTarget);
1016311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  }
1017311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff  ExpectNoMoreBytes();
1018311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}
1019311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff
1020311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}  // anonymous namespace
1021311c71486f5f6074e5ba62a7f4c5397c8700b868openvcdiff}  // namespace open_vcdiff
1022