1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright 2008 Google Inc.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Author: Lincoln Smith
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Licensed under the Apache License, Version 2.0 (the "License");
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// you may not use this file except in compliance with the License.
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// You may obtain a copy of the License at
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//      http://www.apache.org/licenses/LICENSE-2.0
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Unless required by applicable law or agreed to in writing, software
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// distributed under the License is distributed on an "AS IS" BASIS,
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// See the License for the specific language governing permissions and
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// limitations under the License.
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Unit tests for the class VCDiffCodeTableReader, found in decodetable.h.
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <config.h>
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "decodetable.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdint.h>  // int32_t
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector>
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "addrcache.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "codetable.h"
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "varint_bigendian.h"
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace open_vcdiff {
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass DecodeTableTest : public testing::Test {
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DecodeTableTest()
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  : instructions_and_sizes_(instruction_buffer_size),
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    found_size_(0),
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    found_mode_(0) {
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    instructions_and_sizes_ptr_ = &instructions_and_sizes_[0];
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    reader_.Init(&instructions_and_sizes_ptr_,
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                 instructions_and_sizes_ptr_ + instruction_buffer_size);
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void AddExerciseOpcode(unsigned char inst1,
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                unsigned char mode1,
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                unsigned char size1,
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                unsigned char inst2,
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                unsigned char mode2,
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                unsigned char size2,
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                int opcode) {
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    g_exercise_code_table_->inst1[opcode] = inst1;
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    g_exercise_code_table_->mode1[opcode] = mode1;
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    g_exercise_code_table_->size1[opcode] = (inst1 == VCD_NOOP) ? 0 : size1;
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    g_exercise_code_table_->inst2[opcode] = inst2;
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    g_exercise_code_table_->mode2[opcode] = mode2;
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    g_exercise_code_table_->size2[opcode] = (inst2 == VCD_NOOP) ? 0 : size2;
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void SetUpTestCase() {
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    g_exercise_code_table_ = new VCDiffCodeTableData;
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int opcode = 0;
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (unsigned char inst_mode1 = 0;
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         inst_mode1 <= VCD_LAST_INSTRUCTION_TYPE + kLastExerciseMode;
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         ++inst_mode1) {
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      unsigned char inst1 = inst_mode1;
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      unsigned char mode1 = 0;
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (inst_mode1 > VCD_COPY) {
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        inst1 = VCD_COPY;
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        mode1 = inst_mode1 - VCD_COPY;
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      for (unsigned char inst_mode2 = 0;
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott           inst_mode2 <= VCD_LAST_INSTRUCTION_TYPE + kLastExerciseMode;
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott           ++inst_mode2) {
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        unsigned char inst2 = inst_mode2;
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        unsigned char mode2 = 0;
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (inst_mode2 > VCD_COPY) {
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          inst2 = VCD_COPY;
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          mode2 = inst_mode2 - VCD_COPY;
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        AddExerciseOpcode(inst1, mode1, 0, inst2, mode2, 0, opcode++);
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        AddExerciseOpcode(inst1, mode1, 0, inst2, mode2, 255, opcode++);
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        AddExerciseOpcode(inst1, mode1, 255, inst2, mode2, 0, opcode++);
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        AddExerciseOpcode(inst1, mode1, 255, inst2, mode2, 255, opcode++);
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CHECK_EQ(VCDiffCodeTableData::kCodeTableSize, opcode);
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(VCDiffCodeTableData::kDefaultCodeTableData.Validate());
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(g_exercise_code_table_->Validate(kLastExerciseMode));
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void TearDownTestCase() {
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete g_exercise_code_table_;
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void VerifyInstModeSize(unsigned char inst,
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          unsigned char mode,
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          unsigned char size,
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          unsigned char opcode) {
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (inst == VCD_NOOP) return;  // GetNextInstruction skips NOOPs
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t found_size = 0;
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    unsigned char found_mode = 0;
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    unsigned char found_inst = reader_.GetNextInstruction(&found_size,
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                          &found_mode);
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(inst, found_inst);
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(mode, found_mode);
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (size == 0) {
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ(1000 + opcode, found_size);
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ(size, found_size);
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void VerifyInstModeSize1(unsigned char inst,
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           unsigned char mode,
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           unsigned char size,
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           unsigned char opcode) {
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (inst == VCD_NOOP) size = 0;
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(g_exercise_code_table_->inst1[opcode], inst);
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(g_exercise_code_table_->mode1[opcode], mode);
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(g_exercise_code_table_->size1[opcode], size);
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VerifyInstModeSize(inst, mode, size, opcode);
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void VerifyInstModeSize2(unsigned char inst,
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           unsigned char mode,
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           unsigned char size,
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           unsigned char opcode) {
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (inst == VCD_NOOP) size = 0;
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(g_exercise_code_table_->inst2[opcode], inst);
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(g_exercise_code_table_->mode2[opcode], mode);
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(g_exercise_code_table_->size2[opcode], size);
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VerifyInstModeSize(inst, mode, size, opcode);
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This value is designed so that the total number of inst values and modes
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // will equal 8 (VCD_NOOP, VCD_ADD, VCD_RUN, VCD_COPY modes 0 - 4).
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Eight combinations of inst and mode, times two possible size values,
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // squared (because there are two instructions per opcode), makes
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // exactly 256 possible instruction combinations, which fits kCodeTableSize
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // (the number of opcodes in the table.)
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const int kLastExerciseMode = 4;
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The buffer size (in bytes) needed to store kCodeTableSize opcodes plus
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // up to kCodeTableSize VarintBE-encoded size values.
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const int instruction_buffer_size;
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // A code table that exercises as many combinations as possible:
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // 2 instructions, each is a NOOP, ADD, RUN, or one of 5 copy modes
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // (== 8 total combinations of inst and mode), and each has
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // size == 0 or 255 (2 possibilities.)
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static VCDiffCodeTableData* g_exercise_code_table_;
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffCodeTableReader reader_;
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // A buffer to which instructions and sizes will be added manually
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // in order to exercise VCDiffCodeTableReader.
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::vector<char> instructions_and_sizes_;
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The buffer pointer used by the VCDiffCodeTableReader.
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* instructions_and_sizes_ptr_;
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The size and mode returned by GetNextInstruction().
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int32_t found_size_;
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_mode_;
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottVCDiffCodeTableData* DecodeTableTest::g_exercise_code_table_ = NULL;
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int DecodeTableTest::instruction_buffer_size =
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCDiffCodeTableData::kCodeTableSize *
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        (1 + (VarintBE<VCDAddress>::kMaxBytes));
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, ReadAdd) {
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 1;
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VarintBE<VCDAddress>::Encode(257, &instructions_and_sizes_[1]);
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, found_inst);
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(257, found_size_);
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, ReadRun) {
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 0;
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VarintBE<VCDAddress>::Encode(111, &instructions_and_sizes_[1]);
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_RUN, found_inst);
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(111, found_size_);
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, ReadCopy) {
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 58;
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[1] = 0;
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(10, found_size_);
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(2, found_mode_);
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, ReadAddCopy) {
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 175;
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[1] = 0;
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, found_inst);
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_size_);
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, found_size_);
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_mode_);
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, ReadCopyAdd) {
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 255;
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[1] = 0;
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, found_size_);
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(8, found_mode_);
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_mode_ = 0;
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, found_inst);
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_size_);
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, UnGetAdd) {
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 1;
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[1] = 255;
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VarintBE<VCDAddress>::Encode(257, &instructions_and_sizes_[1]);
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, found_inst);
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(257, found_size_);
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.UnGetInstruction();
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_size_ = 0;
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, found_inst);
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(257, found_size_);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, UnGetCopy) {
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 58;
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[1] = 0;
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[2] = 255;
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(10, found_size_);
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(2, found_mode_);
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.UnGetInstruction();
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_size_ = 0;
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_mode_ = 0;
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(10, found_size_);
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(2, found_mode_);
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, UnGetCopyAdd) {
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 255;
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[1] = 0;
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, found_size_);
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(8, found_mode_);
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.UnGetInstruction();
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_mode_ = 0;
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, found_size_);
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(8, found_mode_);
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_mode_ = 0;
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, found_inst);
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_size_);
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, UnGetTwice) {
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 255;
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[1] = 0;
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, found_size_);
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(8, found_mode_);
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.UnGetInstruction();
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.UnGetInstruction();
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_mode_ = 0;
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, found_size_);
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(8, found_mode_);
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_mode_ = 0;
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, found_inst);
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_size_);
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, UnGetBeforeGet) {
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 255;
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[1] = 0;
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.UnGetInstruction();
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, found_size_);
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(8, found_mode_);
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, UnGetAddCopy) {
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 175;
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[1] = 0;
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unsigned char found_inst = reader_.GetNextInstruction(&found_size_,
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                        &found_mode_);
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, found_inst);
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_size_);
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.UnGetInstruction();
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, found_inst);
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_size_);
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  found_inst = reader_.GetNextInstruction(&found_size_, &found_mode_);
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, found_inst);
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, found_size_);
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_mode_);
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, ReReadIncomplete) {
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[0] = 175;  // Add(1) + Copy1(4)
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[1] = 1;    // Add(0)
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[2] = 111;  // with size 111
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  instructions_and_sizes_[3] = 255;  // Copy8(4) + Add(1)
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.Init(&instructions_and_sizes_ptr_,
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               instructions_and_sizes_ptr_ + 0);  // 0 bytes available
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_INSTRUCTION_END_OF_DATA,
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            reader_.GetNextInstruction(&found_size_, &found_mode_));
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(&instructions_and_sizes_[0], instructions_and_sizes_ptr_);
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.Init(&instructions_and_sizes_ptr_,
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              instructions_and_sizes_ptr_ + 1);  // 1 more byte available
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, reader_.GetNextInstruction(&found_size_, &found_mode_));
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_size_);
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, reader_.GetNextInstruction(&found_size_, &found_mode_));
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, found_size_);
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_mode_);
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_INSTRUCTION_END_OF_DATA,
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            reader_.GetNextInstruction(&found_size_, &found_mode_));
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(&instructions_and_sizes_[1], instructions_and_sizes_ptr_);
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.Init(&instructions_and_sizes_ptr_,
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              instructions_and_sizes_ptr_ + 1);  // 1 more byte available
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The opcode is available, but the separately encoded size is not
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_INSTRUCTION_END_OF_DATA,
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            reader_.GetNextInstruction(&found_size_, &found_mode_));
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(&instructions_and_sizes_[1], instructions_and_sizes_ptr_);
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.Init(&instructions_and_sizes_ptr_,
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              instructions_and_sizes_ptr_ + 2);  // 2 more bytes available
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, reader_.GetNextInstruction(&found_size_, &found_mode_));
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(111, found_size_);
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_INSTRUCTION_END_OF_DATA,
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            reader_.GetNextInstruction(&found_size_, &found_mode_));
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(&instructions_and_sizes_[3], instructions_and_sizes_ptr_);
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  reader_.Init(&instructions_and_sizes_ptr_,
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              instructions_and_sizes_ptr_ + 1);  // 1 more byte available
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_COPY, reader_.GetNextInstruction(&found_size_, &found_mode_));
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, found_size_);
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(8, found_mode_);
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_ADD, reader_.GetNextInstruction(&found_size_, &found_mode_));
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(1, found_size_);
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(0, found_mode_);
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(VCD_INSTRUCTION_END_OF_DATA,
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            reader_.GetNextInstruction(&found_size_, &found_mode_));
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(&instructions_and_sizes_[4], instructions_and_sizes_ptr_);
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DecodeTableTest, ExerciseCodeTableReader) {
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char* instruction_ptr = &instructions_and_sizes_[0];
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int opcode = 0; opcode < VCDiffCodeTableData::kCodeTableSize; ++opcode) {
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *instruction_ptr = opcode;
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ++instruction_ptr;
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if ((g_exercise_code_table_->inst1[opcode] != VCD_NOOP) &&
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        (g_exercise_code_table_->size1[opcode] == 0)) {
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // A separately-encoded size value
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int encoded_size = VarintBE<VCDAddress>::Encode(1000 + opcode,
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                      instruction_ptr);
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_LT(0, encoded_size);
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      instruction_ptr += encoded_size;
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if ((g_exercise_code_table_->inst2[opcode] != VCD_NOOP) &&
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        (g_exercise_code_table_->size2[opcode] == 0)) {
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int encoded_size = VarintBE<VCDAddress>::Encode(1000 + opcode,
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                      instruction_ptr);
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_LT(0, encoded_size);
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      instruction_ptr += encoded_size;
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(reader_.UseCodeTable(*g_exercise_code_table_, kLastExerciseMode));
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int opcode = 0;
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This loop has the same bounds as the one in SetUpTestCase.
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Iterate over the instruction types and make sure that the opcodes,
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // interpreted in order, return exactly those instruction types.
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (unsigned char inst_mode1 = 0;
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       inst_mode1 <= VCD_LAST_INSTRUCTION_TYPE + kLastExerciseMode;
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       ++inst_mode1) {
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    unsigned char inst1 = inst_mode1;
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    unsigned char mode1 = 0;
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (inst_mode1 > VCD_COPY) {
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      inst1 = VCD_COPY;
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      mode1 = inst_mode1 - VCD_COPY;
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (unsigned char inst_mode2 = 0;
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         inst_mode2 <= VCD_LAST_INSTRUCTION_TYPE + kLastExerciseMode;
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         ++inst_mode2) {
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      unsigned char inst2 = inst_mode2;
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      unsigned char mode2 = 0;
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (inst_mode2 > VCD_COPY) {
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        inst2 = VCD_COPY;
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        mode2 = inst_mode2 - VCD_COPY;
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      VerifyInstModeSize1(inst1, mode1, 0, opcode);
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      VerifyInstModeSize2(inst2, mode2, 0, opcode);
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ++opcode;
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      VerifyInstModeSize1(inst1, mode1, 0, opcode);
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      VerifyInstModeSize2(inst2, mode2, 255, opcode);
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ++opcode;
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      VerifyInstModeSize1(inst1, mode1, 255, opcode);
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      VerifyInstModeSize2(inst2, mode2, 0, opcode);
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ++opcode;
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      VerifyInstModeSize1(inst1, mode1, 255, opcode);
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      VerifyInstModeSize2(inst2, mode2, 255, opcode);
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ++opcode;
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK_EQ(VCDiffCodeTableData::kCodeTableSize, opcode);
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // unnamed namespace
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace open_vcdiff
453