blob: 8e716fbd6849b3ad319f010829b9667dc443bcc4 [file] [log] [blame]
openvcdiff311c7142008-08-26 19:29:25 +00001// Copyright 2008 Google Inc.
2// Author: Lincoln Smith
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16// Unit tests for struct VCDiffCodeTableData, found in codetable.h.
17
18#include <config.h>
19#include "codetable.h"
20#include "addrcache.h"
21#include "testing.h"
22
23namespace open_vcdiff {
24namespace {
25
26class CodeTableTest : public testing::Test {
27 protected:
28 CodeTableTest()
29 : code_table_data_(VCDiffCodeTableData::kDefaultCodeTableData) { }
30
31 virtual ~CodeTableTest() { }
32
33 virtual void SetUp() {
34 // Default code table must pass
35 EXPECT_TRUE(ValidateCodeTable());
36 }
37
38 static void AddExerciseOpcode(unsigned char inst1,
39 unsigned char mode1,
40 unsigned char size1,
41 unsigned char inst2,
42 unsigned char mode2,
43 unsigned char size2,
44 int opcode) {
45 g_exercise_code_table_->inst1[opcode] = inst1;
46 g_exercise_code_table_->mode1[opcode] = mode1;
47 g_exercise_code_table_->size1[opcode] = (inst1 == VCD_NOOP) ? 0 : size1;
48 g_exercise_code_table_->inst2[opcode] = inst2;
49 g_exercise_code_table_->mode2[opcode] = mode2;
50 g_exercise_code_table_->size2[opcode] = (inst2 == VCD_NOOP) ? 0 : size2;
51 }
52
53 static void SetUpTestCase() {
54 g_exercise_code_table_ = new VCDiffCodeTableData;
55 int opcode = 0;
56 for (unsigned char inst_mode1 = 0;
57 inst_mode1 <= VCD_LAST_INSTRUCTION_TYPE + kLastExerciseMode;
58 ++inst_mode1) {
59 unsigned char inst1 = inst_mode1;
60 unsigned char mode1 = 0;
61 if (inst_mode1 > VCD_COPY) {
62 inst1 = VCD_COPY;
63 mode1 = inst_mode1 - VCD_COPY;
64 }
65 for (unsigned char inst_mode2 = 0;
66 inst_mode2 <= VCD_LAST_INSTRUCTION_TYPE + kLastExerciseMode;
67 ++inst_mode2) {
68 unsigned char inst2 = inst_mode2;
69 unsigned char mode2 = 0;
70 if (inst_mode2 > VCD_COPY) {
71 inst2 = VCD_COPY;
72 mode2 = inst_mode2 - VCD_COPY;
73 }
74 AddExerciseOpcode(inst1, mode1, 0, inst2, mode2, 0, opcode++);
75 AddExerciseOpcode(inst1, mode1, 0, inst2, mode2, 255, opcode++);
76 AddExerciseOpcode(inst1, mode1, 255, inst2, mode2, 0, opcode++);
77 AddExerciseOpcode(inst1, mode1, 255, inst2, mode2, 255, opcode++);
78 }
79 }
80 // This is a CHECK rather than an EXPECT because it validates only
81 // the logic of the test, not of the code being tested.
82 CHECK_EQ(VCDiffCodeTableData::kCodeTableSize, opcode);
83
84 EXPECT_TRUE(VCDiffCodeTableData::kDefaultCodeTableData.Validate());
85 EXPECT_TRUE(g_exercise_code_table_->Validate(kLastExerciseMode));
86 }
87
88 static void TearDownTestCase() {
89 delete g_exercise_code_table_;
90 }
91
92 void VerifyInstruction(unsigned char opcode,
93 unsigned char inst,
94 unsigned char size,
95 unsigned char mode) {
96 EXPECT_EQ(inst, code_table_data_.inst1[opcode]);
97 EXPECT_EQ(size, code_table_data_.size1[opcode]);
98 EXPECT_EQ(mode, code_table_data_.mode1[opcode]);
99 EXPECT_EQ(VCD_NOOP, code_table_data_.inst2[opcode]);
100 EXPECT_EQ(0, code_table_data_.size2[opcode]);
101 EXPECT_EQ(0, code_table_data_.mode2[opcode]);
102 }
103
104 bool ValidateCodeTable() {
105 return code_table_data_.Validate();
106 }
107
108 // This value is designed so that the total number of inst values and modes
109 // will equal 8 (VCD_NOOP, VCD_ADD, VCD_RUN, VCD_COPY modes 0 - 4).
110 // Eight combinations of inst and mode, times two possible size values,
111 // squared (because there are two instructions per opcode), makes
112 // exactly 256 possible instruction combinations, which fits kCodeTableSize
113 // (the number of opcodes in the table.)
114 static const int kLastExerciseMode = 4;
115
116 // A code table that exercises as many combinations as possible:
117 // 2 instructions, each is a NOOP, ADD, RUN, or one of 5 copy modes
118 // (== 8 total combinations of inst and mode), and each has
119 // size == 0 or 255 (2 possibilities.)
120 static VCDiffCodeTableData* g_exercise_code_table_;
121
122 // The code table used by the current test.
123 VCDiffCodeTableData code_table_data_;
124};
125
126VCDiffCodeTableData* CodeTableTest::g_exercise_code_table_ = NULL;
127
128// These tests make sure that ValidateCodeTable() catches particular
129// error conditions in a custom code table.
130
131// All possible combinations of inst and mode should have an opcode with size 0.
132TEST_F(CodeTableTest, MissingCopyMode) {
133 VerifyInstruction(/* opcode */ 131, VCD_COPY, /* size */ 0, /* mode */ 7);
134 code_table_data_.size1[131] = 0xFF;
135 // Now there is no opcode expressing COPY with mode 7 and size 0.
136 EXPECT_FALSE(ValidateCodeTable());
137}
138
139TEST_F(CodeTableTest, MissingAdd) {
140 VerifyInstruction(/* opcode */ 1, VCD_ADD, /* size */ 0, /* mode */ 0);
141 code_table_data_.size1[1] = 0xFF; // Add size 0 => size 255
142 // Now there is no opcode expressing ADD with size 0.
143 EXPECT_FALSE(ValidateCodeTable());
144}
145
146TEST_F(CodeTableTest, MissingRun) {
147 VerifyInstruction(/* opcode */ 0, VCD_RUN, /* size */ 0, /* mode */ 0);
148 code_table_data_.size1[0] = 0xFF; // Run size 0 => size 255
149 // Now there is no opcode expressing RUN with size 0.
150 EXPECT_FALSE(ValidateCodeTable());
151}
152
153TEST_F(CodeTableTest, BadOpcode) {
154 VerifyInstruction(/* opcode */ 0, VCD_RUN, /* size */ 0, /* mode */ 0);
155 code_table_data_.inst1[0] = VCD_LAST_INSTRUCTION_TYPE + 1;
156 EXPECT_FALSE(ValidateCodeTable());
157 code_table_data_.inst1[0] = 0xFF;
158 EXPECT_FALSE(ValidateCodeTable());
159}
160
161TEST_F(CodeTableTest, BadMode) {
162 VerifyInstruction(/* opcode */ 131, VCD_COPY, /* size */ 0, /* mode */ 7);
163 code_table_data_.mode1[131] = VCDiffAddressCache::DefaultLastMode() + 1;
164 EXPECT_FALSE(ValidateCodeTable());
165 code_table_data_.mode1[131] = 0xFF;
166 EXPECT_FALSE(ValidateCodeTable());
167}
168
169TEST_F(CodeTableTest, AddWithNonzeroMode) {
170 VerifyInstruction(/* opcode */ 1, VCD_ADD, /* size */ 0, /* mode */ 0);
171 code_table_data_.mode1[1] = 1;
172 EXPECT_FALSE(ValidateCodeTable());
173}
174
175TEST_F(CodeTableTest, RunWithNonzeroMode) {
176 VerifyInstruction(/* opcode */ 0, VCD_RUN, /* size */ 0, /* mode */ 0);
177 code_table_data_.mode1[0] = 1;
178 EXPECT_FALSE(ValidateCodeTable());
179}
180
181TEST_F(CodeTableTest, NoOpWithNonzeroMode) {
182 VerifyInstruction(/* opcode */ 20, VCD_COPY, /* size */ 4, /* mode */ 0);
183 code_table_data_.inst1[20] = VCD_NOOP;
184 code_table_data_.mode1[20] = 0;
185 code_table_data_.size1[20] = 0;
186 EXPECT_TRUE(ValidateCodeTable());
187 code_table_data_.mode1[20] = 1;
188 EXPECT_FALSE(ValidateCodeTable());
189}
190
191TEST_F(CodeTableTest, NoOpWithNonzeroSize) {
192 VerifyInstruction(/* opcode */ 20, VCD_COPY, /* size */ 4, /* mode */ 0);
193 code_table_data_.inst1[20] = VCD_NOOP;
194 code_table_data_.mode1[20] = 0;
195 code_table_data_.size1[20] = 0;
196 EXPECT_TRUE(ValidateCodeTable());
197 code_table_data_.size1[20] = 1;
198 EXPECT_FALSE(ValidateCodeTable());
199}
200
201TEST_F(CodeTableTest, BadSecondOpcode) {
202 VerifyInstruction(/* opcode */ 20, VCD_COPY, /* size */ 4, /* mode */ 0);
203 code_table_data_.inst2[20] = VCD_LAST_INSTRUCTION_TYPE + 1;
204 EXPECT_FALSE(ValidateCodeTable());
205 code_table_data_.inst2[20] = 0xFF;
206 EXPECT_FALSE(ValidateCodeTable());
207}
208
209TEST_F(CodeTableTest, BadSecondMode) {
210 VerifyInstruction(/* opcode */ 20, VCD_COPY, /* size */ 4, /* mode */ 0);
211 code_table_data_.inst2[20] = VCD_COPY;
212 EXPECT_TRUE(ValidateCodeTable());
213 code_table_data_.mode2[20] = VCDiffAddressCache::DefaultLastMode() + 1;
214 EXPECT_FALSE(ValidateCodeTable());
215 code_table_data_.mode2[20] = 0xFF;
216 EXPECT_FALSE(ValidateCodeTable());
217}
218
219TEST_F(CodeTableTest, AddSecondWithNonzeroMode) {
220 VerifyInstruction(/* opcode */ 20, VCD_COPY, /* size */ 4, /* mode */ 0);
221 code_table_data_.inst2[20] = VCD_ADD;
222 EXPECT_TRUE(ValidateCodeTable());
223 code_table_data_.mode2[20] = 1;
224 EXPECT_FALSE(ValidateCodeTable());
225}
226
227TEST_F(CodeTableTest, RunSecondWithNonzeroMode) {
228 VerifyInstruction(/* opcode */ 20, VCD_COPY, /* size */ 4, /* mode */ 0);
229 code_table_data_.inst2[20] = VCD_RUN;
230 EXPECT_TRUE(ValidateCodeTable());
231 code_table_data_.mode2[20] = 1;
232 EXPECT_FALSE(ValidateCodeTable());
233}
234
235TEST_F(CodeTableTest, SecondNoOpWithNonzeroMode) {
236 VerifyInstruction(/* opcode */ 20, VCD_COPY, /* size */ 4, /* mode */ 0);
237 EXPECT_EQ(VCD_NOOP, code_table_data_.inst2[20]);
238 code_table_data_.mode2[20] = 1;
239 EXPECT_FALSE(ValidateCodeTable());
240}
241
242TEST_F(CodeTableTest, SecondNoOpWithNonzeroSize) {
243 VerifyInstruction(/* opcode */ 20, VCD_COPY, /* size */ 4, /* mode */ 0);
244 EXPECT_EQ(VCD_NOOP, code_table_data_.inst2[20]);
245 code_table_data_.size2[20] = 1;
246 EXPECT_FALSE(ValidateCodeTable());
247}
248
249TEST_F(CodeTableTest, ValidateExerciseCodeTable) {
250 EXPECT_TRUE(g_exercise_code_table_->Validate(kLastExerciseMode));
251}
252
253} // unnamed namespace
254} // namespace open_vcdiff