blob: 1b767f15555f9fb28ee2ba38924d163b8b446161 [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"
10#include "update_engine/test_utils.h"
11
12using std::vector;
13
14namespace chromeos_update_engine {
15
16class ExtentRangesTest : public ::testing::Test {};
17
18namespace {
19void ExpectRangeEq(const ExtentRanges& ranges,
Darin Petkov94817cb2013-05-08 14:33:24 +020020 const uint64_t* expected,
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -070021 size_t sz,
22 int line) {
23 uint64_t blocks = 0;
24 for (size_t i = 1; i < sz; i += 2) {
25 blocks += expected[i];
26 }
27 EXPECT_EQ(blocks, ranges.blocks()) << "line: " << line;
28
29 const ExtentRanges::ExtentSet& result = ranges.extent_set();
30 ExtentRanges::ExtentSet::const_iterator it = result.begin();
31 for (size_t i = 0; i < sz; i += 2) {
32 EXPECT_FALSE(it == result.end()) << "line: " << line;
33 EXPECT_EQ(expected[i], it->start_block()) << "line: " << line;
34 EXPECT_EQ(expected[i + 1], it->num_blocks()) << "line: " << line;
35 ++it;
36 }
37}
38
39#define EXPECT_RANGE_EQ(ranges, var) \
40 do { \
41 ExpectRangeEq(ranges, var, arraysize(var), __LINE__); \
42 } while (0)
43
44void ExpectRangesOverlapOrTouch(uint64_t a_start, uint64_t a_num,
45 uint64_t b_start, uint64_t b_num) {
46 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start,
47 a_num),
48 ExtentForRange(b_start,
49 b_num)));
50 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start,
51 b_num),
52 ExtentForRange(a_start,
53 a_num)));
54}
55
56void ExpectFalseRangesOverlapOrTouch(uint64_t a_start, uint64_t a_num,
57 uint64_t b_start, uint64_t b_num) {
58 EXPECT_FALSE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start,
59 a_num),
60 ExtentForRange(b_start,
61 b_num)));
62 EXPECT_FALSE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start,
63 b_num),
64 ExtentForRange(a_start,
65 a_num)));
66 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start,
67 a_num),
68 ExtentForRange(b_start,
69 b_num)));
70 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start,
71 b_num),
72 ExtentForRange(a_start,
73 a_num)));
74}
75
76void ExpectRangesOverlap(uint64_t a_start, uint64_t a_num,
77 uint64_t b_start, uint64_t b_num) {
78 EXPECT_TRUE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start,
79 a_num),
80 ExtentForRange(b_start,
81 b_num)));
82 EXPECT_TRUE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start,
83 b_num),
84 ExtentForRange(a_start,
85 a_num)));
86 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start,
87 a_num),
88 ExtentForRange(b_start,
89 b_num)));
90 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start,
91 b_num),
92 ExtentForRange(a_start,
93 a_num)));
94}
95
96void ExpectFalseRangesOverlap(uint64_t a_start, uint64_t a_num,
97 uint64_t b_start, uint64_t b_num) {
98 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start,
99 a_num),
100 ExtentForRange(b_start,
101 b_num)));
102 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start,
103 b_num),
104 ExtentForRange(a_start,
105 a_num)));
106}
107
108} // namespace {}
109
110TEST(ExtentRangesTest, ExtentsOverlapTest) {
111 ExpectRangesOverlapOrTouch(10, 20, 30, 10);
112 ExpectRangesOverlap(10, 20, 25, 10);
113 ExpectFalseRangesOverlapOrTouch(10, 20, 35, 10);
114 ExpectFalseRangesOverlap(10, 20, 30, 10);
115 ExpectRangesOverlap(12, 4, 12, 3);
Darin Petkov94817cb2013-05-08 14:33:24 +0200116
117 ExpectRangesOverlapOrTouch(kSparseHole, 2, kSparseHole, 3);
118 ExpectRangesOverlap(kSparseHole, 2, kSparseHole, 3);
119 ExpectFalseRangesOverlapOrTouch(kSparseHole, 2, 10, 3);
120 ExpectFalseRangesOverlapOrTouch(10, 2, kSparseHole, 3);
121 ExpectFalseRangesOverlap(kSparseHole, 2, 10, 3);
122 ExpectFalseRangesOverlap(10, 2, kSparseHole, 3);
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700123}
124
125TEST(ExtentRangesTest, SimpleTest) {
126 ExtentRanges ranges;
127 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200128 static const uint64_t expected[] = {};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700129 // Can't use arraysize() on 0-length arrays:
130 ExpectRangeEq(ranges, expected, 0, __LINE__);
131 }
132 ranges.SubtractBlock(2);
133 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200134 static const uint64_t expected[] = {};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700135 // Can't use arraysize() on 0-length arrays:
136 ExpectRangeEq(ranges, expected, 0, __LINE__);
137 }
Darin Petkov94817cb2013-05-08 14:33:24 +0200138
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700139 ranges.AddBlock(0);
140 ranges.Dump();
141 ranges.AddBlock(1);
142 ranges.AddBlock(3);
Darin Petkov94817cb2013-05-08 14:33:24 +0200143
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700144 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200145 static const uint64_t expected[] = {0, 2, 3, 1};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700146 EXPECT_RANGE_EQ(ranges, expected);
147 }
148 ranges.AddBlock(2);
149 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200150 static const uint64_t expected[] = {0, 4};
151 EXPECT_RANGE_EQ(ranges, expected);
152 ranges.AddBlock(kSparseHole);
153 EXPECT_RANGE_EQ(ranges, expected);
154 ranges.SubtractBlock(kSparseHole);
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700155 EXPECT_RANGE_EQ(ranges, expected);
156 }
157 ranges.SubtractBlock(2);
158 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200159 static const uint64_t expected[] = {0, 2, 3, 1};
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700160 EXPECT_RANGE_EQ(ranges, expected);
161 }
162
163 for (uint64_t i = 100; i < 1000; i += 100) {
164 ranges.AddExtent(ExtentForRange(i, 50));
165 }
166 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200167 static const uint64_t expected[] = {
168 0, 2, 3, 1, 100, 50, 200, 50, 300, 50, 400, 50,
169 500, 50, 600, 50, 700, 50, 800, 50, 900, 50
170 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700171 EXPECT_RANGE_EQ(ranges, expected);
172 }
173
174 ranges.SubtractExtent(ExtentForRange(210, 410 - 210));
175 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200176 static const uint64_t expected[] = {
177 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50,
178 600, 50, 700, 50, 800, 50, 900, 50
179 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700180 EXPECT_RANGE_EQ(ranges, expected);
181 }
182 ranges.AddExtent(ExtentForRange(100000, 0));
183 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200184 static const uint64_t expected[] = {
185 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50,
186 600, 50, 700, 50, 800, 50, 900, 50
187 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700188 EXPECT_RANGE_EQ(ranges, expected);
189 }
190 ranges.SubtractExtent(ExtentForRange(3, 0));
191 {
Darin Petkov94817cb2013-05-08 14:33:24 +0200192 static const uint64_t expected[] = {
193 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50,
194 600, 50, 700, 50, 800, 50, 900, 50
195 };
Andrew de los Reyes5fdae4a2010-10-05 10:47:42 -0700196 EXPECT_RANGE_EQ(ranges, expected);
197 }
198}
199
200TEST(ExtentRangesTest, MultipleRanges) {
201 ExtentRanges ranges_a, ranges_b;
202 ranges_a.AddBlock(0);
203 ranges_b.AddBlock(4);
204 ranges_b.AddBlock(3);
205 {
206 uint64_t expected[] = {3, 2};
207 EXPECT_RANGE_EQ(ranges_b, expected);
208 }
209 ranges_a.AddRanges(ranges_b);
210 {
211 uint64_t expected[] = {0, 1, 3, 2};
212 EXPECT_RANGE_EQ(ranges_a, expected);
213 }
214 ranges_a.SubtractRanges(ranges_b);
215 {
216 uint64_t expected[] = {0, 1};
217 EXPECT_RANGE_EQ(ranges_a, expected);
218 }
219 {
220 uint64_t expected[] = {3, 2};
221 EXPECT_RANGE_EQ(ranges_b, expected);
222 }
223}
224
225TEST(ExtentRangesTest, GetExtentsForBlockCountTest) {
226 ExtentRanges ranges;
227 ranges.AddExtents(vector<Extent>(1, ExtentForRange(10, 30)));
228 {
229 vector<Extent> zero_extents = ranges.GetExtentsForBlockCount(0);
230 EXPECT_TRUE(zero_extents.empty());
231 }
232 ::google::protobuf::RepeatedPtrField<Extent> rep_field;
233 *rep_field.Add() = ExtentForRange(30, 40);
234 ranges.AddRepeatedExtents(rep_field);
235 ranges.SubtractExtents(vector<Extent>(1, ExtentForRange(20, 10)));
236 *rep_field.Mutable(0) = ExtentForRange(50, 10);
237 ranges.SubtractRepeatedExtents(rep_field);
238 EXPECT_EQ(40, ranges.blocks());
239
240 for (int i = 0; i < 2; i++) {
241 vector<Extent> expected(2);
242 expected[0] = ExtentForRange(10, 10);
243 expected[1] = ExtentForRange(30, i == 0 ? 10 : 20);
244 vector<Extent> actual =
245 ranges.GetExtentsForBlockCount(10 + expected[1].num_blocks());
246 EXPECT_EQ(expected.size(), actual.size());
247 for (vector<Extent>::size_type j = 0, e = expected.size(); j != e; ++j) {
248 EXPECT_EQ(expected[j].start_block(), actual[j].start_block())
249 << "j = " << j;
250 EXPECT_EQ(expected[j].num_blocks(), actual[j].num_blocks())
251 << "j = " << j;
252 }
253 }
254}
255
256} // namespace chromeos_update_engine