xref: /aosp_15_r20/external/zucchini/address_translator_unittest.cc (revision a03ca8b91e029cd15055c20c78c2e087c84792e4)
1*a03ca8b9SKrzysztof Kosiński // Copyright 2017 The Chromium Authors. All rights reserved.
2*a03ca8b9SKrzysztof Kosiński // Use of this source code is governed by a BSD-style license that can be
3*a03ca8b9SKrzysztof Kosiński // found in the LICENSE file.
4*a03ca8b9SKrzysztof Kosiński 
5*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/address_translator.h"
6*a03ca8b9SKrzysztof Kosiński 
7*a03ca8b9SKrzysztof Kosiński #include <algorithm>
8*a03ca8b9SKrzysztof Kosiński #include <string>
9*a03ca8b9SKrzysztof Kosiński #include <utility>
10*a03ca8b9SKrzysztof Kosiński 
11*a03ca8b9SKrzysztof Kosiński #include "base/format_macros.h"
12*a03ca8b9SKrzysztof Kosiński #include "base/strings/stringprintf.h"
13*a03ca8b9SKrzysztof Kosiński #include "testing/gtest/include/gtest/gtest.h"
14*a03ca8b9SKrzysztof Kosiński 
15*a03ca8b9SKrzysztof Kosiński namespace zucchini {
16*a03ca8b9SKrzysztof Kosiński 
17*a03ca8b9SKrzysztof Kosiński namespace {
18*a03ca8b9SKrzysztof Kosiński 
19*a03ca8b9SKrzysztof Kosiński // Test case structs. The convention of EXPECT() specifies "expectd" value
20*a03ca8b9SKrzysztof Kosiński // before ""actual". However, AddressTranslator interfaces explicitly state "X
21*a03ca8b9SKrzysztof Kosiński // to Y". So it is clearer in test cases to specify "input" before "expect".
22*a03ca8b9SKrzysztof Kosiński struct OffsetToRvaTestCase {
23*a03ca8b9SKrzysztof Kosiński   offset_t input;
24*a03ca8b9SKrzysztof Kosiński   rva_t expect;
25*a03ca8b9SKrzysztof Kosiński };
26*a03ca8b9SKrzysztof Kosiński 
27*a03ca8b9SKrzysztof Kosiński struct RvaToOffsetTestCase {
28*a03ca8b9SKrzysztof Kosiński   rva_t input;
29*a03ca8b9SKrzysztof Kosiński   offset_t expect;
30*a03ca8b9SKrzysztof Kosiński };
31*a03ca8b9SKrzysztof Kosiński 
32*a03ca8b9SKrzysztof Kosiński class TestAddressTranslator : public AddressTranslator {
33*a03ca8b9SKrzysztof Kosiński  public:
34*a03ca8b9SKrzysztof Kosiński   using AddressTranslator::AddressTranslator;
35*a03ca8b9SKrzysztof Kosiński 
36*a03ca8b9SKrzysztof Kosiński   // Initialize() alternative that parses a visual representation of offset and
37*a03ca8b9SKrzysztof Kosiński   // RVA ranges. Illustrative example ("special" means '.' or '!'):
38*a03ca8b9SKrzysztof Kosiński   // "..AAA...|....aaaa" => "..AAA..." for offsets, and "....aaaa" for RVAs:
39*a03ca8b9SKrzysztof Kosiński   // - "..AAA...": First non-period character is at 2, so |offset_begin| = 2.
40*a03ca8b9SKrzysztof Kosiński   // - "..AAA...": There are 3 non-special characters, so |offset_size| = +3.
41*a03ca8b9SKrzysztof Kosiński   // - "....aaaa": First non-period character is at 4, so |rva_begin| = 4.
42*a03ca8b9SKrzysztof Kosiński   // - "....aaaa": There are 4 non-special characters, so |rva_size| = +4.
43*a03ca8b9SKrzysztof Kosiński   // For the special case of length-0 range, '!' can be used. For example,
44*a03ca8b9SKrzysztof Kosiński   // "...!...." specifies |begin| = 3 and |size| = +0.
InitializeWithStrings(const std::vector<std::string> & specs)45*a03ca8b9SKrzysztof Kosiński   AddressTranslator::Status InitializeWithStrings(
46*a03ca8b9SKrzysztof Kosiński       const std::vector<std::string>& specs) {
47*a03ca8b9SKrzysztof Kosiński     std::vector<Unit> units;
48*a03ca8b9SKrzysztof Kosiński     units.reserve(specs.size());
49*a03ca8b9SKrzysztof Kosiński     for (const std::string& s : specs) {
50*a03ca8b9SKrzysztof Kosiński       size_t sep = s.find('|');
51*a03ca8b9SKrzysztof Kosiński       CHECK_NE(sep, std::string::npos);
52*a03ca8b9SKrzysztof Kosiński       std::string s1 = s.substr(0, sep);
53*a03ca8b9SKrzysztof Kosiński       std::string s2 = s.substr(sep + 1);
54*a03ca8b9SKrzysztof Kosiński 
55*a03ca8b9SKrzysztof Kosiński       auto first_non_blank = [](const std::string& t) {
56*a03ca8b9SKrzysztof Kosiński         auto is_blank = [](char ch) { return ch == '.'; };
57*a03ca8b9SKrzysztof Kosiński         return std::find_if_not(t.begin(), t.end(), is_blank) - t.begin();
58*a03ca8b9SKrzysztof Kosiński       };
59*a03ca8b9SKrzysztof Kosiński       auto count_non_special = [](const std::string& t) {
60*a03ca8b9SKrzysztof Kosiński         auto is_special = [](char ch) { return ch == '.' || ch == '!'; };
61*a03ca8b9SKrzysztof Kosiński         return t.size() - std::count_if(t.begin(), t.end(), is_special);
62*a03ca8b9SKrzysztof Kosiński       };
63*a03ca8b9SKrzysztof Kosiński       units.push_back({static_cast<offset_t>(first_non_blank(s1)),
64*a03ca8b9SKrzysztof Kosiński                        static_cast<offset_t>(count_non_special(s1)),
65*a03ca8b9SKrzysztof Kosiński                        static_cast<rva_t>(first_non_blank(s2)),
66*a03ca8b9SKrzysztof Kosiński                        static_cast<rva_t>(count_non_special(s2))});
67*a03ca8b9SKrzysztof Kosiński     }
68*a03ca8b9SKrzysztof Kosiński     return Initialize(std::move(units));
69*a03ca8b9SKrzysztof Kosiński   }
70*a03ca8b9SKrzysztof Kosiński };
71*a03ca8b9SKrzysztof Kosiński 
72*a03ca8b9SKrzysztof Kosiński // Simple test: Initialize TestAddressTranslator using |specs|, and match
73*a03ca8b9SKrzysztof Kosiński // |expected| results re. success or failure.
SimpleTest(const std::vector<std::string> & specs,AddressTranslator::Status expected,const std::string & case_name)74*a03ca8b9SKrzysztof Kosiński void SimpleTest(const std::vector<std::string>& specs,
75*a03ca8b9SKrzysztof Kosiński                 AddressTranslator::Status expected,
76*a03ca8b9SKrzysztof Kosiński                 const std::string& case_name) {
77*a03ca8b9SKrzysztof Kosiński   TestAddressTranslator translator;
78*a03ca8b9SKrzysztof Kosiński   auto result = translator.InitializeWithStrings(specs);
79*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(expected, result) << case_name;
80*a03ca8b9SKrzysztof Kosiński }
81*a03ca8b9SKrzysztof Kosiński 
82*a03ca8b9SKrzysztof Kosiński // Test AddressTranslator::Initialize's Unit overlap and error checks over
83*a03ca8b9SKrzysztof Kosiński // multiple test cases, each case consists of a fixed unit (specified as
84*a03ca8b9SKrzysztof Kosiński // string), and a variable string taken from an list.
85*a03ca8b9SKrzysztof Kosiński class TwoUnitOverlapTester {
86*a03ca8b9SKrzysztof Kosiński  public:
87*a03ca8b9SKrzysztof Kosiński   struct TestCase {
88*a03ca8b9SKrzysztof Kosiński     std::string unit_str;
89*a03ca8b9SKrzysztof Kosiński     AddressTranslator::Status expected;
90*a03ca8b9SKrzysztof Kosiński   };
91*a03ca8b9SKrzysztof Kosiński 
RunTest(const std::string & unit_str1,const std::vector<TestCase> & test_cases)92*a03ca8b9SKrzysztof Kosiński   static void RunTest(const std::string& unit_str1,
93*a03ca8b9SKrzysztof Kosiński                       const std::vector<TestCase>& test_cases) {
94*a03ca8b9SKrzysztof Kosiński     for (size_t i = 0; i < test_cases.size(); ++i) {
95*a03ca8b9SKrzysztof Kosiński       const auto& test_case = test_cases[i];
96*a03ca8b9SKrzysztof Kosiński       const std::string& unit_str2 = test_case.unit_str;
97*a03ca8b9SKrzysztof Kosiński       const std::string str =
98*a03ca8b9SKrzysztof Kosiński           base::StringPrintf("Case #%" PRIuS ": %s", i, unit_str2.c_str());
99*a03ca8b9SKrzysztof Kosiński       SimpleTest({unit_str1, unit_str2}, test_case.expected, str);
100*a03ca8b9SKrzysztof Kosiński       // Switch order. Expect same results.
101*a03ca8b9SKrzysztof Kosiński       SimpleTest({unit_str2, unit_str1}, test_case.expected, str);
102*a03ca8b9SKrzysztof Kosiński     }
103*a03ca8b9SKrzysztof Kosiński   }
104*a03ca8b9SKrzysztof Kosiński };
105*a03ca8b9SKrzysztof Kosiński 
106*a03ca8b9SKrzysztof Kosiński }  // namespace
107*a03ca8b9SKrzysztof Kosiński 
TEST(AddressTranslatorTest,Empty)108*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, Empty) {
109*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
110*a03ca8b9SKrzysztof Kosiński   TestAddressTranslator translator;
111*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(AT::kSuccess,
112*a03ca8b9SKrzysztof Kosiński             translator.Initialize(std::vector<AddressTranslator::Unit>()));
113*a03ca8b9SKrzysztof Kosiński   offset_t fake_offset_begin = translator.fake_offset_begin();
114*a03ca8b9SKrzysztof Kosiński 
115*a03ca8b9SKrzysztof Kosiński   // Optimized versions.
116*a03ca8b9SKrzysztof Kosiński   AddressTranslator::OffsetToRvaCache offset_to_rva(translator);
117*a03ca8b9SKrzysztof Kosiński   AddressTranslator::RvaToOffsetCache rva_to_offset(translator);
118*a03ca8b9SKrzysztof Kosiński 
119*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, translator.OffsetToRva(0U));
120*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, translator.OffsetToRva(100U));
121*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, offset_to_rva.Convert(0U));
122*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, offset_to_rva.Convert(100U));
123*a03ca8b9SKrzysztof Kosiński 
124*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidOffset, translator.RvaToOffset(0U));
125*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidOffset, translator.RvaToOffset(100U));
126*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidOffset, rva_to_offset.Convert(0U));
127*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidOffset, rva_to_offset.Convert(100U));
128*a03ca8b9SKrzysztof Kosiński 
129*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, translator.OffsetToRva(fake_offset_begin));
130*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, offset_to_rva.Convert(fake_offset_begin));
131*a03ca8b9SKrzysztof Kosiński }
132*a03ca8b9SKrzysztof Kosiński 
TEST(AddressTranslatorTest,Single)133*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, Single) {
134*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
135*a03ca8b9SKrzysztof Kosiński   TestAddressTranslator translator;
136*a03ca8b9SKrzysztof Kosiński   // Offsets to RVA: [10, 30) -> [100, 120).
137*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(AT::kSuccess, translator.Initialize({{10U, +20U, 100U, +20U}}));
138*a03ca8b9SKrzysztof Kosiński   offset_t fake_offset_begin = translator.fake_offset_begin();
139*a03ca8b9SKrzysztof Kosiński 
140*a03ca8b9SKrzysztof Kosiński   // Optimized versions.
141*a03ca8b9SKrzysztof Kosiński   AddressTranslator::OffsetToRvaCache offset_to_rva(translator);
142*a03ca8b9SKrzysztof Kosiński   AddressTranslator::RvaToOffsetCache rva_to_offset(translator);
143*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(30U, fake_offset_begin);  // Test implementation detail.
144*a03ca8b9SKrzysztof Kosiński 
145*a03ca8b9SKrzysztof Kosiński   // Offsets to RVAs.
146*a03ca8b9SKrzysztof Kosiński   OffsetToRvaTestCase test_cases1[] = {
147*a03ca8b9SKrzysztof Kosiński       {0U, kInvalidRva}, {9U, kInvalidRva}, {10U, 100U},
148*a03ca8b9SKrzysztof Kosiński       {20U, 110U},       {29U, 119U},       {30U, kInvalidRva},
149*a03ca8b9SKrzysztof Kosiński   };
150*a03ca8b9SKrzysztof Kosiński   for (auto& test_case : test_cases1) {
151*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, translator.OffsetToRva(test_case.input));
152*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, offset_to_rva.Convert(test_case.input));
153*a03ca8b9SKrzysztof Kosiński   }
154*a03ca8b9SKrzysztof Kosiński 
155*a03ca8b9SKrzysztof Kosiński   // RVAs to offsets.
156*a03ca8b9SKrzysztof Kosiński   RvaToOffsetTestCase test_cases2[] = {
157*a03ca8b9SKrzysztof Kosiński       {0U, kInvalidOffset}, {99U, kInvalidOffset}, {100U, 10U},
158*a03ca8b9SKrzysztof Kosiński       {110U, 20U},          {119U, 29U},           {120U, kInvalidOffset},
159*a03ca8b9SKrzysztof Kosiński   };
160*a03ca8b9SKrzysztof Kosiński   for (auto& test_case : test_cases2) {
161*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, translator.RvaToOffset(test_case.input));
162*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, rva_to_offset.Convert(test_case.input));
163*a03ca8b9SKrzysztof Kosiński   }
164*a03ca8b9SKrzysztof Kosiński }
165*a03ca8b9SKrzysztof Kosiński 
TEST(AddressTranslatorTest,SingleDanglingRva)166*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, SingleDanglingRva) {
167*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
168*a03ca8b9SKrzysztof Kosiński   TestAddressTranslator translator;
169*a03ca8b9SKrzysztof Kosiński   // Offsets to RVA: [10, 30) -> [100, 120 + 7), so has dangling RVAs.
170*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(AT::kSuccess,
171*a03ca8b9SKrzysztof Kosiński             translator.Initialize({{10U, +20U, 100U, +20U + 7U}}));
172*a03ca8b9SKrzysztof Kosiński   offset_t fake_offset_begin = translator.fake_offset_begin();
173*a03ca8b9SKrzysztof Kosiński 
174*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(30U, fake_offset_begin);  // Test implementation detail.
175*a03ca8b9SKrzysztof Kosiński 
176*a03ca8b9SKrzysztof Kosiński   // Optimized versions.
177*a03ca8b9SKrzysztof Kosiński   AddressTranslator::OffsetToRvaCache offset_to_rva(translator);
178*a03ca8b9SKrzysztof Kosiński   AddressTranslator::RvaToOffsetCache rva_to_offset(translator);
179*a03ca8b9SKrzysztof Kosiński 
180*a03ca8b9SKrzysztof Kosiński   // Offsets to RVAs.
181*a03ca8b9SKrzysztof Kosiński   OffsetToRvaTestCase test_cases1[] = {
182*a03ca8b9SKrzysztof Kosiński       {0U, kInvalidRva},
183*a03ca8b9SKrzysztof Kosiński       {9U, kInvalidRva},
184*a03ca8b9SKrzysztof Kosiński       {10U, 100U},
185*a03ca8b9SKrzysztof Kosiński       {20U, 110U},
186*a03ca8b9SKrzysztof Kosiński       {29U, 119U},
187*a03ca8b9SKrzysztof Kosiński       {30U, kInvalidRva},
188*a03ca8b9SKrzysztof Kosiński       // Fake offsets to dangling RVAs.
189*a03ca8b9SKrzysztof Kosiński       {fake_offset_begin + 100U, kInvalidRva},
190*a03ca8b9SKrzysztof Kosiński       {fake_offset_begin + 119U, kInvalidRva},
191*a03ca8b9SKrzysztof Kosiński       {fake_offset_begin + 120U, 120U},
192*a03ca8b9SKrzysztof Kosiński       {fake_offset_begin + 126U, 126U},
193*a03ca8b9SKrzysztof Kosiński       {fake_offset_begin + 127U, kInvalidRva},
194*a03ca8b9SKrzysztof Kosiński   };
195*a03ca8b9SKrzysztof Kosiński   for (auto& test_case : test_cases1) {
196*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, translator.OffsetToRva(test_case.input));
197*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, offset_to_rva.Convert(test_case.input));
198*a03ca8b9SKrzysztof Kosiński   }
199*a03ca8b9SKrzysztof Kosiński 
200*a03ca8b9SKrzysztof Kosiński   // RVAs to offsets.
201*a03ca8b9SKrzysztof Kosiński   RvaToOffsetTestCase test_cases2[] = {
202*a03ca8b9SKrzysztof Kosiński       {0U, kInvalidOffset},
203*a03ca8b9SKrzysztof Kosiński       {99U, kInvalidOffset},
204*a03ca8b9SKrzysztof Kosiński       {100U, 10U},
205*a03ca8b9SKrzysztof Kosiński       {110U, 20U},
206*a03ca8b9SKrzysztof Kosiński       {119U, 29U},
207*a03ca8b9SKrzysztof Kosiński       // Dangling RVAs to fake offsets.
208*a03ca8b9SKrzysztof Kosiński       {120U, fake_offset_begin + 120U},
209*a03ca8b9SKrzysztof Kosiński       {126U, fake_offset_begin + 126U},
210*a03ca8b9SKrzysztof Kosiński       {127U, kInvalidOffset},
211*a03ca8b9SKrzysztof Kosiński   };
212*a03ca8b9SKrzysztof Kosiński   for (auto& test_case : test_cases2) {
213*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, translator.RvaToOffset(test_case.input));
214*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, rva_to_offset.Convert(test_case.input));
215*a03ca8b9SKrzysztof Kosiński   }
216*a03ca8b9SKrzysztof Kosiński }
217*a03ca8b9SKrzysztof Kosiński 
TEST(AddressTranslatorTest,BasicUsage)218*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, BasicUsage) {
219*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
220*a03ca8b9SKrzysztof Kosiński   TestAddressTranslator translator;
221*a03ca8b9SKrzysztof Kosiński   // Offsets covered: [10, 30), [40, 70), [70, 110).
222*a03ca8b9SKrzysztof Kosiński   // Map to RVAs: [200, 220 + 5), [300, 330), [100, 140), so has dangling RVAs.
223*a03ca8b9SKrzysztof Kosiński   auto result = translator.Initialize({
224*a03ca8b9SKrzysztof Kosiński       {10U, +20U, 200U, +20U + 5U},  // Has dangling RVAs.
225*a03ca8b9SKrzysztof Kosiński       {40U, +30U, 300U, +20U},       // Extra offset truncated and ignored.
226*a03ca8b9SKrzysztof Kosiński       {50U, +20U, 310U, +20U},       // Overlap with previous: Merged.
227*a03ca8b9SKrzysztof Kosiński       {70U, +40U, 100U, +20U},  // Tangent with previous but inconsistent; extra
228*a03ca8b9SKrzysztof Kosiński                                 // offset truncated and ignored.
229*a03ca8b9SKrzysztof Kosiński       {90U, +20U, 120U, +20U},  // Tangent with previous and consistent: Merged.
230*a03ca8b9SKrzysztof Kosiński   });
231*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(AT::kSuccess, result);
232*a03ca8b9SKrzysztof Kosiński   offset_t fake_offset_begin = translator.fake_offset_begin();
233*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(110U, fake_offset_begin);  // Test implementation detail.
234*a03ca8b9SKrzysztof Kosiński 
235*a03ca8b9SKrzysztof Kosiński   // Optimized versions.
236*a03ca8b9SKrzysztof Kosiński   AddressTranslator::OffsetToRvaCache offset_to_rva(translator);
237*a03ca8b9SKrzysztof Kosiński   AddressTranslator::RvaToOffsetCache rva_to_offset(translator);
238*a03ca8b9SKrzysztof Kosiński 
239*a03ca8b9SKrzysztof Kosiński   // Offsets to RVAs.
240*a03ca8b9SKrzysztof Kosiński   OffsetToRvaTestCase test_cases1[] = {
241*a03ca8b9SKrzysztof Kosiński       {0U, kInvalidRva},
242*a03ca8b9SKrzysztof Kosiński       {9U, kInvalidRva},
243*a03ca8b9SKrzysztof Kosiński       {10U, 200U},
244*a03ca8b9SKrzysztof Kosiński       {20U, 210U},
245*a03ca8b9SKrzysztof Kosiński       {29U, 219U},
246*a03ca8b9SKrzysztof Kosiński       {30U, kInvalidRva},
247*a03ca8b9SKrzysztof Kosiński       {39U, kInvalidRva},
248*a03ca8b9SKrzysztof Kosiński       {40U, 300U},
249*a03ca8b9SKrzysztof Kosiński       {55U, 315U},
250*a03ca8b9SKrzysztof Kosiński       {69U, 329U},
251*a03ca8b9SKrzysztof Kosiński       {70U, 100U},
252*a03ca8b9SKrzysztof Kosiński       {90U, 120U},
253*a03ca8b9SKrzysztof Kosiński       {109U, 139U},
254*a03ca8b9SKrzysztof Kosiński       {110U, kInvalidRva},
255*a03ca8b9SKrzysztof Kosiński       // Fake offsets to dangling RVAs.
256*a03ca8b9SKrzysztof Kosiński       {fake_offset_begin + 220U, 220U},
257*a03ca8b9SKrzysztof Kosiński       {fake_offset_begin + 224U, 224U},
258*a03ca8b9SKrzysztof Kosiński       {fake_offset_begin + 225U, kInvalidRva},
259*a03ca8b9SKrzysztof Kosiński   };
260*a03ca8b9SKrzysztof Kosiński   for (auto& test_case : test_cases1) {
261*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, translator.OffsetToRva(test_case.input));
262*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, offset_to_rva.Convert(test_case.input));
263*a03ca8b9SKrzysztof Kosiński   }
264*a03ca8b9SKrzysztof Kosiński 
265*a03ca8b9SKrzysztof Kosiński   // RVAs to offsets.
266*a03ca8b9SKrzysztof Kosiński   RvaToOffsetTestCase test_cases2[] = {
267*a03ca8b9SKrzysztof Kosiński       {0U, kInvalidOffset},
268*a03ca8b9SKrzysztof Kosiński       {99U, kInvalidOffset},
269*a03ca8b9SKrzysztof Kosiński       {100U, 70U},
270*a03ca8b9SKrzysztof Kosiński       {120U, 90U},
271*a03ca8b9SKrzysztof Kosiński       {139U, 109U},
272*a03ca8b9SKrzysztof Kosiński       {140U, kInvalidOffset},
273*a03ca8b9SKrzysztof Kosiński       {199U, kInvalidOffset},
274*a03ca8b9SKrzysztof Kosiński       {200U, 10U},
275*a03ca8b9SKrzysztof Kosiński       {210U, 20U},
276*a03ca8b9SKrzysztof Kosiński       {219U, 29U},
277*a03ca8b9SKrzysztof Kosiński       {225U, kInvalidOffset},
278*a03ca8b9SKrzysztof Kosiński       {299U, kInvalidOffset},
279*a03ca8b9SKrzysztof Kosiński       {300U, 40U},
280*a03ca8b9SKrzysztof Kosiński       {315U, 55U},
281*a03ca8b9SKrzysztof Kosiński       {329U, 69U},
282*a03ca8b9SKrzysztof Kosiński       {330U, kInvalidOffset},
283*a03ca8b9SKrzysztof Kosiński       // Dangling RVAs to fake offsets.
284*a03ca8b9SKrzysztof Kosiński       {220U, fake_offset_begin + 220U},
285*a03ca8b9SKrzysztof Kosiński       {224U, fake_offset_begin + 224U},
286*a03ca8b9SKrzysztof Kosiński       {225U, kInvalidOffset},
287*a03ca8b9SKrzysztof Kosiński   };
288*a03ca8b9SKrzysztof Kosiński   for (auto& test_case : test_cases2) {
289*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, translator.RvaToOffset(test_case.input));
290*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(test_case.expect, rva_to_offset.Convert(test_case.input));
291*a03ca8b9SKrzysztof Kosiński   }
292*a03ca8b9SKrzysztof Kosiński }
293*a03ca8b9SKrzysztof Kosiński 
TEST(AddressTranslatorTest,Overflow)294*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, Overflow) {
295*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
296*a03ca8b9SKrzysztof Kosiński   // Test assumes that offset_t and rva_t to be 32-bit.
297*a03ca8b9SKrzysztof Kosiński   static_assert(sizeof(offset_t) == 4 && sizeof(rva_t) == 4,
298*a03ca8b9SKrzysztof Kosiński                 "Needs to update test.");
299*a03ca8b9SKrzysztof Kosiński   {
300*a03ca8b9SKrzysztof Kosiński     AddressTranslator translator1;
301*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(AT::kErrorOverflow,
302*a03ca8b9SKrzysztof Kosiński               translator1.Initialize({{0, +0xC0000000U, 0, +0xC0000000U}}));
303*a03ca8b9SKrzysztof Kosiński   }
304*a03ca8b9SKrzysztof Kosiński   {
305*a03ca8b9SKrzysztof Kosiński     AddressTranslator translator2;
306*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(AT::kErrorOverflow,
307*a03ca8b9SKrzysztof Kosiński               translator2.Initialize({{0, +0, 0, +0xC0000000U}}));
308*a03ca8b9SKrzysztof Kosiński   }
309*a03ca8b9SKrzysztof Kosiński   {
310*a03ca8b9SKrzysztof Kosiński     // Units are okay, owing to but limitations of the heuristic to convert
311*a03ca8b9SKrzysztof Kosiński     // dangling RVA to fake offset, AddressTranslator::Initialize() fails.
312*a03ca8b9SKrzysztof Kosiński     AddressTranslator translator3;
313*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(AT::kErrorFakeOffsetBeginTooLarge,
314*a03ca8b9SKrzysztof Kosiński               translator3.Initialize(
315*a03ca8b9SKrzysztof Kosiński                   {{32, +0, 32, +0x50000000U}, {0x50000000U, +16, 0, +16}}));
316*a03ca8b9SKrzysztof Kosiński   }
317*a03ca8b9SKrzysztof Kosiński }
318*a03ca8b9SKrzysztof Kosiński 
319*a03ca8b9SKrzysztof Kosiński // Sanity test for TestAddressTranslator::InitializeWithStrings();
TEST(AddressTranslatorTest,AddUnitAsString)320*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, AddUnitAsString) {
321*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
322*a03ca8b9SKrzysztof Kosiński   {
323*a03ca8b9SKrzysztof Kosiński     TestAddressTranslator translator1;
324*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(AT::kSuccess, translator1.InitializeWithStrings({"..A..|.aaa."}));
325*a03ca8b9SKrzysztof Kosiński     AddressTranslator::Unit unit1 = translator1.units_sorted_by_offset()[0];
326*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(2U, unit1.offset_begin);
327*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(+1U, unit1.offset_size);
328*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(1U, unit1.rva_begin);
329*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(+3U, unit1.rva_size);
330*a03ca8b9SKrzysztof Kosiński   }
331*a03ca8b9SKrzysztof Kosiński   {
332*a03ca8b9SKrzysztof Kosiński     TestAddressTranslator translator2;
333*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(AT::kSuccess,
334*a03ca8b9SKrzysztof Kosiński               translator2.InitializeWithStrings({".....!...|.bbbbbb..."}));
335*a03ca8b9SKrzysztof Kosiński     AddressTranslator::Unit unit2 = translator2.units_sorted_by_offset()[0];
336*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(5U, unit2.offset_begin);
337*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(+0U, unit2.offset_size);
338*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(1U, unit2.rva_begin);
339*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(+6U, unit2.rva_size);
340*a03ca8b9SKrzysztof Kosiński   }
341*a03ca8b9SKrzysztof Kosiński }
342*a03ca8b9SKrzysztof Kosiński 
343*a03ca8b9SKrzysztof Kosiński // AddressTranslator::Initialize() lists Unit merging examples in comments. The
344*a03ca8b9SKrzysztof Kosiński // format is different from that used by InitializeWithStrings(), but adapting
345*a03ca8b9SKrzysztof Kosiński // them is easy, so we may as well do so.
TEST(AddressTranslatorTest,OverlapFromComment)346*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, OverlapFromComment) {
347*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
348*a03ca8b9SKrzysztof Kosiński   constexpr auto OK = AT::kSuccess;
349*a03ca8b9SKrzysztof Kosiński   struct {
350*a03ca8b9SKrzysztof Kosiński     const char* rva_str;  // RVA comes first in this case.
351*a03ca8b9SKrzysztof Kosiński     const char* offset_str;
352*a03ca8b9SKrzysztof Kosiński     AT::Status expected;
353*a03ca8b9SKrzysztof Kosiński   } test_cases[] = {
354*a03ca8b9SKrzysztof Kosiński       {"..ssssffff..", "..SSSSFFFF..", OK},
355*a03ca8b9SKrzysztof Kosiński       {"..ssssffff..", "..SSSS..FFFF..", OK},
356*a03ca8b9SKrzysztof Kosiński       {"..ssssffff..", "..FFFF..SSSS..", OK},
357*a03ca8b9SKrzysztof Kosiński       {"..ssssffff..", "..SSOOFF..", AT::kErrorBadOverlap},
358*a03ca8b9SKrzysztof Kosiński       {"..sssooofff..", "..SSSOOOFFF..", OK},
359*a03ca8b9SKrzysztof Kosiński       {"..sssooofff..", "..SSSSSOFFFFF..", AT::kErrorBadOverlap},
360*a03ca8b9SKrzysztof Kosiński       {"..sssooofff..", "..FFOOOOSS..", AT::kErrorBadOverlap},
361*a03ca8b9SKrzysztof Kosiński       {"..sssooofff..", "..SSSOOOF..", OK},
362*a03ca8b9SKrzysztof Kosiński       {"..sssooofff..", "..SSSOOOF..", OK},
363*a03ca8b9SKrzysztof Kosiński       {"..sssooosss..", "..SSSOOOS..", OK},
364*a03ca8b9SKrzysztof Kosiński       {"..sssooofff..", "..SSSOO..", OK},
365*a03ca8b9SKrzysztof Kosiński       {"..sssooofff..", "..SSSOFFF..", AT::kErrorBadOverlapDanglingRva},
366*a03ca8b9SKrzysztof Kosiński       {"..sssooosss..", "..SSSOOSSSS..", AT::kErrorBadOverlapDanglingRva},
367*a03ca8b9SKrzysztof Kosiński       {"..oooooo..", "..OOO..", OK},
368*a03ca8b9SKrzysztof Kosiński   };
369*a03ca8b9SKrzysztof Kosiński 
370*a03ca8b9SKrzysztof Kosiński   auto to_period = [](std::string s, char ch) {  // |s| passed by value.
371*a03ca8b9SKrzysztof Kosiński     std::replace(s.begin(), s.end(), ch, '.');
372*a03ca8b9SKrzysztof Kosiński     return s;
373*a03ca8b9SKrzysztof Kosiński   };
374*a03ca8b9SKrzysztof Kosiński 
375*a03ca8b9SKrzysztof Kosiński   size_t idx = 0;
376*a03ca8b9SKrzysztof Kosiński   for (const auto& test_case : test_cases) {
377*a03ca8b9SKrzysztof Kosiński     std::string base_str =
378*a03ca8b9SKrzysztof Kosiński         std::string(test_case.offset_str) + "|" + test_case.rva_str;
379*a03ca8b9SKrzysztof Kosiński     std::string unit_str1 = to_period(to_period(base_str, 'S'), 's');
380*a03ca8b9SKrzysztof Kosiński     std::string unit_str2 = to_period(to_period(base_str, 'F'), 'f');
381*a03ca8b9SKrzysztof Kosiński     SimpleTest({unit_str1, unit_str2}, test_case.expected,
382*a03ca8b9SKrzysztof Kosiński                base::StringPrintf("Case #%" PRIuS, idx));
383*a03ca8b9SKrzysztof Kosiński     ++idx;
384*a03ca8b9SKrzysztof Kosiński   }
385*a03ca8b9SKrzysztof Kosiński }
386*a03ca8b9SKrzysztof Kosiński 
TEST(AddressTranslatorTest,Overlap)387*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, Overlap) {
388*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
389*a03ca8b9SKrzysztof Kosiński   constexpr auto OK = AT::kSuccess;
390*a03ca8b9SKrzysztof Kosiński   constexpr const char* unit_str1 = "....AAA.......|.....aaa......";
391*a03ca8b9SKrzysztof Kosiński 
392*a03ca8b9SKrzysztof Kosiński   std::vector<TwoUnitOverlapTester::TestCase> test_cases = {
393*a03ca8b9SKrzysztof Kosiński       //....AAA.......|.....aaa......   The first Unit. NOLINT
394*a03ca8b9SKrzysztof Kosiński       {"....BBB.......|.....bbb......", OK},
395*a03ca8b9SKrzysztof Kosiński       {"..BBB.........|...bbb........", OK},
396*a03ca8b9SKrzysztof Kosiński       {"......BBB.....|.......bbb....", OK},
397*a03ca8b9SKrzysztof Kosiński       {"..BBBBBBBBB...|...bbb........", OK},  // Extra offset get truncated.
398*a03ca8b9SKrzysztof Kosiński       {"......BBBBBBBB|.......bbb....", OK},
399*a03ca8b9SKrzysztof Kosiński       {"....BBB.......|.......bbb....", AT::kErrorBadOverlap},
400*a03ca8b9SKrzysztof Kosiński       {"..BBB.........|.......bbb....", AT::kErrorBadOverlap},
401*a03ca8b9SKrzysztof Kosiński       {".......BBB....|.......bbb....", AT::kErrorBadOverlap},
402*a03ca8b9SKrzysztof Kosiński       //....AAA.......|.....aaa......   The first Unit. NOLINT
403*a03ca8b9SKrzysztof Kosiński       {"....BBB.......|..........bbb.", AT::kErrorBadOverlap},
404*a03ca8b9SKrzysztof Kosiński       {"..........BBB.|.......bbb....", AT::kErrorBadOverlap},
405*a03ca8b9SKrzysztof Kosiński       {"......BBB.....|.....bbb......", AT::kErrorBadOverlap},
406*a03ca8b9SKrzysztof Kosiński       {"......BBB.....|..bbb.........", AT::kErrorBadOverlap},
407*a03ca8b9SKrzysztof Kosiński       {"......BBB.....|bbb...........", AT::kErrorBadOverlap},
408*a03ca8b9SKrzysztof Kosiński       {"BBB...........|bbb...........", OK},  // Disjoint.
409*a03ca8b9SKrzysztof Kosiński       {"........BBB...|.........bbb..", OK},  // Disjoint.
410*a03ca8b9SKrzysztof Kosiński       {"BBB...........|..........bbb.", OK},  // Disjoint, offset elsewhere.
411*a03ca8b9SKrzysztof Kosiński       //....AAA.......|.....aaa......   The first Unit. NOLINT
412*a03ca8b9SKrzysztof Kosiński       {".BBB..........|..bbb.........", OK},  // Tangent.
413*a03ca8b9SKrzysztof Kosiński       {".......BBB....|........bbb...", OK},  // Tangent.
414*a03ca8b9SKrzysztof Kosiński       {".BBB..........|........bbb...", OK},  // Tangent, offset elsewhere.
415*a03ca8b9SKrzysztof Kosiński       {"BBBBBB........|bbb...........", OK},  // Repeat, with extra offsets.
416*a03ca8b9SKrzysztof Kosiński       {"........BBBB..|.........bbb..", OK},
417*a03ca8b9SKrzysztof Kosiński       {"BBBBBB........|..........bbb.", OK},
418*a03ca8b9SKrzysztof Kosiński       {".BBBBBB.......|..bbb.........", OK},
419*a03ca8b9SKrzysztof Kosiński       {".......BBBBB..|........bbb...", OK},
420*a03ca8b9SKrzysztof Kosiński       //....AAA.......|.....aaa......   The first Unit. NOLINT
421*a03ca8b9SKrzysztof Kosiński       {".BBB..........|........bbb...", OK},  // Tangent, offset elsewhere.
422*a03ca8b9SKrzysztof Kosiński       {"..BBB.........|........bbb...", AT::kErrorBadOverlap},
423*a03ca8b9SKrzysztof Kosiński       {"...BB.........|....bb........", OK},
424*a03ca8b9SKrzysztof Kosiński       {"....BB........|.....bb.......", OK},
425*a03ca8b9SKrzysztof Kosiński       {".......BB.....|........bb....", OK},
426*a03ca8b9SKrzysztof Kosiński       {"...BBBBBB.....|....bbbbbb....", OK},
427*a03ca8b9SKrzysztof Kosiński       {"..BBBBBB......|...bbbbbb.....", OK},
428*a03ca8b9SKrzysztof Kosiński       {"......BBBBBB..|.......bbbbbb.", OK},
429*a03ca8b9SKrzysztof Kosiński       //....AAA.......|.....aaa......   The first Unit. NOLINT
430*a03ca8b9SKrzysztof Kosiński       {"BBBBBBBBBBBBBB|bbbbbbbbbbbbbb", AT::kErrorBadOverlap},
431*a03ca8b9SKrzysztof Kosiński       {"B.............|b.............", OK},
432*a03ca8b9SKrzysztof Kosiński       {"B.............|.............b", OK},
433*a03ca8b9SKrzysztof Kosiński       {"....B.........|.....b........", OK},
434*a03ca8b9SKrzysztof Kosiński       {"....B.........|......b.......", AT::kErrorBadOverlap},
435*a03ca8b9SKrzysztof Kosiński       {"....B.........|......b.......", AT::kErrorBadOverlap},
436*a03ca8b9SKrzysztof Kosiński       {"....BBB.......|.....bb.......", OK},
437*a03ca8b9SKrzysztof Kosiński       {"....BBBB......|.....bbb......", OK},
438*a03ca8b9SKrzysztof Kosiński       //....AAA.......|.....aaa......   The first Unit. NOLINT
439*a03ca8b9SKrzysztof Kosiński       {".........BBBBB|.b............", OK},
440*a03ca8b9SKrzysztof Kosiński       {"....AAA.......|.....!........", OK},
441*a03ca8b9SKrzysztof Kosiński       {"....!.........|.....!........", OK},  // Empty units gets deleted early.
442*a03ca8b9SKrzysztof Kosiński       {"....!.........|..........!...", OK},  // Forgiving!
443*a03ca8b9SKrzysztof Kosiński   };
444*a03ca8b9SKrzysztof Kosiński 
445*a03ca8b9SKrzysztof Kosiński   TwoUnitOverlapTester::RunTest(unit_str1, test_cases);
446*a03ca8b9SKrzysztof Kosiński }
447*a03ca8b9SKrzysztof Kosiński 
TEST(AddressTranslatorTest,OverlapOffsetMultiple)448*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, OverlapOffsetMultiple) {
449*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
450*a03ca8b9SKrzysztof Kosiński   // Simple case. Note that RVA ranges don't get merged.
451*a03ca8b9SKrzysztof Kosiński   SimpleTest({"A..|a....",  //
452*a03ca8b9SKrzysztof Kosiński               ".A.|..a..",  //
453*a03ca8b9SKrzysztof Kosiński               "..A|....a"},
454*a03ca8b9SKrzysztof Kosiński              AT::kSuccess, "Case #0");
455*a03ca8b9SKrzysztof Kosiński 
456*a03ca8b9SKrzysztof Kosiński   // Offset range 1 overlaps 2 and 3, but truncation takes place to trim down
457*a03ca8b9SKrzysztof Kosiński   // offset ranges, so still successful.
458*a03ca8b9SKrzysztof Kosiński   SimpleTest({"..A|a....",  //
459*a03ca8b9SKrzysztof Kosiński               ".AA|..a..",  //
460*a03ca8b9SKrzysztof Kosiński               "AAA|....a"},
461*a03ca8b9SKrzysztof Kosiński              AT::kSuccess, "Case #1");
462*a03ca8b9SKrzysztof Kosiński 
463*a03ca8b9SKrzysztof Kosiński   // Offset range 2 and 3 overlap, so fail.
464*a03ca8b9SKrzysztof Kosiński   SimpleTest({"A..|a....",  //
465*a03ca8b9SKrzysztof Kosiński               ".A.|..a..",  //
466*a03ca8b9SKrzysztof Kosiński               ".A.|....a"},
467*a03ca8b9SKrzysztof Kosiński              AT::kErrorBadOverlap, "Case #2");
468*a03ca8b9SKrzysztof Kosiński }
469*a03ca8b9SKrzysztof Kosiński 
TEST(AddressTranslatorTest,OverlapDangling)470*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, OverlapDangling) {
471*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
472*a03ca8b9SKrzysztof Kosiński   constexpr auto OK = AT::kSuccess;
473*a03ca8b9SKrzysztof Kosiński   // First Unit has dangling offsets at
474*a03ca8b9SKrzysztof Kosiński   constexpr const char* unit_str1 = "....AAA.......|.....aaaaaa...";
475*a03ca8b9SKrzysztof Kosiński 
476*a03ca8b9SKrzysztof Kosiński   std::vector<TwoUnitOverlapTester::TestCase> test_cases = {
477*a03ca8b9SKrzysztof Kosiński       //....AAA.......|.....aaaaaa...   The first Unit. NOLINT
478*a03ca8b9SKrzysztof Kosiński       {"....BBB.......|.....bbbbbb...", OK},
479*a03ca8b9SKrzysztof Kosiński       {"....BBB.......|.....bbbbb....", OK},
480*a03ca8b9SKrzysztof Kosiński       {"....BBB.......|.....bbbb.....", OK},
481*a03ca8b9SKrzysztof Kosiński       {"....BBB.......|.....bbb......", OK},
482*a03ca8b9SKrzysztof Kosiński       {".....BBB......|......bbb.....", AT::kErrorBadOverlapDanglingRva},
483*a03ca8b9SKrzysztof Kosiński       {".....BB.......|......bbb.....", OK},
484*a03ca8b9SKrzysztof Kosiński       {"....BBB.......|.....bbbbbbbb.", OK},
485*a03ca8b9SKrzysztof Kosiński       {"..BBBBB.......|...bbbbbbbb...", OK},
486*a03ca8b9SKrzysztof Kosiński       //....AAA.......|.....aaaaaa...   The first Unit. NOLINT
487*a03ca8b9SKrzysztof Kosiński       {"......!.......|.bbb..........", AT::kErrorBadOverlap},
488*a03ca8b9SKrzysztof Kosiński       {"..BBBBB.......|...bbbbb......", OK},
489*a03ca8b9SKrzysztof Kosiński       {".......BBB....|.bbb..........", OK},  // Just tangent: Can go elsewhere.
490*a03ca8b9SKrzysztof Kosiński       {".......BBB....|.bbbb.........", OK},  // Can be another dangling RVA.
491*a03ca8b9SKrzysztof Kosiński       {".......!......|.bbbb.........", OK},  // Same with empty.
492*a03ca8b9SKrzysztof Kosiński       {"......!.......|.......!......", OK},  // Okay, but gets deleted.
493*a03ca8b9SKrzysztof Kosiński       {"......!.......|.......b......", AT::kErrorBadOverlapDanglingRva},
494*a03ca8b9SKrzysztof Kosiński       {"......B.......|.......b......", OK},
495*a03ca8b9SKrzysztof Kosiński       //....AAA.......|.....aaaaaa...   The first Unit. NOLINT
496*a03ca8b9SKrzysztof Kosiński       {"......BBBB....|.......bbbb...", AT::kErrorBadOverlapDanglingRva},
497*a03ca8b9SKrzysztof Kosiński       {"......BB......|.......bb.....", AT::kErrorBadOverlapDanglingRva},
498*a03ca8b9SKrzysztof Kosiński       {"......BB......|bb............", AT::kErrorBadOverlap},
499*a03ca8b9SKrzysztof Kosiński   };
500*a03ca8b9SKrzysztof Kosiński 
501*a03ca8b9SKrzysztof Kosiński   TwoUnitOverlapTester::RunTest(unit_str1, test_cases);
502*a03ca8b9SKrzysztof Kosiński }
503*a03ca8b9SKrzysztof Kosiński 
504*a03ca8b9SKrzysztof Kosiński // Tests implementation since algorithm is tricky.
TEST(AddressTranslatorTest,Merge)505*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, Merge) {
506*a03ca8b9SKrzysztof Kosiński   using AT = AddressTranslator;
507*a03ca8b9SKrzysztof Kosiński   // Merge a bunch of overlapping Units into one big Unit.
508*a03ca8b9SKrzysztof Kosiński   std::vector<std::string> test_case1 = {
509*a03ca8b9SKrzysztof Kosiński       "AAA.......|.aaa......",  // Comment to prevent wrap by formatter.
510*a03ca8b9SKrzysztof Kosiński       "AA........|.aa.......",  //
511*a03ca8b9SKrzysztof Kosiński       "..AAA.....|...aaa....",  //
512*a03ca8b9SKrzysztof Kosiński       "....A.....|.....a....",  //
513*a03ca8b9SKrzysztof Kosiński       ".....AAA..|......aaa.",  //
514*a03ca8b9SKrzysztof Kosiński       "........A.|.........a",  //
515*a03ca8b9SKrzysztof Kosiński   };
516*a03ca8b9SKrzysztof Kosiński   // Try all 6! permutations.
517*a03ca8b9SKrzysztof Kosiński   std::sort(test_case1.begin(), test_case1.end());
518*a03ca8b9SKrzysztof Kosiński   do {
519*a03ca8b9SKrzysztof Kosiński     TestAddressTranslator translator1;
520*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(AT::kSuccess, translator1.InitializeWithStrings(test_case1));
521*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(9U, translator1.fake_offset_begin());
522*a03ca8b9SKrzysztof Kosiński 
523*a03ca8b9SKrzysztof Kosiński     AT::Unit expected{0U, +9U, 1U, +9U};
524*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(1U, translator1.units_sorted_by_offset().size());
525*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(expected, translator1.units_sorted_by_offset()[0]);
526*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(1U, translator1.units_sorted_by_rva().size());
527*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(expected, translator1.units_sorted_by_rva()[0]);
528*a03ca8b9SKrzysztof Kosiński   } while (std::next_permutation(test_case1.begin(), test_case1.end()));
529*a03ca8b9SKrzysztof Kosiński 
530*a03ca8b9SKrzysztof Kosiński   // Merge RVA-adjacent Units into two Units.
531*a03ca8b9SKrzysztof Kosiński   std::vector<std::string> test_case2 = {
532*a03ca8b9SKrzysztof Kosiński       ".....A..|.a......",  // First Unit.
533*a03ca8b9SKrzysztof Kosiński       "......A.|..a.....",  //
534*a03ca8b9SKrzysztof Kosiński       "A.......|...a....",  // Second Unit: RVA-adjacent to first Unit, but
535*a03ca8b9SKrzysztof Kosiński       ".A......|....a...",  // offset would become inconsistent, so a new
536*a03ca8b9SKrzysztof Kosiński       "..A.....|.....a..",  // Unit gets created.
537*a03ca8b9SKrzysztof Kosiński   };
538*a03ca8b9SKrzysztof Kosiński   // Try all 5! permutations.
539*a03ca8b9SKrzysztof Kosiński   std::sort(test_case2.begin(), test_case2.end());
540*a03ca8b9SKrzysztof Kosiński   do {
541*a03ca8b9SKrzysztof Kosiński     TestAddressTranslator translator2;
542*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(AT::kSuccess, translator2.InitializeWithStrings(test_case2));
543*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(7U, translator2.fake_offset_begin());
544*a03ca8b9SKrzysztof Kosiński 
545*a03ca8b9SKrzysztof Kosiński     AT::Unit expected1{0U, +3U, 3U, +3U};
546*a03ca8b9SKrzysztof Kosiński     AT::Unit expected2{5U, +2U, 1U, +2U};
547*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(2U, translator2.units_sorted_by_offset().size());
548*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(expected1, translator2.units_sorted_by_offset()[0]);
549*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(expected2, translator2.units_sorted_by_offset()[1]);
550*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(2U, translator2.units_sorted_by_rva().size());
551*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(expected2, translator2.units_sorted_by_rva()[0]);
552*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(expected1, translator2.units_sorted_by_rva()[1]);
553*a03ca8b9SKrzysztof Kosiński   } while (std::next_permutation(test_case2.begin(), test_case2.end()));
554*a03ca8b9SKrzysztof Kosiński }
555*a03ca8b9SKrzysztof Kosiński 
TEST(AddressTranslatorTest,RvaToOffsetCache_IsValid)556*a03ca8b9SKrzysztof Kosiński TEST(AddressTranslatorTest, RvaToOffsetCache_IsValid) {
557*a03ca8b9SKrzysztof Kosiński   AddressTranslator translator;
558*a03ca8b9SKrzysztof Kosiński   // Notice that the second section has dangling RVA.
559*a03ca8b9SKrzysztof Kosiński   ASSERT_EQ(AddressTranslator::kSuccess,
560*a03ca8b9SKrzysztof Kosiński             translator.Initialize(
561*a03ca8b9SKrzysztof Kosiński                 {{0x04, +0x28, 0x1A00, +0x28}, {0x30, +0x10, 0x3A00, +0x30}}));
562*a03ca8b9SKrzysztof Kosiński   AddressTranslator::RvaToOffsetCache rva_checker(translator);
563*a03ca8b9SKrzysztof Kosiński 
564*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(kInvalidRva));
565*a03ca8b9SKrzysztof Kosiński 
566*a03ca8b9SKrzysztof Kosiński   for (int i = 0; i < 0x28; ++i)
567*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(rva_checker.IsValid(0x1A00 + i));
568*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0x1A00 + 0x28));
569*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0x1A00 + 0x29));
570*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0x1A00 - 1));
571*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0x1A00 - 2));
572*a03ca8b9SKrzysztof Kosiński 
573*a03ca8b9SKrzysztof Kosiński   for (int i = 0; i < 0x30; ++i)
574*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(rva_checker.IsValid(0x3A00 + i));
575*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0x3A00 + 0x30));
576*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0x3A00 + 0x31));
577*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0x3A00 - 1));
578*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0x3A00 - 2));
579*a03ca8b9SKrzysztof Kosiński 
580*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0));
581*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0x10));
582*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0x7FFFFFFFU));
583*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(rva_checker.IsValid(0xFFFFFFFFU));
584*a03ca8b9SKrzysztof Kosiński }
585*a03ca8b9SKrzysztof Kosiński 
586*a03ca8b9SKrzysztof Kosiński }  // namespace zucchini
587