1 //===-- RangeTest.cpp -----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Utility/RangeMap.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
12 
13 using namespace lldb_private;
14 
TEST(RangeVector,CombineConsecutiveRanges)15 TEST(RangeVector, CombineConsecutiveRanges) {
16   using RangeVector = RangeVector<uint32_t, uint32_t>;
17   using Entry = RangeVector::Entry;
18 
19   RangeVector V;
20   V.Append(0, 1);
21   V.Append(5, 1);
22   V.Append(6, 1);
23   V.Append(10, 9);
24   V.Append(15, 1);
25   V.Append(20, 9);
26   V.Append(21, 9);
27   V.Sort();
28   V.CombineConsecutiveRanges();
29   EXPECT_THAT(V, testing::ElementsAre(Entry(0, 1), Entry(5, 2), Entry(10, 9),
30                                       Entry(20, 10)));
31 
32   V.Clear();
33   V.Append(0, 20);
34   V.Append(5, 1);
35   V.Append(10, 1);
36   V.Sort();
37   V.CombineConsecutiveRanges();
38   EXPECT_THAT(V, testing::ElementsAre(Entry(0, 20)));
39 }
40 
TEST(RangeVector,GetOverlaps)41 TEST(RangeVector, GetOverlaps) {
42   using RangeVector = RangeVector<uint32_t, uint32_t>;
43 
44   RangeVector V1;
45   RangeVector V2;
46   RangeVector Expected;
47   // same range
48   V1.Append(0, 1);
49   V2.Append(0, 1);
50   Expected.Append(0, 1);
51 
52   // no overlap
53   V1.Append(2, 2);
54   V2.Append(4, 1);
55 
56   // same base overlap
57   V1.Append(10, 5);
58   V2.Append(10, 3);
59   Expected.Append(10, 3);
60 
61   // same end overlap
62   V1.Append(27, 1);
63   V2.Append(20, 8);
64   Expected.Append(27, 1);
65 
66   // smaller base overlap
67   V1.Append(33, 4);
68   V2.Append(30, 5);
69   Expected.Append(33, 2);
70 
71   // larger base overlap
72   V1.Append(46, 3);
73   V2.Append(40, 7);
74   Expected.Append(46, 1);
75 
76   // encompass 1 range
77   V1.Append(50, 9);
78   V2.Append(51, 7);
79   Expected.Append(51, 7);
80 
81   // encompass 2 ranges
82   V1.Append(60, 9);
83   V2.Append(60, 3);
84   V2.Append(65, 3);
85   Expected.Append(60, 3);
86   Expected.Append(65, 3);
87 
88   V1.Sort();
89   V2.Sort();
90   Expected.Sort();
91 
92   EXPECT_EQ(RangeVector::GetOverlaps(V1, V2), Expected);
93   EXPECT_EQ(RangeVector::GetOverlaps(V2, V1), Expected);
94 }
95 
96 using RangeDataVectorT = RangeDataVector<uint32_t, uint32_t, uint32_t>;
97 using EntryT = RangeDataVectorT::Entry;
98 
EntryIs(uint32_t ID)99 static testing::Matcher<const EntryT *> EntryIs(uint32_t ID) {
100   return testing::Pointee(testing::Field(&EntryT::data, ID));
101 }
102 
FindEntryIndexes(uint32_t address,RangeDataVectorT map)103 std::vector<uint32_t> FindEntryIndexes(uint32_t address, RangeDataVectorT map) {
104   std::vector<uint32_t> result;
105   map.FindEntryIndexesThatContain(address, result);
106   return result;
107 }
108 
TEST(RangeDataVector,FindEntryThatContains)109 TEST(RangeDataVector, FindEntryThatContains) {
110   RangeDataVectorT Map;
111   uint32_t NextID = 0;
112   Map.Append(EntryT(0, 10, NextID++));
113   Map.Append(EntryT(10, 10, NextID++));
114   Map.Append(EntryT(20, 10, NextID++));
115   Map.Sort();
116 
117   EXPECT_THAT(Map.FindEntryThatContains(0), EntryIs(0));
118   EXPECT_THAT(Map.FindEntryThatContains(9), EntryIs(0));
119   EXPECT_THAT(Map.FindEntryThatContains(10), EntryIs(1));
120   EXPECT_THAT(Map.FindEntryThatContains(19), EntryIs(1));
121   EXPECT_THAT(Map.FindEntryThatContains(20), EntryIs(2));
122   EXPECT_THAT(Map.FindEntryThatContains(29), EntryIs(2));
123   EXPECT_THAT(Map.FindEntryThatContains(30), nullptr);
124 }
125 
TEST(RangeDataVector,FindEntryThatContains_Overlap)126 TEST(RangeDataVector, FindEntryThatContains_Overlap) {
127   RangeDataVectorT Map;
128   uint32_t NextID = 0;
129   Map.Append(EntryT(0, 40, NextID++));
130   Map.Append(EntryT(10, 20, NextID++));
131   Map.Append(EntryT(20, 10, NextID++));
132   Map.Sort();
133 
134   // With overlapping intervals, the intention seems to be to return the first
135   // interval which contains the address.
136   EXPECT_THAT(Map.FindEntryThatContains(25), EntryIs(0));
137 
138   // However, this does not always succeed.
139   // TODO: This should probably return the range (0, 40) as well.
140   EXPECT_THAT(Map.FindEntryThatContains(35), nullptr);
141 }
142 
TEST(RangeDataVector,CustomSort)143 TEST(RangeDataVector, CustomSort) {
144   // First the default ascending order sorting of the data field.
145   auto Map = RangeDataVectorT();
146   Map.Append(EntryT(0, 10, 50));
147   Map.Append(EntryT(0, 10, 52));
148   Map.Append(EntryT(0, 10, 53));
149   Map.Append(EntryT(0, 10, 51));
150   Map.Sort();
151 
152   EXPECT_THAT(Map.GetSize(), 4);
153   EXPECT_THAT(Map.GetEntryRef(0).data, 50);
154   EXPECT_THAT(Map.GetEntryRef(1).data, 51);
155   EXPECT_THAT(Map.GetEntryRef(2).data, 52);
156   EXPECT_THAT(Map.GetEntryRef(3).data, 53);
157 
158   // And then a custom descending order sorting of the data field.
159   class CtorParam {};
160   class CustomSort {
161   public:
162     CustomSort(CtorParam) {}
163     bool operator()(const uint32_t a_data, const uint32_t b_data) {
164       return a_data > b_data;
165     }
166   };
167   using RangeDataVectorCustomSortT =
168       RangeDataVector<uint32_t, uint32_t, uint32_t, 0, CustomSort>;
169   using EntryT = RangeDataVectorT::Entry;
170 
171   auto MapC = RangeDataVectorCustomSortT(CtorParam());
172   MapC.Append(EntryT(0, 10, 50));
173   MapC.Append(EntryT(0, 10, 52));
174   MapC.Append(EntryT(0, 10, 53));
175   MapC.Append(EntryT(0, 10, 51));
176   MapC.Sort();
177 
178   EXPECT_THAT(MapC.GetSize(), 4);
179   EXPECT_THAT(MapC.GetEntryRef(0).data, 53);
180   EXPECT_THAT(MapC.GetEntryRef(1).data, 52);
181   EXPECT_THAT(MapC.GetEntryRef(2).data, 51);
182   EXPECT_THAT(MapC.GetEntryRef(3).data, 50);
183 }
184 
TEST(RangeDataVector,FindEntryIndexesThatContain)185 TEST(RangeDataVector, FindEntryIndexesThatContain) {
186   RangeDataVectorT Map;
187   Map.Append(EntryT(0, 10, 10));
188   Map.Append(EntryT(10, 10, 11));
189   Map.Append(EntryT(20, 10, 12));
190   Map.Sort();
191 
192   EXPECT_THAT(FindEntryIndexes(0, Map), testing::ElementsAre(10));
193   EXPECT_THAT(FindEntryIndexes(9, Map), testing::ElementsAre(10));
194   EXPECT_THAT(FindEntryIndexes(10, Map), testing::ElementsAre(11));
195   EXPECT_THAT(FindEntryIndexes(19, Map), testing::ElementsAre(11));
196   EXPECT_THAT(FindEntryIndexes(20, Map), testing::ElementsAre(12));
197   EXPECT_THAT(FindEntryIndexes(29, Map), testing::ElementsAre(12));
198   EXPECT_THAT(FindEntryIndexes(30, Map), testing::ElementsAre());
199 }
200 
TEST(RangeDataVector,FindEntryIndexesThatContain_Overlap)201 TEST(RangeDataVector, FindEntryIndexesThatContain_Overlap) {
202   RangeDataVectorT Map;
203   Map.Append(EntryT(0, 40, 10));
204   Map.Append(EntryT(10, 20, 11));
205   Map.Append(EntryT(20, 10, 12));
206   Map.Sort();
207 
208   EXPECT_THAT(FindEntryIndexes(0, Map), testing::ElementsAre(10));
209   EXPECT_THAT(FindEntryIndexes(9, Map), testing::ElementsAre(10));
210   EXPECT_THAT(FindEntryIndexes(10, Map), testing::ElementsAre(10, 11));
211   EXPECT_THAT(FindEntryIndexes(19, Map), testing::ElementsAre(10, 11));
212   EXPECT_THAT(FindEntryIndexes(20, Map), testing::ElementsAre(10, 11, 12));
213   EXPECT_THAT(FindEntryIndexes(29, Map), testing::ElementsAre(10, 11, 12));
214   EXPECT_THAT(FindEntryIndexes(30, Map), testing::ElementsAre(10));
215   EXPECT_THAT(FindEntryIndexes(39, Map), testing::ElementsAre(10));
216   EXPECT_THAT(FindEntryIndexes(40, Map), testing::ElementsAre());
217 }
218