#include <config.h>
#include "vcdecoder_test.h"
#include <string.h>
#include "checksum.h"
#include "codetable.h"
#include "testing.h"
#include "varint_bigendian.h"
#include "vcdiff_defs.h"
namespace open_vcdiff {
const char VCDiffDecoderTest::kStandardFileHeader[] = {
0xD6, 0xC3, 0xC4, 0x00, 0x00 };
const char VCDiffDecoderTest::kInterleavedFileHeader[] = {
0xD6, 0xC3, 0xC4, 'S', 0x00 };
const char VCDiffDecoderTest::kDictionary[] =
"\"Just the place for a Snark!\" the Bellman cried,\n"
"As he landed his crew with care;\n"
"Supporting each man on the top of the tide\n"
"By a finger entwined in his hair.\n";
const char VCDiffDecoderTest::kExpectedTarget[] =
"\"Just the place for a Snark! I have said it twice:\n"
"That alone should encourage the crew.\n"
"Just the place for a Snark! I have said it thrice:\n"
"What I tell you three times is true.\"\n";
VCDiffDecoderTest::VCDiffDecoderTest() : fuzzer_(0), fuzzed_byte_position_(0) {
dictionary_ = kDictionary;
expected_target_ = kExpectedTarget;
}
void VCDiffDecoderTest::SetUp() {
InitializeDeltaFile();
}
void VCDiffDecoderTest::UseStandardFileHeader() {
delta_file_header_.assign(kStandardFileHeader,
sizeof(kStandardFileHeader));
}
void VCDiffDecoderTest::UseInterleavedFileHeader() {
delta_file_header_.assign(kInterleavedFileHeader,
sizeof(kInterleavedFileHeader));
}
void VCDiffDecoderTest::InitializeDeltaFile() {
delta_file_ = delta_file_header_ + delta_window_header_ + delta_window_body_;
}
char VCDiffDecoderTest::GetByteFromStringLength(const char* s,
int which_byte) {
char varint_buf[VarintBE<int32_t>::kMaxBytes];
VarintBE<int32_t>::Encode(static_cast<int32_t>(strlen(s)), varint_buf);
return varint_buf[which_byte];
}
void VCDiffDecoderTest::AddChecksum(VCDChecksum checksum) {
int32_t checksum_as_int32 = static_cast<int32_t>(checksum);
delta_window_header_[0] |= VCD_CHECKSUM;
VarintBE<int32_t>::AppendToString(checksum_as_int32, &delta_window_header_);
delta_window_header_[4] += VarintBE<int32_t>::Length(checksum_as_int32);
}
void VCDiffDecoderTest::ComputeAndAddChecksum() {
AddChecksum(ComputeAdler32(expected_target_.data(),
expected_target_.size()));
}
void VCDiffDecoderTest::WriteMaxVarintAtOffset(int offset,
int bytes_to_replace) {
static const char kMaxVarint[] = { 0x87, 0xFF, 0xFF, 0xFF, 0x7F };
delta_file_.replace(delta_file_header_.size() + offset,
bytes_to_replace,
kMaxVarint,
sizeof(kMaxVarint));
}
void VCDiffDecoderTest::WriteNegativeVarintAtOffset(int offset,
int bytes_to_replace) {
static const char kNegativeVarint[] = { 0x88, 0x80, 0x80, 0x80, 0x00 };
delta_file_.replace(delta_file_header_.size() + offset,
bytes_to_replace,
kNegativeVarint,
sizeof(kNegativeVarint));
}
void VCDiffDecoderTest::WriteInvalidVarintAtOffset(int offset,
int bytes_to_replace) {
static const char kInvalidVarint[] = { 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F };
delta_file_.replace(delta_file_header_.size() + offset,
bytes_to_replace,
kInvalidVarint,
sizeof(kInvalidVarint));
}
bool VCDiffDecoderTest::FuzzOneByteInDeltaFile() {
static const struct Fuzzer {
char _and;
char _or;
char _xor;
} fuzzers[] = {
{ 0xff, 0x80, 0x00 },
{ 0xff, 0xff, 0x00 },
{ 0xff, 0x00, 0x80 },
{ 0xff, 0x00, 0xff },
{ 0xff, 0x01, 0x00 },
{ 0x7f, 0x00, 0x00 },
};
for (; fuzzer_ < (sizeof(fuzzers) / sizeof(fuzzers[0])); ++fuzzer_) {
for (; fuzzed_byte_position_ < delta_file_.size();
++fuzzed_byte_position_) {
char fuzzed_byte = (((delta_file_[fuzzed_byte_position_]
& fuzzers[fuzzer_]._and)
| fuzzers[fuzzer_]._or)
^ fuzzers[fuzzer_]._xor);
if (fuzzed_byte != delta_file_[fuzzed_byte_position_]) {
delta_file_[fuzzed_byte_position_] = fuzzed_byte;
++fuzzed_byte_position_;
return true;
}
}
fuzzed_byte_position_ = 0;
}
return false;
}
const char VCDiffStandardDecoderTest::kWindowHeader[] = {
VCD_SOURCE, FirstByteOfStringLength(kDictionary), SecondByteOfStringLength(kDictionary),
0x00, 0x79, FirstByteOfStringLength(kExpectedTarget), SecondByteOfStringLength(kExpectedTarget),
0x00, 0x64, 0x0C, 0x03 };
const char VCDiffStandardDecoderTest::kWindowBody[] = {
' ', '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',
'h', 'r',
'W', 'h', 'a', 't', ' ',
'I', ' ', 't', 'e',
'l',
' ', 'y', 'o', 'u', ' ',
't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ',
't', 'r', 'u', 'e', '.', '\"', '\n',
0x13, 0x1C, 0x01, 0x3D, 0x23, 0x2C, 0xCB, 0x0A, 0x00, 0x02, 0x01, 0x1B, 0x00, 0x58, 0x2D };
VCDiffStandardDecoderTest::VCDiffStandardDecoderTest() {
UseStandardFileHeader();
delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader));
delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
}
const char VCDiffInterleavedDecoderTest::kWindowHeader[] = {
VCD_SOURCE, FirstByteOfStringLength(kDictionary), SecondByteOfStringLength(kDictionary),
0x00, 0x79, FirstByteOfStringLength(kExpectedTarget), SecondByteOfStringLength(kExpectedTarget),
0x00, 0x00, 0x73, 0x00 };
const char VCDiffInterleavedDecoderTest::kWindowBody[] = {
0x13, 0x1C, 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',
0x23, 0x2C, 0x58, 0xCB, 'h', 'r',
0x2D, 0x0A, 'W', 'h', 'a', 't', ' ',
'I', ' ', 't', 'e',
0x00, 0x02, 'l',
0x01, 0x1B, ' ', 'y', 'o', 'u', ' ',
't', 'h', 'r', 'e', 'e', ' ', 't', 'i', 'm', 'e', 's', ' ', 'i', 's', ' ',
't', 'r', 'u', 'e', '.', '\"', '\n'
};
VCDiffInterleavedDecoderTest::VCDiffInterleavedDecoderTest() {
UseInterleavedFileHeader();
delta_window_header_.assign(kWindowHeader, sizeof(kWindowHeader));
delta_window_body_.assign(kWindowBody, sizeof(kWindowBody));
}
}