#include <config.h>
#include "google/vcdecoder.h"
#include <string>
#include "codetable.h"
#include "testing.h"
#include "varint_bigendian.h"
#include "vcdecoder_test.h"
#include "vcdiff_defs.h"
namespace open_vcdiff {
namespace {
class VCDiffDecoderInterleavedAllowedButNotUsed
: public VCDiffStandardDecoderTest {
public:
VCDiffDecoderInterleavedAllowedButNotUsed() {
UseInterleavedFileHeader();
}
virtual ~VCDiffDecoderInterleavedAllowedButNotUsed() { }
};
TEST_F(VCDiffDecoderInterleavedAllowedButNotUsed, Decode) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffDecoderInterleavedAllowedButNotUsed, DecodeWithChecksum) {
ComputeAndAddChecksum();
InitializeDeltaFile();
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
typedef VCDiffDecoderInterleavedAllowedButNotUsed
VCDiffDecoderInterleavedAllowedButNotUsedByteByByte;
TEST_F(VCDiffDecoderInterleavedAllowedButNotUsedByteByByte, Decode) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffDecoderInterleavedAllowedButNotUsedByteByByte,
DecodeWithChecksum) {
ComputeAndAddChecksum();
InitializeDeltaFile();
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
class VCDiffDecoderInterleavedUsedButNotSupported
: public VCDiffInterleavedDecoderTest {
public:
VCDiffDecoderInterleavedUsedButNotSupported() {
UseStandardFileHeader();
}
virtual ~VCDiffDecoderInterleavedUsedButNotSupported() { }
};
TEST_F(VCDiffDecoderInterleavedUsedButNotSupported, DecodeShouldFail) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_EQ("", output_);
}
TEST_F(VCDiffDecoderInterleavedUsedButNotSupported,
DecodeByteByByteShouldFail) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
bool failed = false;
for (size_t i = 0; i < delta_file_.size(); ++i) {
if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
failed = true;
break;
}
}
EXPECT_TRUE(failed);
EXPECT_GE(expected_target_.size(), output_.size());
}
class VCDiffStandardWindowDecoderTest : public VCDiffDecoderTest {
protected:
static const size_t kWindow2Size = 61;
VCDiffStandardWindowDecoderTest();
virtual ~VCDiffStandardWindowDecoderTest() {}
private:
static const char kWindowBody[];
};
const size_t VCDiffStandardWindowDecoderTest::kWindow2Size;
const char VCDiffStandardWindowDecoderTest::kWindowBody[] = {
VCD_SOURCE, FirstByteOfStringLength(kDictionary), SecondByteOfStringLength(kDictionary),
0x00, 0x08, 0x1C, 0x00, 0x00, 0x02, 0x01, 0x13, 0x1C, 0x00, 0x00, 0x44, static_cast<char>(kWindow2Size), 0x00, 0x3D, 0x02, 0x00, ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ',
'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n',
'T', 'h', 'a', 't', ' ',
'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ',
'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ',
't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n',
0x01, 0x3D, VCD_TARGET, 0x59, 0x00, 0x08, 0x2C, 0x00, 0x00, 0x02, 0x01, 0x23, 0x2C, 0x58, VCD_TARGET, 0x05, 0x2E, 0x09, 0x07, 0x00, 0x02, 0x01, 0x01, 'h', 'r',
0xA7, 0x00, 0x00, 0x0F, 0x09, 0x00, 0x09, 0x01, 0x00, 'W', 'h', 'a', 't', ' ', 'I', ' ', 't', 'e',
0x0A, 0x00, 0x08, 0x02, 0x00, 0x01, 0x02, 0x00, 'l',
0x00, 0x02, 0x00, 0x22, 0x1B, 0x00, 0x1B, 0x02, 0x00, ' ', 'y', 'o', 'u', ' ',
't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ',
't', 'r', 'u', 'e', '.', '\"', '\n',
0x01, 0x1B, };
VCDiffStandardWindowDecoderTest::VCDiffStandardWindowDecoderTest() {
UseStandardFileHeader();
delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
}
TEST_F(VCDiffStandardWindowDecoderTest, Decode) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffStandardWindowDecoderTest, DecodeBreakInFourthWindowHeader) {
const size_t chunk_1_size = delta_file_header_.size() + 83;
const size_t chunk_2_size = 12 + 5;
CHECK_EQ(VCD_TARGET, static_cast<unsigned char>(delta_file_[chunk_1_size]));
CHECK_EQ(0x00, static_cast<int>(delta_file_[chunk_1_size + chunk_2_size]));
string output_chunk1, output_chunk2, output_chunk3;
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0],
chunk_1_size,
&output_chunk1));
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[chunk_1_size],
chunk_2_size,
&output_chunk2));
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[chunk_1_size + chunk_2_size],
delta_file_.size()
- (chunk_1_size + chunk_2_size),
&output_chunk3));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(),
output_chunk1 + output_chunk2 + output_chunk3);
}
TEST_F(VCDiffStandardWindowDecoderTest, DecodeChunkNoVcdTargetAllowed) {
decoder_.SetAllowVcdTarget(false);
const size_t chunk_1_size = delta_file_header_.size() + 83;
CHECK_EQ(VCD_TARGET, static_cast<unsigned char>(delta_file_[chunk_1_size]));
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0], chunk_1_size, &output_));
EXPECT_FALSE(decoder_.DecodeChunk(&delta_file_[chunk_1_size], 1, &output_));
EXPECT_EQ(expected_target_.substr(0, 89).c_str(), output_);
}
TEST_F(VCDiffStandardWindowDecoderTest, DecodeInTwoParts) {
const size_t delta_file_size = delta_file_.size();
for (size_t i = 1; i < delta_file_size; i++) {
string output_chunk1, output_chunk2;
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0],
i,
&output_chunk1));
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i],
delta_file_size - i,
&output_chunk2));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_chunk1 + output_chunk2);
}
}
TEST_F(VCDiffStandardWindowDecoderTest, DecodeInThreeParts) {
const size_t delta_file_size = delta_file_.size();
for (size_t i = 1; i < delta_file_size - 1; i++) {
for (size_t j = i + 1; j < delta_file_size; j++) {
string output_chunk1, output_chunk2, output_chunk3;
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0],
i,
&output_chunk1));
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i],
j - i,
&output_chunk2));
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[j],
delta_file_size - j,
&output_chunk3));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(),
output_chunk1 + output_chunk2 + output_chunk3);
}
}
}
TEST_F(VCDiffStandardWindowDecoderTest, TargetMatchesWindowSizeLimit) {
decoder_.SetMaximumTargetWindowSize(kWindow2Size);
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffStandardWindowDecoderTest, TargetMatchesFileSizeLimit) {
decoder_.SetMaximumTargetFileSize(expected_target_.size());
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffStandardWindowDecoderTest, TargetExceedsWindowSizeLimit) {
decoder_.SetMaximumTargetWindowSize(kWindow2Size - 1);
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_EQ("", output_);
}
TEST_F(VCDiffStandardWindowDecoderTest, TargetExceedsFileSizeLimit) {
decoder_.SetMaximumTargetFileSize(expected_target_.size() - 1);
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_EQ("", output_);
}
typedef VCDiffStandardWindowDecoderTest
VCDiffStandardWindowDecoderTestByteByByte;
TEST_F(VCDiffStandardWindowDecoderTestByteByByte, Decode) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffStandardWindowDecoderTestByteByByte, DecodeExplicitVcdTarget) {
decoder_.SetAllowVcdTarget(true);
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffStandardWindowDecoderTestByteByByte, DecodeNoVcdTarget) {
decoder_.SetAllowVcdTarget(false);
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
size_t i = 0;
for (; i < delta_file_.size(); ++i) {
if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
break;
}
}
EXPECT_EQ(delta_file_header_.size() + 83, i);
EXPECT_EQ(expected_target_.substr(0, 89).c_str(), output_);
}
class VCDiffInterleavedWindowDecoderTest
: public VCDiffStandardWindowDecoderTest {
protected:
VCDiffInterleavedWindowDecoderTest();
virtual ~VCDiffInterleavedWindowDecoderTest() {}
private:
static const char kWindowBody[];
};
const char VCDiffInterleavedWindowDecoderTest::kWindowBody[] = {
VCD_SOURCE, FirstByteOfStringLength(kDictionary), SecondByteOfStringLength(kDictionary),
0x00, 0x08, 0x1C, 0x00, 0x00, 0x03, 0x00, 0x13, 0x1C, 0x00, 0x00, 0x44, 0x3D, 0x00, 0x00, 0x3F, 0x00, 0x01, 0x3D, ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ',
'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n',
'T', 'h', 'a', 't', ' ',
'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ',
'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ',
't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n',
VCD_TARGET, 0x59, 0x00, 0x08, 0x2C, 0x00, 0x00, 0x03, 0x00, 0x23, 0x2C, 0x58, VCD_TARGET, 0x05, 0x2E, 0x09, 0x07, 0x00, 0x00, 0x04, 0x00, 0xA7, 'h', 'r',
0x00, 0x00, 0x0F, 0x09, 0x00, 0x00, 0x0A, 0x00, 0x0A, 'W', 'h', 'a', 't', ' ', 'I', ' ', 't', 'e',
0x00, 0x08, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 'l',
0x00, 0x22, 0x1B, 0x00, 0x00, 0x1D, 0x00, 0x01, 0x1B, ' ', 'y', 'o', 'u', ' ',
't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ',
't', 'r', 'u', 'e', '.', '\"', '\n',
};
VCDiffInterleavedWindowDecoderTest::VCDiffInterleavedWindowDecoderTest() {
UseInterleavedFileHeader();
delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
}
TEST_F(VCDiffInterleavedWindowDecoderTest, Decode) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffInterleavedWindowDecoderTest, DecodeInTwoParts) {
const size_t delta_file_size = delta_file_.size();
for (size_t i = 1; i < delta_file_size; i++) {
string output_chunk1, output_chunk2;
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0],
i,
&output_chunk1));
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i],
delta_file_size - i,
&output_chunk2));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_chunk1 + output_chunk2);
}
}
TEST_F(VCDiffInterleavedWindowDecoderTest, DecodeInThreeParts) {
const size_t delta_file_size = delta_file_.size();
for (size_t i = 1; i < delta_file_size - 1; i++) {
for (size_t j = i + 1; j < delta_file_size; j++) {
string output_chunk1, output_chunk2, output_chunk3;
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[0],
i,
&output_chunk1));
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i],
j - i,
&output_chunk2));
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[j],
delta_file_size - j,
&output_chunk3));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(),
output_chunk1 + output_chunk2 + output_chunk3);
}
}
}
typedef VCDiffInterleavedWindowDecoderTest
VCDiffInterleavedWindowDecoderTestByteByByte;
TEST_F(VCDiffInterleavedWindowDecoderTestByteByByte, Decode) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffInterleavedWindowDecoderTestByteByByte, DecodeNoVcdTarget) {
decoder_.SetAllowVcdTarget(false);
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
size_t i = 0;
for (; i < delta_file_.size(); ++i) {
if (!decoder_.DecodeChunk(&delta_file_[i], 1, &output_)) {
break;
}
}
EXPECT_EQ(delta_file_header_.size() + 83, i);
EXPECT_EQ(expected_target_.substr(0, 89).c_str(), output_);
}
TEST_F(VCDiffInterleavedWindowDecoderTest, OutputStringCanBeModified) {
string temp_output;
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &temp_output));
output_.append(temp_output);
temp_output.clear();
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffInterleavedWindowDecoderTest, OutputStringIsPreserved) {
const string previous_data("Previous data");
output_ = previous_data;
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ((previous_data + expected_target_).c_str(), output_);
}
class VCDiffStandardCrossDecoderTest : public VCDiffDecoderTest {
protected:
static const char kExpectedTarget[];
static const char kWindowHeader[];
static const char kWindowBody[];
VCDiffStandardCrossDecoderTest();
virtual ~VCDiffStandardCrossDecoderTest() {}
};
const char VCDiffStandardCrossDecoderTest::kWindowHeader[] = {
VCD_SOURCE, FirstByteOfStringLength(kDictionary), SecondByteOfStringLength(kDictionary),
0x00, 0x15, StringLengthAsByte(kExpectedTarget), 0x00, 0x07, 0x06, 0x03 };
const char VCDiffStandardCrossDecoderTest::kWindowBody[] = {
'S', 'p', 'i', 'd', 'e', 'r', 's',
0x01, 0x07, 0x23, 0x19, 0x14, 0x25, 0x15, 0x06, 0x14 };
const char VCDiffStandardCrossDecoderTest::kExpectedTarget[] =
"Spiders in his hair.\n"
"Spiders in the air.\n";
VCDiffStandardCrossDecoderTest::VCDiffStandardCrossDecoderTest() {
UseStandardFileHeader();
delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader));
delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
expected_target_.assign(kExpectedTarget);
}
TEST_F(VCDiffStandardCrossDecoderTest, Decode) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
typedef VCDiffStandardCrossDecoderTest VCDiffStandardCrossDecoderTestByteByByte;
TEST_F(VCDiffStandardCrossDecoderTestByteByByte, Decode) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
class VCDiffInterleavedCrossDecoderTest
: public VCDiffStandardCrossDecoderTest {
protected:
VCDiffInterleavedCrossDecoderTest();
virtual ~VCDiffInterleavedCrossDecoderTest() {}
private:
static const char kWindowHeader[];
static const char kWindowBody[];
};
const char VCDiffInterleavedCrossDecoderTest::kWindowHeader[] = {
VCD_SOURCE, FirstByteOfStringLength(kDictionary), SecondByteOfStringLength(kDictionary),
0x00, 0x15, StringLengthAsByte(kExpectedTarget), 0x00, 0x00, 0x10, 0x00, };
const char VCDiffInterleavedCrossDecoderTest::kWindowBody[] = {
0x01, 0x07, 'S', 'p', 'i', 'd', 'e', 'r', 's',
0x23, 0x19, 0x15, 0x14, 0x06, 0x25, 0x14 };
VCDiffInterleavedCrossDecoderTest::VCDiffInterleavedCrossDecoderTest() {
UseInterleavedFileHeader();
delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader));
delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
}
TEST_F(VCDiffInterleavedCrossDecoderTest, Decode) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffInterleavedCrossDecoderTest, DecodeWithChecksum) {
ComputeAndAddChecksum();
InitializeDeltaFile();
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
typedef VCDiffInterleavedCrossDecoderTest
VCDiffInterleavedCrossDecoderTestByteByByte;
TEST_F(VCDiffInterleavedCrossDecoderTestByteByByte, Decode) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffInterleavedCrossDecoderTestByteByByte, DecodeWithChecksum) {
ComputeAndAddChecksum();
InitializeDeltaFile();
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
class VCDiffCustomCodeTableDecoderTest : public VCDiffInterleavedDecoderTest {
protected:
static const char kFileHeader[];
static const char kWindowHeader[];
static const char kWindowBody[];
static const char kEncodedCustomCodeTable[];
VCDiffCustomCodeTableDecoderTest();
virtual ~VCDiffCustomCodeTableDecoderTest() {}
};
const char VCDiffCustomCodeTableDecoderTest::kFileHeader[] = {
0xD6, 0xC3, 0xC4, 'S', 0x02 };
const char VCDiffCustomCodeTableDecoderTest::kEncodedCustomCodeTable[] = {
0xD6, 0xC3, 0xC4, 'S', 0x00, VCD_SOURCE, (sizeof(VCDiffCodeTableData) >> 7) | 0x80, sizeof(VCDiffCodeTableData) & 0x7F, 0x00, 0x1F, (sizeof(VCDiffCodeTableData) >> 7) | 0x80, sizeof(VCDiffCodeTableData) & 0x7F, 0x00, 0x00, 0x19, 0x00, 0x05, VCD_RUN, VCD_ADD, VCD_ADD, VCD_RUN,
0x13, 0x84, 0x0D, 0x04, 0x03, 0x1B, 0x3D,
0x3F, 0x84, 0x0F, 0x02, 0x1C,
0x4F, 0x10, 0x02, 0x2C,
0x53, 0x87, 0x4D, 0x10 };
const char VCDiffCustomCodeTableDecoderTest::kWindowHeader[] = {
VCD_SOURCE, FirstByteOfStringLength(kDictionary), SecondByteOfStringLength(kDictionary),
0x00, 0x74, FirstByteOfStringLength(kExpectedTarget), SecondByteOfStringLength(kExpectedTarget),
0x00, 0x00, 0x6E, 0x00 };
const char VCDiffCustomCodeTableDecoderTest::kWindowBody[] = {
0x22, 0x00, 0x12, ' ', 'I', ' ', 'h', 'a', 'v', 'e', ' ', 's', 'a', 'i', 'd', ' ',
'i', 't', ' ', 't', 'w', 'i', 'c', 'e', ':', '\n',
'T', 'h', 'a', 't', ' ',
'a', 'l', 'o', 'n', 'e', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ',
'e', 'n', 'c', 'o', 'u', 'r', 'a', 'g', 'e', ' ',
't', 'h', 'e', ' ', 'c', 'r', 'e', 'w', '.', '\n',
0x32, 0x58, 0xBF, 'h', 'r',
0x2D, 0x0A, 'W', 'h', 'a', 't', ' ',
'I', ' ', 't', 'e',
0x03, 'l',
0x11, ' ', 'y', 'o', 'u', ' ',
't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ',
't', 'r', 'u', 'e', '.', '\"', '\n'
};
VCDiffCustomCodeTableDecoderTest::VCDiffCustomCodeTableDecoderTest() {
delta_file_header_.assign(kFileHeader, sizeof(kFileHeader));
delta_file_header_.push_back(0x01); delta_file_header_.push_back(0x06); delta_file_header_.append(kEncodedCustomCodeTable,
sizeof(kEncodedCustomCodeTable));
delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader));
delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
}
TEST_F(VCDiffCustomCodeTableDecoderTest, CustomCodeTableEncodingMatches) {
VCDiffCodeTableData custom_code_table(
VCDiffCodeTableData::kDefaultCodeTableData);
custom_code_table.inst1[3] = VCD_RUN;
custom_code_table.size1[17] = 27;
custom_code_table.size1[18] = 61;
custom_code_table.size1[34] = 28;
custom_code_table.size1[50] = 44;
decoder_.StartDecoding(
reinterpret_cast<const char*>(
&VCDiffCodeTableData::kDefaultCodeTableData),
sizeof(VCDiffCodeTableData::kDefaultCodeTableData));
EXPECT_TRUE(decoder_.DecodeChunk(kEncodedCustomCodeTable,
sizeof(kEncodedCustomCodeTable),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(sizeof(custom_code_table), output_.size());
const VCDiffCodeTableData* decoded_table =
reinterpret_cast<const VCDiffCodeTableData*>(output_.data());
EXPECT_EQ(VCD_RUN, decoded_table->inst1[0]);
EXPECT_EQ(VCD_RUN, decoded_table->inst1[3]);
EXPECT_EQ(27, decoded_table->size1[17]);
EXPECT_EQ(61, decoded_table->size1[18]);
EXPECT_EQ(28, decoded_table->size1[34]);
EXPECT_EQ(44, decoded_table->size1[50]);
for (int i = 0; i < VCDiffCodeTableData::kCodeTableSize; ++i) {
EXPECT_EQ(custom_code_table.inst1[i], decoded_table->inst1[i]);
EXPECT_EQ(custom_code_table.inst2[i], decoded_table->inst2[i]);
EXPECT_EQ(custom_code_table.size1[i], decoded_table->size1[i]);
EXPECT_EQ(custom_code_table.size2[i], decoded_table->size2[i]);
EXPECT_EQ(custom_code_table.mode1[i], decoded_table->mode1[i]);
EXPECT_EQ(custom_code_table.mode2[i], decoded_table->mode2[i]);
}
}
TEST_F(VCDiffCustomCodeTableDecoderTest, DecodeUsingCustomCodeTable) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffCustomCodeTableDecoderTest, IncompleteCustomCodeTable) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_TRUE(decoder_.DecodeChunk(delta_file_header_.data(),
delta_file_header_.size() - 1,
&output_));
EXPECT_FALSE(decoder_.FinishDecoding());
EXPECT_EQ("", output_);
}
typedef VCDiffCustomCodeTableDecoderTest
VCDiffCustomCodeTableDecoderTestByteByByte;
TEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, DecodeUsingCustomCodeTable) {
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
TEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, IncompleteCustomCodeTable) {
delta_file_.resize(delta_file_header_.size() - 1);
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_FALSE(decoder_.FinishDecoding());
EXPECT_EQ("", output_);
}
TEST_F(VCDiffCustomCodeTableDecoderTestByteByByte, CustomTableNoVcdTarget) {
decoder_.SetAllowVcdTarget(false);
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
for (size_t i = 0; i < delta_file_.size(); ++i) {
EXPECT_TRUE(decoder_.DecodeChunk(&delta_file_[i], 1, &output_));
}
EXPECT_TRUE(decoder_.FinishDecoding());
EXPECT_EQ(expected_target_.c_str(), output_);
}
#ifdef GTEST_HAS_DEATH_TEST
class VCDiffCustomCacheSizeTest : public VCDiffCustomCodeTableDecoderTest {
protected:
void CustomCacheSizeTest(int32_t near_value, int32_t same_value);
};
void VCDiffCustomCacheSizeTest::CustomCacheSizeTest(int32_t near_value,
int32_t same_value) {
SCOPED_TRACE(testing::Message() << "Near value: " << near_value
<< ", same value: " << same_value);
delta_file_header_.assign(kFileHeader, sizeof(kFileHeader));
VarintBE<int32_t>::AppendToString(near_value, &delta_file_header_);
VarintBE<int32_t>::AppendToString(same_value, &delta_file_header_);
delta_file_header_.append(kEncodedCustomCodeTable,
sizeof(kEncodedCustomCodeTable));
InitializeDeltaFile();
EXPECT_DEBUG_DEATH({
decoder_.StartDecoding(dictionary_.data(), dictionary_.size());
EXPECT_FALSE(decoder_.DecodeChunk(delta_file_.data(),
delta_file_.size(),
&output_));
}, "cache");
EXPECT_EQ("", output_);
}
TEST_F(VCDiffCustomCacheSizeTest, BadCustomCacheSizes) {
CustomCacheSizeTest(0x90, 0x90);
CustomCacheSizeTest(INT_MAX, INT_MAX);
}
TEST_F(VCDiffCustomCacheSizeTest, BadCustomCacheSizesNoVcdTarget) {
decoder_.SetAllowVcdTarget(false);
CustomCacheSizeTest(0x90, 0x90);
CustomCacheSizeTest(INT_MAX, INT_MAX);
}
#endif
} }