blob: 11b17edff6a3a32d1a38b7c96c57ec5e4de8019d [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
5#include <vector>
6
7#include <gtest/gtest.h>
8
9#include "update_engine/extent_ranges.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070010#include "update_engine/payload_constants.h"
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -070011#include "update_engine/test_utils.h"
12
13using std::vector;
14
15namespace chromeos_update_engine {
16
17class ExtentRangesTest : public ::testing::Test {};
18
19namespace {
20void ExpectRangeEq(const ExtentRanges& ranges,
Darin Petkov94817cb2013-05-08 14:33:24 +020021 const uint64_t* expected,
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -070022 size_t sz,
23 int line) {
24 uint64_t blocks = 0;
25 for (size_t i = 1; i < sz; i += 2) {
26 blocks += expected[i];
27 }
28 EXPECT_EQ(blocks, ranges.blocks()) << "line: " << line;
29
30 const ExtentRanges::ExtentSet& result = ranges.extent_set();
31 ExtentRanges::ExtentSet::const_iterator it = result.begin();
32 for (size_t i = 0; i < sz; i += 2) {
33 EXPECT_FALSE(it == result.end()) << "line: " << line;
34 EXPECT_EQ(expected[i], it->start_block()) << "line: " << line;
35 EXPECT_EQ(expected[i + 1], it->num_blocks()) << "line: " << line;
36 ++it;
37 }
38}
39
40#define EXPECT_RANGE_EQ(ranges, var) \
41 do { \
42 ExpectRangeEq(ranges, var, arraysize(var), __LINE__); \
43 } while (0)
44
45void ExpectRangesOverlapOrTouch(uint64_t a_start, uint64_t a_num,
46 uint64_t b_start, uint64_t b_num) {
47 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start,
48 a_num),
49 ExtentForRange(b_start,
50 b_num)));
51 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start,
52 b_num),
53 ExtentForRange(a_start,
54 a_num)));
55}
56
57void ExpectFalseRangesOverlapOrTouch(uint64_t a_start, uint64_t a_num,
58 uint64_t b_start, uint64_t b_num) {
59 EXPECT_FALSE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start,
60 a_num),
61 ExtentForRange(b_start,
62 b_num)));
63 EXPECT_FALSE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start,
64 b_num),
65 ExtentForRange(a_start,
66 a_num)));
67 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start,
68 a_num),
69 ExtentForRange(b_start,
70 b_num)));
71 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start,
72 b_num),
73 ExtentForRange(a_start,
74 a_num)));
75}
76
77void ExpectRangesOverlap(uint64_t a_start, uint64_t a_num,
78 uint64_t b_start, uint64_t b_num) {
79 EXPECT_TRUE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start,
80 a_num),
81 ExtentForRange(b_start,
82 b_num)));
83 EXPECT_TRUE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start,
84 b_num),
85 ExtentForRange(a_start,
86 a_num)));
87 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start,
88 a_num),
89 ExtentForRange(b_start,
90 b_num)));
91 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start,
92 b_num),
93 ExtentForRange(a_start,
94 a_num)));
95}
96
97void ExpectFalseRangesOverlap(uint64_t a_start, uint64_t a_num,
98 uint64_t b_start, uint64_t b_num) {
99 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start,
100 a_num),
101 ExtentForRange(b_start,
102 b_num)));
103 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start,
104 b_num),
105 ExtentForRange(a_start,
106 a_num)));
107}
108
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700109} // namespace
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700110
111TEST(ExtentRangesTest, ExtentsOverlapTest) {
112 ExpectRangesOverlapOrTouch(10, 20, 30, 10);
113 ExpectRangesOverlap(10, 20, 25, 10);
114 ExpectFalseRangesOverlapOrTouch(10, 20, 35, 10);
115 ExpectFalseRangesOverlap(10, 20, 30, 10);
116 ExpectRangesOverlap(12, 4, 12, 3);
Darin Petkov94817cb2013-05-08 14:33:24 +0200117
118 ExpectRangesOverlapOrTouch(kSparseHole, 2, kSparseHole, 3);
119 ExpectRangesOverlap(kSparseHole, 2, kSparseHole, 3);
120 ExpectFalseRangesOverlapOrTouch(kSparseHole, 2, 10, 3);
121 ExpectFalseRangesOverlapOrTouch(10, 2, kSparseHole, 3);
122 ExpectFalseRangesOverlap(kSparseHole, 2, 10, 3);
123 ExpectFalseRangesOverlap(10, 2, kSparseHole, 3);
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700124}
125
126TEST(ExtentRangesTest, SimpleTest) {
127 ExtentRanges ranges;
128 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200129 static const uint64_t expected[] = {};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700130 // Can't use arraysize() on 0-length arrays:
131 ExpectRangeEq(ranges, expected, 0, __LINE__);
132 }
133 ranges.SubtractBlock(2);
134 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200135 static const uint64_t expected[] = {};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700136 // Can't use arraysize() on 0-length arrays:
137 ExpectRangeEq(ranges, expected, 0, __LINE__);
138 }
Darin Petkov94817cb2013-05-08 14:33:24 +0200139
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700140 ranges.AddBlock(0);
141 ranges.Dump();
142 ranges.AddBlock(1);
143 ranges.AddBlock(3);
Darin Petkov94817cb2013-05-08 14:33:24 +0200144
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700145 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200146 static const uint64_t expected[] = {0, 2, 3, 1};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700147 EXPECT_RANGE_EQ(ranges, expected);
148 }
149 ranges.AddBlock(2);
150 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200151 static const uint64_t expected[] = {0, 4};
152 EXPECT_RANGE_EQ(ranges, expected);
153 ranges.AddBlock(kSparseHole);
154 EXPECT_RANGE_EQ(ranges, expected);
155 ranges.SubtractBlock(kSparseHole);
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700156 EXPECT_RANGE_EQ(ranges, expected);
157 }
158 ranges.SubtractBlock(2);
159 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200160 static const uint64_t expected[] = {0, 2, 3, 1};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700161 EXPECT_RANGE_EQ(ranges, expected);
162 }
163
164 for (uint64_t i = 100; i < 1000; i += 100) {
165 ranges.AddExtent(ExtentForRange(i, 50));
166 }
167 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200168 static const uint64_t expected[] = {
169 0, 2, 3, 1, 100, 50, 200, 50, 300, 50, 400, 50,
170 500, 50, 600, 50, 700, 50, 800, 50, 900, 50
171 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700172 EXPECT_RANGE_EQ(ranges, expected);
173 }
174
175 ranges.SubtractExtent(ExtentForRange(210, 410 - 210));
176 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200177 static const uint64_t expected[] = {
178 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50,
179 600, 50, 700, 50, 800, 50, 900, 50
180 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700181 EXPECT_RANGE_EQ(ranges, expected);
182 }
183 ranges.AddExtent(ExtentForRange(100000, 0));
184 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200185 static const uint64_t expected[] = {
186 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50,
187 600, 50, 700, 50, 800, 50, 900, 50
188 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700189 EXPECT_RANGE_EQ(ranges, expected);
190 }
191 ranges.SubtractExtent(ExtentForRange(3, 0));
192 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200193 static const uint64_t expected[] = {
194 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50,
195 600, 50, 700, 50, 800, 50, 900, 50
196 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700197 EXPECT_RANGE_EQ(ranges, expected);
198 }
199}
200
201TEST(ExtentRangesTest, MultipleRanges) {
202 ExtentRanges ranges_a, ranges_b;
203 ranges_a.AddBlock(0);
204 ranges_b.AddBlock(4);
205 ranges_b.AddBlock(3);
206 {
207 uint64_t expected[] = {3, 2};
208 EXPECT_RANGE_EQ(ranges_b, expected);
209 }
210 ranges_a.AddRanges(ranges_b);
211 {
212 uint64_t expected[] = {0, 1, 3, 2};
213 EXPECT_RANGE_EQ(ranges_a, expected);
214 }
215 ranges_a.SubtractRanges(ranges_b);
216 {
217 uint64_t expected[] = {0, 1};
218 EXPECT_RANGE_EQ(ranges_a, expected);
219 }
220 {
221 uint64_t expected[] = {3, 2};
222 EXPECT_RANGE_EQ(ranges_b, expected);
223 }
224}
225
226TEST(ExtentRangesTest, GetExtentsForBlockCountTest) {
227 ExtentRanges ranges;
228 ranges.AddExtents(vector<Extent>(1, ExtentForRange(10, 30)));
229 {
230 vector<Extent> zero_extents = ranges.GetExtentsForBlockCount(0);
231 EXPECT_TRUE(zero_extents.empty());
232 }
233 ::google::protobuf::RepeatedPtrField<Extent> rep_field;
234 *rep_field.Add() = ExtentForRange(30, 40);
235 ranges.AddRepeatedExtents(rep_field);
236 ranges.SubtractExtents(vector<Extent>(1, ExtentForRange(20, 10)));
237 *rep_field.Mutable(0) = ExtentForRange(50, 10);
238 ranges.SubtractRepeatedExtents(rep_field);
239 EXPECT_EQ(40, ranges.blocks());
240
241 for (int i = 0; i < 2; i++) {
242 vector<Extent> expected(2);
243 expected[0] = ExtentForRange(10, 10);
244 expected[1] = ExtentForRange(30, i == 0 ? 10 : 20);
245 vector<Extent> actual =
246 ranges.GetExtentsForBlockCount(10 + expected[1].num_blocks());
247 EXPECT_EQ(expected.size(), actual.size());
248 for (vector<Extent>::size_type j = 0, e = expected.size(); j != e; ++j) {
249 EXPECT_EQ(expected[j].start_block(), actual[j].start_block())
250 << "j = " << j;
251 EXPECT_EQ(expected[j].num_blocks(), actual[j].num_blocks())
252 << "j = " << j;
253 }
254 }
255}
256
257} // namespace chromeos_update_engine