blob: b4de3bc8852fb342327b4276c4982cf548a5169c [file] [log] [blame]
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -07001// Copyright (c) 2010 The Chromium OS 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.
4
Alex Deymoaab50e32014-11-10 19:55:35 -08005#include "update_engine/extent_ranges.h"
6
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -07007#include <vector>
8
9#include <gtest/gtest.h>
10
Alex Deymo161c4a12014-05-16 15:56:21 -070011#include "update_engine/payload_constants.h"
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -070012#include "update_engine/test_utils.h"
13
14using std::vector;
15
16namespace chromeos_update_engine {
17
18class ExtentRangesTest : public ::testing::Test {};
19
20namespace {
21void ExpectRangeEq(const ExtentRanges& ranges,
Darin Petkov94817cb2013-05-08 14:33:24 +020022 const uint64_t* expected,
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -070023 size_t sz,
24 int line) {
25 uint64_t blocks = 0;
26 for (size_t i = 1; i < sz; i += 2) {
27 blocks += expected[i];
28 }
29 EXPECT_EQ(blocks, ranges.blocks()) << "line: " << line;
30
31 const ExtentRanges::ExtentSet& result = ranges.extent_set();
32 ExtentRanges::ExtentSet::const_iterator it = result.begin();
33 for (size_t i = 0; i < sz; i += 2) {
34 EXPECT_FALSE(it == result.end()) << "line: " << line;
35 EXPECT_EQ(expected[i], it->start_block()) << "line: " << line;
36 EXPECT_EQ(expected[i + 1], it->num_blocks()) << "line: " << line;
37 ++it;
38 }
39}
40
41#define EXPECT_RANGE_EQ(ranges, var) \
42 do { \
43 ExpectRangeEq(ranges, var, arraysize(var), __LINE__); \
44 } while (0)
45
46void ExpectRangesOverlapOrTouch(uint64_t a_start, uint64_t a_num,
47 uint64_t b_start, uint64_t b_num) {
48 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start,
49 a_num),
50 ExtentForRange(b_start,
51 b_num)));
52 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start,
53 b_num),
54 ExtentForRange(a_start,
55 a_num)));
56}
57
58void ExpectFalseRangesOverlapOrTouch(uint64_t a_start, uint64_t a_num,
59 uint64_t b_start, uint64_t b_num) {
60 EXPECT_FALSE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start,
61 a_num),
62 ExtentForRange(b_start,
63 b_num)));
64 EXPECT_FALSE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start,
65 b_num),
66 ExtentForRange(a_start,
67 a_num)));
68 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start,
69 a_num),
70 ExtentForRange(b_start,
71 b_num)));
72 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start,
73 b_num),
74 ExtentForRange(a_start,
75 a_num)));
76}
77
78void ExpectRangesOverlap(uint64_t a_start, uint64_t a_num,
79 uint64_t b_start, uint64_t b_num) {
80 EXPECT_TRUE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start,
81 a_num),
82 ExtentForRange(b_start,
83 b_num)));
84 EXPECT_TRUE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start,
85 b_num),
86 ExtentForRange(a_start,
87 a_num)));
88 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start,
89 a_num),
90 ExtentForRange(b_start,
91 b_num)));
92 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start,
93 b_num),
94 ExtentForRange(a_start,
95 a_num)));
96}
97
98void ExpectFalseRangesOverlap(uint64_t a_start, uint64_t a_num,
99 uint64_t b_start, uint64_t b_num) {
100 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start,
101 a_num),
102 ExtentForRange(b_start,
103 b_num)));
104 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start,
105 b_num),
106 ExtentForRange(a_start,
107 a_num)));
108}
109
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700110} // namespace
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700111
112TEST(ExtentRangesTest, ExtentsOverlapTest) {
113 ExpectRangesOverlapOrTouch(10, 20, 30, 10);
114 ExpectRangesOverlap(10, 20, 25, 10);
115 ExpectFalseRangesOverlapOrTouch(10, 20, 35, 10);
116 ExpectFalseRangesOverlap(10, 20, 30, 10);
117 ExpectRangesOverlap(12, 4, 12, 3);
Darin Petkov94817cb2013-05-08 14:33:24 +0200118
119 ExpectRangesOverlapOrTouch(kSparseHole, 2, kSparseHole, 3);
120 ExpectRangesOverlap(kSparseHole, 2, kSparseHole, 3);
121 ExpectFalseRangesOverlapOrTouch(kSparseHole, 2, 10, 3);
122 ExpectFalseRangesOverlapOrTouch(10, 2, kSparseHole, 3);
123 ExpectFalseRangesOverlap(kSparseHole, 2, 10, 3);
124 ExpectFalseRangesOverlap(10, 2, kSparseHole, 3);
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700125}
126
127TEST(ExtentRangesTest, SimpleTest) {
128 ExtentRanges ranges;
129 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200130 static const uint64_t expected[] = {};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700131 // Can't use arraysize() on 0-length arrays:
132 ExpectRangeEq(ranges, expected, 0, __LINE__);
133 }
134 ranges.SubtractBlock(2);
135 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200136 static const uint64_t expected[] = {};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700137 // Can't use arraysize() on 0-length arrays:
138 ExpectRangeEq(ranges, expected, 0, __LINE__);
139 }
Darin Petkov94817cb2013-05-08 14:33:24 +0200140
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700141 ranges.AddBlock(0);
142 ranges.Dump();
143 ranges.AddBlock(1);
144 ranges.AddBlock(3);
Darin Petkov94817cb2013-05-08 14:33:24 +0200145
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700146 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200147 static const uint64_t expected[] = {0, 2, 3, 1};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700148 EXPECT_RANGE_EQ(ranges, expected);
149 }
150 ranges.AddBlock(2);
151 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200152 static const uint64_t expected[] = {0, 4};
153 EXPECT_RANGE_EQ(ranges, expected);
154 ranges.AddBlock(kSparseHole);
155 EXPECT_RANGE_EQ(ranges, expected);
156 ranges.SubtractBlock(kSparseHole);
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700157 EXPECT_RANGE_EQ(ranges, expected);
158 }
159 ranges.SubtractBlock(2);
160 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200161 static const uint64_t expected[] = {0, 2, 3, 1};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700162 EXPECT_RANGE_EQ(ranges, expected);
163 }
164
165 for (uint64_t i = 100; i < 1000; i += 100) {
166 ranges.AddExtent(ExtentForRange(i, 50));
167 }
168 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200169 static const uint64_t expected[] = {
170 0, 2, 3, 1, 100, 50, 200, 50, 300, 50, 400, 50,
171 500, 50, 600, 50, 700, 50, 800, 50, 900, 50
172 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700173 EXPECT_RANGE_EQ(ranges, expected);
174 }
175
176 ranges.SubtractExtent(ExtentForRange(210, 410 - 210));
177 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200178 static const uint64_t expected[] = {
179 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50,
180 600, 50, 700, 50, 800, 50, 900, 50
181 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700182 EXPECT_RANGE_EQ(ranges, expected);
183 }
184 ranges.AddExtent(ExtentForRange(100000, 0));
185 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200186 static const uint64_t expected[] = {
187 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50,
188 600, 50, 700, 50, 800, 50, 900, 50
189 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700190 EXPECT_RANGE_EQ(ranges, expected);
191 }
192 ranges.SubtractExtent(ExtentForRange(3, 0));
193 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200194 static const uint64_t expected[] = {
195 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50,
196 600, 50, 700, 50, 800, 50, 900, 50
197 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700198 EXPECT_RANGE_EQ(ranges, expected);
199 }
200}
201
202TEST(ExtentRangesTest, MultipleRanges) {
203 ExtentRanges ranges_a, ranges_b;
204 ranges_a.AddBlock(0);
205 ranges_b.AddBlock(4);
206 ranges_b.AddBlock(3);
207 {
208 uint64_t expected[] = {3, 2};
209 EXPECT_RANGE_EQ(ranges_b, expected);
210 }
211 ranges_a.AddRanges(ranges_b);
212 {
213 uint64_t expected[] = {0, 1, 3, 2};
214 EXPECT_RANGE_EQ(ranges_a, expected);
215 }
216 ranges_a.SubtractRanges(ranges_b);
217 {
218 uint64_t expected[] = {0, 1};
219 EXPECT_RANGE_EQ(ranges_a, expected);
220 }
221 {
222 uint64_t expected[] = {3, 2};
223 EXPECT_RANGE_EQ(ranges_b, expected);
224 }
225}
226
227TEST(ExtentRangesTest, GetExtentsForBlockCountTest) {
228 ExtentRanges ranges;
229 ranges.AddExtents(vector<Extent>(1, ExtentForRange(10, 30)));
230 {
231 vector<Extent> zero_extents = ranges.GetExtentsForBlockCount(0);
232 EXPECT_TRUE(zero_extents.empty());
233 }
234 ::google::protobuf::RepeatedPtrField<Extent> rep_field;
235 *rep_field.Add() = ExtentForRange(30, 40);
236 ranges.AddRepeatedExtents(rep_field);
237 ranges.SubtractExtents(vector<Extent>(1, ExtentForRange(20, 10)));
238 *rep_field.Mutable(0) = ExtentForRange(50, 10);
239 ranges.SubtractRepeatedExtents(rep_field);
240 EXPECT_EQ(40, ranges.blocks());
241
242 for (int i = 0; i < 2; i++) {
243 vector<Extent> expected(2);
244 expected[0] = ExtentForRange(10, 10);
245 expected[1] = ExtentForRange(30, i == 0 ? 10 : 20);
246 vector<Extent> actual =
247 ranges.GetExtentsForBlockCount(10 + expected[1].num_blocks());
248 EXPECT_EQ(expected.size(), actual.size());
249 for (vector<Extent>::size_type j = 0, e = expected.size(); j != e; ++j) {
250 EXPECT_EQ(expected[j].start_block(), actual[j].start_block())
251 << "j = " << j;
252 EXPECT_EQ(expected[j].num_blocks(), actual[j].num_blocks())
253 << "j = " << j;
254 }
255 }
256}
257
258} // namespace chromeos_update_engine