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(¬hing_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(¬hing_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