1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "courgette/encoded_program.h"
13 #include "base/stl_util.h"
14 #include "courgette/image_utils.h"
15 #include "courgette/label_manager.h"
16 #include "courgette/streams.h"
17 #include "testing/gtest/include/gtest/gtest.h"
23 // Helper class to instantiate RVAToLabel while managing allocation.
24 class TestLabelManager : public LabelManager {
26 void RawAddLabel(int index, RVA rva) {
27 labels_.push_back(Label(rva, index)); // Don't care about |count_|.
31 // Creates a simple new program with given addresses. The orders of elements
32 // in |abs32_specs| and |rel32_specs| are important.
33 std::unique_ptr<EncodedProgram> CreateTestProgram(
34 const TestLabelManager& abs32_label_manager,
35 const TestLabelManager& rel32_label_manager) {
36 std::unique_ptr<EncodedProgram> program(new EncodedProgram());
38 uint32_t base = 0x00900000;
39 program->set_image_base(base);
41 EXPECT_TRUE(program->ImportLabels(abs32_label_manager, rel32_label_manager));
43 EXPECT_TRUE(program->AddOrigin(0)); // Start at base.
45 // Add instructions. Since we're using TestLabelManager, Labels are sorted in
46 // the order they're added via Add().
47 for (const Label& label : abs32_label_manager.Labels())
48 EXPECT_TRUE(program->AddAbs32(label.index_));
49 for (const Label& label : rel32_label_manager.Labels())
50 EXPECT_TRUE(program->AddRel32(label.index_));
55 bool CompareSink(const uint8_t expected[],
58 size_t n = ss->Length();
59 if (num_expected != n)
61 const uint8_t* buffer = ss->Buffer();
62 return memcmp(&expected[0], buffer, n) == 0;
67 // Create a simple program with a few addresses and references and
68 // check that the bits produced are as expected.
69 TEST(EncodedProgramTest, Test) {
70 // ABS32 index 7 <-- base + 4.
71 TestLabelManager abs32_label_manager;
72 abs32_label_manager.RawAddLabel(7, 4);
73 // REL32 index 5 <-- base + 0.
74 TestLabelManager rel32_label_manager;
75 rel32_label_manager.RawAddLabel(5, 0);
77 std::unique_ptr<EncodedProgram> program(
78 CreateTestProgram(abs32_label_manager, rel32_label_manager));
80 // Serialize and deserialize.
82 EXPECT_TRUE(program->WriteTo(&sinks));
86 bool can_collect = sinks.CopyTo(&sink);
87 EXPECT_TRUE(can_collect);
89 const void* buffer = sink.Buffer();
90 size_t length = sink.Length();
92 SourceStreamSet sources;
93 bool can_get_source_streams = sources.Init(buffer, length);
94 EXPECT_TRUE(can_get_source_streams);
96 std::unique_ptr<EncodedProgram> encoded2(new EncodedProgram());
97 bool can_read = encoded2->ReadFrom(&sources);
98 EXPECT_TRUE(can_read);
100 // Finally, try to assemble.
101 SinkStream assembled;
102 bool can_assemble = encoded2->AssembleTo(&assembled);
103 EXPECT_TRUE(can_assemble);
106 const uint8_t golden[] = {
108 0x00, // ABS32 to base + 4
110 0xFF // REL32 from next line to base + 2
112 EXPECT_TRUE(CompareSink(golden, base::size(golden), &assembled));
115 // A larger test with multiple addresses. We encode the program and check the
116 // contents of the address streams.
117 TEST(EncodedProgramTest, TestWriteAddress) {
118 // Absolute addresses by index: [_, _, _, 2, _, 23, _, 11].
119 TestLabelManager abs32_label_manager;
120 abs32_label_manager.RawAddLabel(7, 11);
121 abs32_label_manager.RawAddLabel(3, 2);
122 abs32_label_manager.RawAddLabel(5, 23);
123 // Relative addresses by index: [16, 7, _, 32].
124 TestLabelManager rel32_label_manager;
125 rel32_label_manager.RawAddLabel(0, 16);
126 rel32_label_manager.RawAddLabel(3, 32);
127 rel32_label_manager.RawAddLabel(1, 7);
129 std::unique_ptr<EncodedProgram> program(
130 CreateTestProgram(abs32_label_manager, rel32_label_manager));
133 EXPECT_TRUE(program->WriteTo(&sinks));
136 // Check indexes and addresses in sinks.
137 const uint8_t golden_abs32_indexes[] = {
138 0x03, 0x07, 0x03, 0x05 // 3 indexes: [7, 3, 5].
140 EXPECT_TRUE(CompareSink(golden_abs32_indexes,
141 base::size(golden_abs32_indexes),
142 sinks.stream(kStreamAbs32Indexes)));
144 const uint8_t golden_rel32_indexes[] = {
145 0x03, 0x00, 0x03, 0x01 // 3 indexes: [0, 3, 1].
147 EXPECT_TRUE(CompareSink(golden_rel32_indexes,
148 base::size(golden_rel32_indexes),
149 sinks.stream(kStreamRel32Indexes)));
151 // Addresses: [_, _, _, 2, _, 23, _, 11].
152 // Padded: [0, 0, 0, 2, 2, 23, 23, 11].
153 // Delta: [0, 0, 0, 2, 0, 21, 0, -12].
154 // Hex: [0, 0, 0, 0x02, 0, 0x15, 0, 0xFFFFFFF4].
155 // Complement neg: [0, 0, 0, 0x02, 0, 0x15, 0, (0x0B)].
156 // Varint32 Signed: [0, 0, 0, 0x04, 0, 0x2A, 0, 0x17].
157 const uint8_t golden_abs32_addresses[] = {
158 0x08, // 8 address deltas.
159 0x00, 0x00, 0x00, 0x04, 0x00, 0x2A, 0x00, 0x17,
161 EXPECT_TRUE(CompareSink(golden_abs32_addresses,
162 base::size(golden_abs32_addresses),
163 sinks.stream(kStreamAbs32Addresses)));
165 // Addresses: [16, 7, _, 32].
166 // Padded: [16, 7, 7, 32].
167 // Delta: [16, -9, 0, 25].
168 // Hex: [0x10, 0xFFFFFFF7, 0, 0x19].
169 // Complement Neg: [0x10, (0x08), 0, 0x19].
170 // Varint32 Signed: [0x20, 0x11, 0, 0x32].
171 const uint8_t golden_rel32_addresses[] = {
172 0x04, // 4 address deltas.
173 0x20, 0x11, 0x00, 0x32,
175 EXPECT_TRUE(CompareSink(golden_rel32_addresses,
176 base::size(golden_rel32_addresses),
177 sinks.stream(kStreamRel32Addresses)));
180 } // namespace courgette