#include <config.h>
#include "decodetable.h"
#include <stdint.h>
#include <vector>
#include "addrcache.h"
#include "codetable.h"
#include "testing.h"
#include "varint_bigendian.h"
namespace open_vcdiff {
namespace {
class DecodeTableTest : public testing::Test {
protected:
DecodeTableTest()
: instructions_and_sizes_(instruction_buffer_size),
found_size_(0),
found_mode_(0) {
instructions_and_sizes_ptr_ = &instructions_and_sizes_[0];
reader_.Init(&instructions_and_sizes_ptr_,
instructions_and_sizes_ptr_ + instruction_buffer_size);
}
static void AddExerciseOpcode(unsigned char inst1,
unsigned char mode1,
unsigned char size1,
unsigned char inst2,
unsigned char mode2,
unsigned char size2,
int opcode) {
g_exercise_code_table_->inst1[opcode] = inst1;
g_exercise_code_table_->mode1[opcode] = mode1;
g_exercise_code_table_->size1[opcode] = (inst1 == VCD_NOOP) ? 0 : size1;
g_exercise_code_table_->inst2[opcode] = inst2;
g_exercise_code_table_->mode2[opcode] = mode2;
g_exercise_code_table_->size2[opcode] = (inst2 == VCD_NOOP) ? 0 : size2;
}
static void SetUpTestCase() {
g_exercise_code_table_ = new VCDiffCodeTableData;
int opcode = 0;
for (unsigned char inst_mode1 = 0;
inst_mode1 <= VCD_LAST_INSTRUCTION_TYPE + kLastExerciseMode;
++inst_mode1) {
unsigned char inst1 = inst_mode1;
unsigned char mode1 = 0;
if (inst_mode1 > VCD_COPY) {
inst1 = VCD_COPY;
mode1 = inst_mode1 - VCD_COPY;
}
for (unsigned char inst_mode2 = 0;
inst_mode2 <= VCD_LAST_INSTRUCTION_TYPE + kLastExerciseMode;
++inst_mode2) {
unsigned char inst2 = inst_mode2;
unsigned char mode2 = 0;
if (inst_mode2 > VCD_COPY) {
inst2 = VCD_COPY;
mode2 = inst_mode2 - VCD_COPY;
}
AddExerciseOpcode(inst1, mode1, 0, inst2, mode2, 0, opcode++);
AddExerciseOpcode(inst1, mode1, 0, inst2, mode2, 255, opcode++);
AddExerciseOpcode(inst1, mode1, 255, inst2, mode2, 0, opcode++);
AddExerciseOpcode(inst1, mode1, 255, inst2, mode2, 255, opcode++);
}
}
CHECK_EQ(VCDiffCodeTableData::kCodeTableSize, opcode);
EXPECT_TRUE(VCDiffCodeTableData::kDefaultCodeTableData.Validate());
EXPECT_TRUE(g_exercise_code_table_->Validate(kLastExerciseMode));
}
static void TearDownTestCase() {
delete g_exercise_code_table_;
}
void VerifyInstModeSize(unsigned char inst,
unsigned char mode,
unsigned char size,
unsigned char opcode) {
if (inst == VCD_NOOP) return; int32_t found_size = 0;
unsigned char found_mode = 0;
unsigned char found_inst = reader_.GetNextInstruction(&found_size,
&found_mode);
EXPECT_EQ(inst, found_inst);
EXPECT_EQ(mode, found_mode);
if (size == 0) {
EXPECT_EQ(1000 + opcode, found_size);
} else {
EXPECT_EQ(size, found_size);
}
}
void VerifyInstModeSize1(unsigned char inst,
unsigned char mode,
unsigned char size,
unsigned char opcode) {
if (inst == VCD_NOOP) size = 0;
EXPECT_EQ(g_exercise_code_table_->inst1[opcode], inst);
EXPECT_EQ(g_exercise_code_table_->mode1[opcode], mode);
EXPECT_EQ(g_exercise_code_table_->size1[opcode], size);
VerifyInstModeSize(inst, mode, size, opcode);
}
void VerifyInstModeSize2(unsigned char inst,
unsigned char mode,
unsigned char size,
unsigned char opcode) {
if (inst == VCD_NOOP) size = 0;
EXPECT_EQ(g_exercise_code_table_->inst2[opcode], inst);
EXPECT_EQ(g_exercise_code_table_->mode2[opcode], mode);
EXPECT_EQ(g_exercise_code_table_->size2[opcode], size);
VerifyInstModeSize(inst, mode, size, opcode);
}
static const int kLastExerciseMode = 4;
static const int instruction_buffer_size;
static VCDiffCodeTableData* g_exercise_code_table_;
VCDiffCodeTableReader reader_;
std::vector<char> instructions_and_sizes_;
const char* instructions_and_sizes_ptr_;
int32_t found_size_;
unsigned char found_mode_;
};
VCDiffCodeTableData* DecodeTableTest::g_exercise_code_table_ = NULL;
const int DecodeTableTest::instruction_buffer_size =
VCDiffCodeTableData::kCodeTableSize *
(1 + (VarintBE<VCDAddress>::kMaxBytes));
TEST_F(DecodeTableTest, ReadAdd) {
instructions_and_sizes_[0] = 1;
VarintBE<VCDAddress>::Encode(257, &instructions_and_sizes_[1]);
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_ADD, found_inst);
EXPECT_EQ(257, found_size_);
EXPECT_EQ(0, found_mode_);
}
TEST_F(DecodeTableTest, ReadRun) {
instructions_and_sizes_[0] = 0;
VarintBE<VCDAddress>::Encode(111, &instructions_and_sizes_[1]);
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_RUN, found_inst);
EXPECT_EQ(111, found_size_);
EXPECT_EQ(0, found_mode_);
}
TEST_F(DecodeTableTest, ReadCopy) {
instructions_and_sizes_[0] = 58;
instructions_and_sizes_[1] = 0;
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(10, found_size_);
EXPECT_EQ(2, found_mode_);
}
TEST_F(DecodeTableTest, ReadAddCopy) {
instructions_and_sizes_[0] = 175;
instructions_and_sizes_[1] = 0;
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_ADD, found_inst);
EXPECT_EQ(1, found_size_);
EXPECT_EQ(0, found_mode_);
found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(4, found_size_);
EXPECT_EQ(1, found_mode_);
}
TEST_F(DecodeTableTest, ReadCopyAdd) {
instructions_and_sizes_[0] = 255;
instructions_and_sizes_[1] = 0;
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(4, found_size_);
EXPECT_EQ(8, found_mode_);
found_mode_ = 0;
found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
EXPECT_EQ(VCD_ADD, found_inst);
EXPECT_EQ(1, found_size_);
EXPECT_EQ(0, found_mode_);
}
TEST_F(DecodeTableTest, UnGetAdd) {
instructions_and_sizes_[0] = 1;
instructions_and_sizes_[1] = 255;
VarintBE<VCDAddress>::Encode(257, &instructions_and_sizes_[1]);
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_ADD, found_inst);
EXPECT_EQ(257, found_size_);
EXPECT_EQ(0, found_mode_);
reader_.UnGetInstruction();
found_size_ = 0;
found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
EXPECT_EQ(VCD_ADD, found_inst);
EXPECT_EQ(257, found_size_);
EXPECT_EQ(0, found_mode_);
}
TEST_F(DecodeTableTest, UnGetCopy) {
instructions_and_sizes_[0] = 58;
instructions_and_sizes_[1] = 0;
instructions_and_sizes_[2] = 255;
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(10, found_size_);
EXPECT_EQ(2, found_mode_);
reader_.UnGetInstruction();
found_size_ = 0;
found_mode_ = 0;
found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(10, found_size_);
EXPECT_EQ(2, found_mode_);
}
TEST_F(DecodeTableTest, UnGetCopyAdd) {
instructions_and_sizes_[0] = 255;
instructions_and_sizes_[1] = 0;
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(4, found_size_);
EXPECT_EQ(8, found_mode_);
reader_.UnGetInstruction();
found_mode_ = 0;
found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(4, found_size_);
EXPECT_EQ(8, found_mode_);
found_mode_ = 0;
found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
EXPECT_EQ(VCD_ADD, found_inst);
EXPECT_EQ(1, found_size_);
EXPECT_EQ(0, found_mode_);
}
TEST_F(DecodeTableTest, UnGetTwice) {
instructions_and_sizes_[0] = 255;
instructions_and_sizes_[1] = 0;
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(4, found_size_);
EXPECT_EQ(8, found_mode_);
reader_.UnGetInstruction();
reader_.UnGetInstruction();
found_mode_ = 0;
found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(4, found_size_);
EXPECT_EQ(8, found_mode_);
found_mode_ = 0;
found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
EXPECT_EQ(VCD_ADD, found_inst);
EXPECT_EQ(1, found_size_);
EXPECT_EQ(0, found_mode_);
}
TEST_F(DecodeTableTest, UnGetBeforeGet) {
instructions_and_sizes_[0] = 255;
instructions_and_sizes_[1] = 0;
reader_.UnGetInstruction();
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(4, found_size_);
EXPECT_EQ(8, found_mode_);
}
TEST_F(DecodeTableTest, UnGetAddCopy) {
instructions_and_sizes_[0] = 175;
instructions_and_sizes_[1] = 0;
unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
&found_mode_);
EXPECT_EQ(VCD_ADD, found_inst);
EXPECT_EQ(1, found_size_);
EXPECT_EQ(0, found_mode_);
reader_.UnGetInstruction();
found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
EXPECT_EQ(VCD_ADD, found_inst);
EXPECT_EQ(1, found_size_);
EXPECT_EQ(0, found_mode_);
found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
EXPECT_EQ(VCD_COPY, found_inst);
EXPECT_EQ(4, found_size_);
EXPECT_EQ(1, found_mode_);
}
TEST_F(DecodeTableTest, ReReadIncomplete) {
instructions_and_sizes_[0] = 175; instructions_and_sizes_[1] = 1; instructions_and_sizes_[2] = 111; instructions_and_sizes_[3] = 255;
reader_.Init(&instructions_and_sizes_ptr_,
instructions_and_sizes_ptr_ + 0); EXPECT_EQ(VCD_INSTRUCTION_END_OF_DATA,
reader_.GetNextInstruction(&found_size_, &found_mode_));
EXPECT_EQ(&instructions_and_sizes_[0], instructions_and_sizes_ptr_);
reader_.Init(&instructions_and_sizes_ptr_,
instructions_and_sizes_ptr_ + 1); EXPECT_EQ(VCD_ADD, reader_.GetNextInstruction(&found_size_, &found_mode_));
EXPECT_EQ(1, found_size_);
EXPECT_EQ(0, found_mode_);
EXPECT_EQ(VCD_COPY, reader_.GetNextInstruction(&found_size_, &found_mode_));
EXPECT_EQ(4, found_size_);
EXPECT_EQ(1, found_mode_);
EXPECT_EQ(VCD_INSTRUCTION_END_OF_DATA,
reader_.GetNextInstruction(&found_size_, &found_mode_));
EXPECT_EQ(&instructions_and_sizes_[1], instructions_and_sizes_ptr_);
reader_.Init(&instructions_and_sizes_ptr_,
instructions_and_sizes_ptr_ + 1); EXPECT_EQ(VCD_INSTRUCTION_END_OF_DATA,
reader_.GetNextInstruction(&found_size_, &found_mode_));
EXPECT_EQ(&instructions_and_sizes_[1], instructions_and_sizes_ptr_);
reader_.Init(&instructions_and_sizes_ptr_,
instructions_and_sizes_ptr_ + 2); EXPECT_EQ(VCD_ADD, reader_.GetNextInstruction(&found_size_, &found_mode_));
EXPECT_EQ(111, found_size_);
EXPECT_EQ(0, found_mode_);
EXPECT_EQ(VCD_INSTRUCTION_END_OF_DATA,
reader_.GetNextInstruction(&found_size_, &found_mode_));
EXPECT_EQ(&instructions_and_sizes_[3], instructions_and_sizes_ptr_);
reader_.Init(&instructions_and_sizes_ptr_,
instructions_and_sizes_ptr_ + 1); EXPECT_EQ(VCD_COPY, reader_.GetNextInstruction(&found_size_, &found_mode_));
EXPECT_EQ(4, found_size_);
EXPECT_EQ(8, found_mode_);
EXPECT_EQ(VCD_ADD, reader_.GetNextInstruction(&found_size_, &found_mode_));
EXPECT_EQ(1, found_size_);
EXPECT_EQ(0, found_mode_);
EXPECT_EQ(VCD_INSTRUCTION_END_OF_DATA,
reader_.GetNextInstruction(&found_size_, &found_mode_));
EXPECT_EQ(&instructions_and_sizes_[4], instructions_and_sizes_ptr_);
}
TEST_F(DecodeTableTest, ExerciseCodeTableReader) {
char* instruction_ptr = &instructions_and_sizes_[0];
for (int opcode = 0; opcode < VCDiffCodeTableData::kCodeTableSize; ++opcode) {
*instruction_ptr = opcode;
++instruction_ptr;
if ((g_exercise_code_table_->inst1[opcode] != VCD_NOOP) &&
(g_exercise_code_table_->size1[opcode] == 0)) {
int encoded_size = VarintBE<VCDAddress>::Encode(1000 + opcode,
instruction_ptr);
EXPECT_LT(0, encoded_size);
instruction_ptr += encoded_size;
}
if ((g_exercise_code_table_->inst2[opcode] != VCD_NOOP) &&
(g_exercise_code_table_->size2[opcode] == 0)) {
int encoded_size = VarintBE<VCDAddress>::Encode(1000 + opcode,
instruction_ptr);
EXPECT_LT(0, encoded_size);
instruction_ptr += encoded_size;
}
}
EXPECT_TRUE(reader_.UseCodeTable(*g_exercise_code_table_, kLastExerciseMode));
int opcode = 0;
for (unsigned char inst_mode1 = 0;
inst_mode1 <= VCD_LAST_INSTRUCTION_TYPE + kLastExerciseMode;
++inst_mode1) {
unsigned char inst1 = inst_mode1;
unsigned char mode1 = 0;
if (inst_mode1 > VCD_COPY) {
inst1 = VCD_COPY;
mode1 = inst_mode1 - VCD_COPY;
}
for (unsigned char inst_mode2 = 0;
inst_mode2 <= VCD_LAST_INSTRUCTION_TYPE + kLastExerciseMode;
++inst_mode2) {
unsigned char inst2 = inst_mode2;
unsigned char mode2 = 0;
if (inst_mode2 > VCD_COPY) {
inst2 = VCD_COPY;
mode2 = inst_mode2 - VCD_COPY;
}
VerifyInstModeSize1(inst1, mode1, 0, opcode);
VerifyInstModeSize2(inst2, mode2, 0, opcode);
++opcode;
VerifyInstModeSize1(inst1, mode1, 0, opcode);
VerifyInstModeSize2(inst2, mode2, 255, opcode);
++opcode;
VerifyInstModeSize1(inst1, mode1, 255, opcode);
VerifyInstModeSize2(inst2, mode2, 0, opcode);
++opcode;
VerifyInstModeSize1(inst1, mode1, 255, opcode);
VerifyInstModeSize2(inst2, mode2, 255, opcode);
++opcode;
}
}
CHECK_EQ(VCDiffCodeTableData::kCodeTableSize, opcode);
}
} }