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