1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <signal.h>
18 #include <sys/types.h>
19 
20 #include <limits>
21 #include <optional>
22 #include <vector>
23 
24 #include <gtest/gtest.h>
25 
26 #include "otautil/rangeset.h"
27 
TEST(RangeSetTest,ctor)28 TEST(RangeSetTest, ctor) {
29   RangeSet rs(std::vector<Range>{ Range{ 8, 10 }, Range{ 1, 5 } });
30   ASSERT_TRUE(rs);
31 
32   RangeSet rs2(std::vector<Range>{});
33   ASSERT_FALSE(rs2);
34 
35   RangeSet rs3(std::vector<Range>{ Range{ 8, 10 }, Range{ 5, 1 } });
36   ASSERT_FALSE(rs3);
37 }
38 
TEST(RangeSetTest,Parse_smoke)39 TEST(RangeSetTest, Parse_smoke) {
40   RangeSet rs = RangeSet::Parse("2,1,10");
41   ASSERT_EQ(static_cast<size_t>(1), rs.size());
42   ASSERT_EQ((Range{ 1, 10 }), rs[0]);
43   ASSERT_EQ(static_cast<size_t>(9), rs.blocks());
44 
45   RangeSet rs2 = RangeSet::Parse("4,15,20,1,10");
46   ASSERT_EQ(static_cast<size_t>(2), rs2.size());
47   ASSERT_EQ((Range{ 15, 20 }), rs2[0]);
48   ASSERT_EQ((Range{ 1, 10 }), rs2[1]);
49   ASSERT_EQ(static_cast<size_t>(14), rs2.blocks());
50 
51   // Leading zeros are fine. But android::base::ParseUint() doesn't like trailing zeros like "10 ".
52   ASSERT_EQ(rs, RangeSet::Parse(" 2, 1,   10"));
53   ASSERT_FALSE(RangeSet::Parse("2,1,10 "));
54 }
55 
TEST(RangeSetTest,Parse_InvalidCases)56 TEST(RangeSetTest, Parse_InvalidCases) {
57   // Insufficient number of tokens.
58   ASSERT_FALSE(RangeSet::Parse(""));
59   ASSERT_FALSE(RangeSet::Parse("2,1"));
60 
61   // The first token (i.e. the number of following tokens) is invalid.
62   ASSERT_FALSE(RangeSet::Parse("a,1,1"));
63   ASSERT_FALSE(RangeSet::Parse("3,1,1"));
64   ASSERT_FALSE(RangeSet::Parse("-3,1,1"));
65   ASSERT_FALSE(RangeSet::Parse("2,1,2,3"));
66 
67   // Invalid tokens.
68   ASSERT_FALSE(RangeSet::Parse("2,1,10a"));
69   ASSERT_FALSE(RangeSet::Parse("2,,10"));
70 
71   // Empty or negative range.
72   ASSERT_FALSE(RangeSet::Parse("2,2,2"));
73   ASSERT_FALSE(RangeSet::Parse("2,2,1"));
74 }
75 
TEST(RangeSetTest,Clear)76 TEST(RangeSetTest, Clear) {
77   RangeSet rs = RangeSet::Parse("2,1,6");
78   ASSERT_TRUE(rs);
79   rs.Clear();
80   ASSERT_FALSE(rs);
81 
82   // No-op to clear an empty RangeSet.
83   rs.Clear();
84   ASSERT_FALSE(rs);
85 }
86 
TEST(RangeSetTest,PushBack)87 TEST(RangeSetTest, PushBack) {
88   RangeSet rs;
89   ASSERT_FALSE(rs);
90 
91   ASSERT_TRUE(rs.PushBack({ 3, 5 }));
92   ASSERT_EQ(RangeSet::Parse("2,3,5"), rs);
93 
94   ASSERT_TRUE(rs.PushBack({ 5, 15 }));
95   ASSERT_EQ(RangeSet::Parse("4,3,5,5,15"), rs);
96   ASSERT_EQ(static_cast<size_t>(2), rs.size());
97   ASSERT_EQ(static_cast<size_t>(12), rs.blocks());
98 }
99 
TEST(RangeSetTest,PushBack_InvalidInput)100 TEST(RangeSetTest, PushBack_InvalidInput) {
101   RangeSet rs;
102   ASSERT_FALSE(rs);
103   ASSERT_FALSE(rs.PushBack({ 5, 3 }));
104   ASSERT_FALSE(rs);
105   ASSERT_FALSE(rs.PushBack({ 15, 15 }));
106   ASSERT_FALSE(rs);
107 
108   ASSERT_TRUE(rs.PushBack({ 5, 15 }));
109   ASSERT_FALSE(rs.PushBack({ 5, std::numeric_limits<size_t>::max() - 2 }));
110   ASSERT_EQ(RangeSet::Parse("2,5,15"), rs);
111 }
112 
TEST(RangeSetTest,Overlaps)113 TEST(RangeSetTest, Overlaps) {
114   RangeSet r1 = RangeSet::Parse("2,1,6");
115   RangeSet r2 = RangeSet::Parse("2,5,10");
116   ASSERT_TRUE(r1.Overlaps(r2));
117   ASSERT_TRUE(r2.Overlaps(r1));
118 
119   r2 = RangeSet::Parse("2,6,10");
120   ASSERT_FALSE(r1.Overlaps(r2));
121   ASSERT_FALSE(r2.Overlaps(r1));
122 
123   ASSERT_FALSE(RangeSet::Parse("2,3,5").Overlaps(RangeSet::Parse("2,5,7")));
124   ASSERT_FALSE(RangeSet::Parse("2,5,7").Overlaps(RangeSet::Parse("2,3,5")));
125 }
126 
TEST(RangeSetTest,Split)127 TEST(RangeSetTest, Split) {
128   RangeSet rs1 = RangeSet::Parse("2,1,2");
129   ASSERT_TRUE(rs1);
130   ASSERT_EQ((std::vector<RangeSet>{ RangeSet::Parse("2,1,2") }), rs1.Split(1));
131 
132   RangeSet rs2 = RangeSet::Parse("2,5,10");
133   ASSERT_TRUE(rs2);
134   ASSERT_EQ((std::vector<RangeSet>{ RangeSet::Parse("2,5,8"), RangeSet::Parse("2,8,10") }),
135             rs2.Split(2));
136 
137   RangeSet rs3 = RangeSet::Parse("4,0,1,5,10");
138   ASSERT_TRUE(rs3);
139   ASSERT_EQ((std::vector<RangeSet>{ RangeSet::Parse("4,0,1,5,7"), RangeSet::Parse("2,7,10") }),
140             rs3.Split(2));
141 
142   RangeSet rs4 = RangeSet::Parse("6,1,3,3,4,4,5");
143   ASSERT_TRUE(rs4);
144   ASSERT_EQ((std::vector<RangeSet>{ RangeSet::Parse("2,1,3"), RangeSet::Parse("2,3,4"),
145                                     RangeSet::Parse("2,4,5") }),
146             rs4.Split(3));
147 
148   RangeSet rs5 = RangeSet::Parse("2,0,10");
149   ASSERT_TRUE(rs5);
150   ASSERT_EQ((std::vector<RangeSet>{ RangeSet::Parse("2,0,3"), RangeSet::Parse("2,3,6"),
151                                     RangeSet::Parse("2,6,8"), RangeSet::Parse("2,8,10") }),
152             rs5.Split(4));
153 
154   RangeSet rs6 = RangeSet::Parse(
155       "20,0,268,269,271,286,447,8350,32770,33022,98306,98558,163842,164094,196609,204800,229378,"
156       "229630,294914,295166,457564");
157   ASSERT_TRUE(rs6);
158   size_t rs6_blocks = rs6.blocks();
159   auto splits = rs6.Split(4);
160   ASSERT_EQ(
161       (std::vector<RangeSet>{
162           RangeSet::Parse("12,0,268,269,271,286,447,8350,32770,33022,98306,98558,118472"),
163           RangeSet::Parse("8,118472,163842,164094,196609,204800,229378,229630,237216"),
164           RangeSet::Parse("4,237216,294914,295166,347516"), RangeSet::Parse("2,347516,457564") }),
165       splits);
166   size_t sum = 0;
167   for (const auto& element : splits) {
168     sum += element.blocks();
169   }
170   ASSERT_EQ(rs6_blocks, sum);
171 }
172 
TEST(RangeSetTest,Split_EdgeCases)173 TEST(RangeSetTest, Split_EdgeCases) {
174   // Empty RangeSet.
175   RangeSet rs1;
176   ASSERT_FALSE(rs1);
177   ASSERT_EQ((std::vector<RangeSet>{}), rs1.Split(2));
178   ASSERT_FALSE(rs1);
179 
180   // Zero group.
181   RangeSet rs2 = RangeSet::Parse("2,1,5");
182   ASSERT_TRUE(rs2);
183   ASSERT_EQ((std::vector<RangeSet>{}), rs2.Split(0));
184 
185   // The number of blocks equals to the number of groups.
186   RangeSet rs3 = RangeSet::Parse("2,1,5");
187   ASSERT_TRUE(rs3);
188   ASSERT_EQ((std::vector<RangeSet>{ RangeSet::Parse("2,1,2"), RangeSet::Parse("2,2,3"),
189                                     RangeSet::Parse("2,3,4"), RangeSet::Parse("2,4,5") }),
190             rs3.Split(4));
191 
192   // Less blocks than the number of groups.
193   RangeSet rs4 = RangeSet::Parse("2,1,5");
194   ASSERT_TRUE(rs4);
195   ASSERT_EQ((std::vector<RangeSet>{ RangeSet::Parse("2,1,2"), RangeSet::Parse("2,2,3"),
196                                     RangeSet::Parse("2,3,4"), RangeSet::Parse("2,4,5") }),
197             rs4.Split(8));
198 
199   // Less blocks than the number of groups.
200   RangeSet rs5 = RangeSet::Parse("2,0,3");
201   ASSERT_TRUE(rs5);
202   ASSERT_EQ((std::vector<RangeSet>{ RangeSet::Parse("2,0,1"), RangeSet::Parse("2,1,2"),
203                                     RangeSet::Parse("2,2,3") }),
204             rs5.Split(4));
205 }
206 
TEST(RangeSetTest,GetBlockNumber)207 TEST(RangeSetTest, GetBlockNumber) {
208   RangeSet rs = RangeSet::Parse("2,1,10");
209   ASSERT_EQ(static_cast<size_t>(1), rs.GetBlockNumber(0));
210   ASSERT_EQ(static_cast<size_t>(6), rs.GetBlockNumber(5));
211   ASSERT_EQ(static_cast<size_t>(9), rs.GetBlockNumber(8));
212 
213   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
214   // Out of bound.
215   ASSERT_EXIT(rs.GetBlockNumber(9), ::testing::KilledBySignal(SIGABRT), "");
216 }
217 
TEST(RangeSetTest,equality)218 TEST(RangeSetTest, equality) {
219   ASSERT_EQ(RangeSet::Parse("2,1,6"), RangeSet::Parse("2,1,6"));
220 
221   ASSERT_NE(RangeSet::Parse("2,1,6"), RangeSet::Parse("2,1,7"));
222   ASSERT_NE(RangeSet::Parse("2,1,6"), RangeSet::Parse("2,2,7"));
223 
224   // The orders of Range's matter, e.g. "4,1,5,8,10" != "4,8,10,1,5".
225   ASSERT_NE(RangeSet::Parse("4,1,5,8,10"), RangeSet::Parse("4,8,10,1,5"));
226 }
227 
TEST(RangeSetTest,iterators)228 TEST(RangeSetTest, iterators) {
229   RangeSet rs = RangeSet::Parse("4,1,5,8,10");
230   std::vector<Range> ranges;
231   for (const auto& range : rs) {
232     ranges.push_back(range);
233   }
234   ASSERT_EQ((std::vector<Range>{ Range{ 1, 5 }, Range{ 8, 10 } }), ranges);
235 
236   ranges.clear();
237 
238   // Reverse iterators.
239   for (auto it = rs.crbegin(); it != rs.crend(); it++) {
240     ranges.push_back(*it);
241   }
242   ASSERT_EQ((std::vector<Range>{ Range{ 8, 10 }, Range{ 1, 5 } }), ranges);
243 }
244 
TEST(RangeSetTest,ToString)245 TEST(RangeSetTest, ToString) {
246   ASSERT_EQ("", RangeSet::Parse("").ToString());
247   ASSERT_EQ("2,1,6", RangeSet::Parse("2,1,6").ToString());
248   ASSERT_EQ("4,1,5,8,10", RangeSet::Parse("4,1,5,8,10").ToString());
249   ASSERT_EQ("6,1,3,4,6,15,22", RangeSet::Parse("6,1,3,4,6,15,22").ToString());
250 }
251 
TEST(RangeSetTest,GetSubRanges_invalid)252 TEST(RangeSetTest, GetSubRanges_invalid) {
253   RangeSet range0({ { 1, 11 }, { 20, 30 } });
254   ASSERT_FALSE(range0.GetSubRanges(0, 21));  // too many blocks
255   ASSERT_FALSE(range0.GetSubRanges(21, 1));  // start block OOB
256 }
257 
TEST(RangeSetTest,GetSubRanges_empty)258 TEST(RangeSetTest, GetSubRanges_empty) {
259   RangeSet range0({ { 1, 11 }, { 20, 30 } });
260   ASSERT_EQ(RangeSet{}, range0.GetSubRanges(1, 0));  // empty num_of_blocks
261 }
262 
TEST(RangeSetTest,GetSubRanges_smoke)263 TEST(RangeSetTest, GetSubRanges_smoke) {
264   RangeSet range0({ { 10, 11 } });
265   ASSERT_EQ(RangeSet({ { 10, 11 } }), range0.GetSubRanges(0, 1));
266 
267   RangeSet range1({ { 10, 11 }, { 20, 21 }, { 30, 31 } });
268   ASSERT_EQ(range1, range1.GetSubRanges(0, 3));
269   ASSERT_EQ(RangeSet({ { 20, 21 } }), range1.GetSubRanges(1, 1));
270 
271   RangeSet range2({ { 1, 11 }, { 20, 25 }, { 30, 35 } });
272   ASSERT_EQ(RangeSet({ { 10, 11 }, { 20, 25 }, { 30, 31 } }), range2.GetSubRanges(9, 7));
273 }
274 
TEST(SortedRangeSetTest,Insert)275 TEST(SortedRangeSetTest, Insert) {
276   SortedRangeSet rs({ { 2, 3 }, { 4, 6 }, { 8, 14 } });
277   rs.Insert({ 1, 2 });
278   ASSERT_EQ(SortedRangeSet({ { 1, 3 }, { 4, 6 }, { 8, 14 } }), rs);
279   ASSERT_EQ(static_cast<size_t>(10), rs.blocks());
280   rs.Insert({ 3, 5 });
281   ASSERT_EQ(SortedRangeSet({ { 1, 6 }, { 8, 14 } }), rs);
282   ASSERT_EQ(static_cast<size_t>(11), rs.blocks());
283 
284   SortedRangeSet r1({ { 20, 22 }, { 15, 18 } });
285   rs.Insert(r1);
286   ASSERT_EQ(SortedRangeSet({ { 1, 6 }, { 8, 14 }, { 15, 18 }, { 20, 22 } }), rs);
287   ASSERT_EQ(static_cast<size_t>(16), rs.blocks());
288 
289   SortedRangeSet r2({ { 2, 7 }, { 15, 21 }, { 20, 25 } });
290   rs.Insert(r2);
291   ASSERT_EQ(SortedRangeSet({ { 1, 7 }, { 8, 14 }, { 15, 25 } }), rs);
292   ASSERT_EQ(static_cast<size_t>(22), rs.blocks());
293 }
294 
TEST(SortedRangeSetTest,file_range)295 TEST(SortedRangeSetTest, file_range) {
296   SortedRangeSet rs;
297   rs.Insert(4096, 4096);
298   ASSERT_EQ(SortedRangeSet({ { 1, 2 } }), rs);
299   // insert block 2-9
300   rs.Insert(4096 * 3 - 1, 4096 * 7);
301   ASSERT_EQ(SortedRangeSet({ { 1, 10 } }), rs);
302   // insert block 15-19
303   rs.Insert(4096 * 15 + 1, 4096 * 4);
304   ASSERT_EQ(SortedRangeSet({ { 1, 10 }, { 15, 20 } }), rs);
305 
306   // rs overlaps block 2-2
307   ASSERT_TRUE(rs.Overlaps(4096 * 2 - 1, 10));
308   ASSERT_FALSE(rs.Overlaps(4096 * 10, 4096 * 5));
309 
310   ASSERT_EQ(static_cast<size_t>(10), rs.GetOffsetInRangeSet(4106));
311   ASSERT_EQ(static_cast<size_t>(40970), rs.GetOffsetInRangeSet(4096 * 16 + 10));
312 
313   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
314   // block#10 not in range.
315   ASSERT_EXIT(rs.GetOffsetInRangeSet(40970), ::testing::KilledBySignal(SIGABRT), "");
316 }
317