extent_ranges_unittest.cc revision 1beda780333ce51d7872603b70712772eb2383fb
1// 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 "update_engine/payload_generator/extent_ranges.h" 6 7#include <vector> 8 9#include <gtest/gtest.h> 10 11#include "update_engine/payload_constants.h" 12#include "update_engine/payload_generator/extent_utils.h" 13#include "update_engine/test_utils.h" 14 15using std::vector; 16 17namespace chromeos_update_engine { 18 19class ExtentRangesTest : public ::testing::Test {}; 20 21namespace { 22void ExpectRangeEq(const ExtentRanges& ranges, 23 const uint64_t* expected, 24 size_t sz, 25 int line) { 26 uint64_t blocks = 0; 27 for (size_t i = 1; i < sz; i += 2) { 28 blocks += expected[i]; 29 } 30 EXPECT_EQ(blocks, ranges.blocks()) << "line: " << line; 31 32 const ExtentRanges::ExtentSet& result = ranges.extent_set(); 33 ExtentRanges::ExtentSet::const_iterator it = result.begin(); 34 for (size_t i = 0; i < sz; i += 2) { 35 EXPECT_FALSE(it == result.end()) << "line: " << line; 36 EXPECT_EQ(expected[i], it->start_block()) << "line: " << line; 37 EXPECT_EQ(expected[i + 1], it->num_blocks()) << "line: " << line; 38 ++it; 39 } 40} 41 42#define EXPECT_RANGE_EQ(ranges, var) \ 43 do { \ 44 ExpectRangeEq(ranges, var, arraysize(var), __LINE__); \ 45 } while (0) 46 47void ExpectRangesOverlapOrTouch(uint64_t a_start, uint64_t a_num, 48 uint64_t b_start, uint64_t b_num) { 49 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start, 50 a_num), 51 ExtentForRange(b_start, 52 b_num))); 53 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start, 54 b_num), 55 ExtentForRange(a_start, 56 a_num))); 57} 58 59void ExpectFalseRangesOverlapOrTouch(uint64_t a_start, uint64_t a_num, 60 uint64_t b_start, uint64_t b_num) { 61 EXPECT_FALSE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start, 62 a_num), 63 ExtentForRange(b_start, 64 b_num))); 65 EXPECT_FALSE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start, 66 b_num), 67 ExtentForRange(a_start, 68 a_num))); 69 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start, 70 a_num), 71 ExtentForRange(b_start, 72 b_num))); 73 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start, 74 b_num), 75 ExtentForRange(a_start, 76 a_num))); 77} 78 79void ExpectRangesOverlap(uint64_t a_start, uint64_t a_num, 80 uint64_t b_start, uint64_t b_num) { 81 EXPECT_TRUE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start, 82 a_num), 83 ExtentForRange(b_start, 84 b_num))); 85 EXPECT_TRUE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start, 86 b_num), 87 ExtentForRange(a_start, 88 a_num))); 89 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(a_start, 90 a_num), 91 ExtentForRange(b_start, 92 b_num))); 93 EXPECT_TRUE(ExtentRanges::ExtentsOverlapOrTouch(ExtentForRange(b_start, 94 b_num), 95 ExtentForRange(a_start, 96 a_num))); 97} 98 99void ExpectFalseRangesOverlap(uint64_t a_start, uint64_t a_num, 100 uint64_t b_start, uint64_t b_num) { 101 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(a_start, 102 a_num), 103 ExtentForRange(b_start, 104 b_num))); 105 EXPECT_FALSE(ExtentRanges::ExtentsOverlap(ExtentForRange(b_start, 106 b_num), 107 ExtentForRange(a_start, 108 a_num))); 109} 110 111} // namespace 112 113TEST(ExtentRangesTest, ExtentsOverlapTest) { 114 ExpectRangesOverlapOrTouch(10, 20, 30, 10); 115 ExpectRangesOverlap(10, 20, 25, 10); 116 ExpectFalseRangesOverlapOrTouch(10, 20, 35, 10); 117 ExpectFalseRangesOverlap(10, 20, 30, 10); 118 ExpectRangesOverlap(12, 4, 12, 3); 119 120 ExpectRangesOverlapOrTouch(kSparseHole, 2, kSparseHole, 3); 121 ExpectRangesOverlap(kSparseHole, 2, kSparseHole, 3); 122 ExpectFalseRangesOverlapOrTouch(kSparseHole, 2, 10, 3); 123 ExpectFalseRangesOverlapOrTouch(10, 2, kSparseHole, 3); 124 ExpectFalseRangesOverlap(kSparseHole, 2, 10, 3); 125 ExpectFalseRangesOverlap(10, 2, kSparseHole, 3); 126} 127 128TEST(ExtentRangesTest, SimpleTest) { 129 ExtentRanges ranges; 130 { 131 static const uint64_t expected[] = {}; 132 // Can't use arraysize() on 0-length arrays: 133 ExpectRangeEq(ranges, expected, 0, __LINE__); 134 } 135 ranges.SubtractBlock(2); 136 { 137 static const uint64_t expected[] = {}; 138 // Can't use arraysize() on 0-length arrays: 139 ExpectRangeEq(ranges, expected, 0, __LINE__); 140 } 141 142 ranges.AddBlock(0); 143 ranges.Dump(); 144 ranges.AddBlock(1); 145 ranges.AddBlock(3); 146 147 { 148 static const uint64_t expected[] = {0, 2, 3, 1}; 149 EXPECT_RANGE_EQ(ranges, expected); 150 } 151 ranges.AddBlock(2); 152 { 153 static const uint64_t expected[] = {0, 4}; 154 EXPECT_RANGE_EQ(ranges, expected); 155 ranges.AddBlock(kSparseHole); 156 EXPECT_RANGE_EQ(ranges, expected); 157 ranges.SubtractBlock(kSparseHole); 158 EXPECT_RANGE_EQ(ranges, expected); 159 } 160 ranges.SubtractBlock(2); 161 { 162 static const uint64_t expected[] = {0, 2, 3, 1}; 163 EXPECT_RANGE_EQ(ranges, expected); 164 } 165 166 for (uint64_t i = 100; i < 1000; i += 100) { 167 ranges.AddExtent(ExtentForRange(i, 50)); 168 } 169 { 170 static const uint64_t expected[] = { 171 0, 2, 3, 1, 100, 50, 200, 50, 300, 50, 400, 50, 172 500, 50, 600, 50, 700, 50, 800, 50, 900, 50 173 }; 174 EXPECT_RANGE_EQ(ranges, expected); 175 } 176 177 ranges.SubtractExtent(ExtentForRange(210, 410 - 210)); 178 { 179 static const uint64_t expected[] = { 180 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50, 181 600, 50, 700, 50, 800, 50, 900, 50 182 }; 183 EXPECT_RANGE_EQ(ranges, expected); 184 } 185 ranges.AddExtent(ExtentForRange(100000, 0)); 186 { 187 static const uint64_t expected[] = { 188 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50, 189 600, 50, 700, 50, 800, 50, 900, 50 190 }; 191 EXPECT_RANGE_EQ(ranges, expected); 192 } 193 ranges.SubtractExtent(ExtentForRange(3, 0)); 194 { 195 static const uint64_t expected[] = { 196 0, 2, 3, 1, 100, 50, 200, 10, 410, 40, 500, 50, 197 600, 50, 700, 50, 800, 50, 900, 50 198 }; 199 EXPECT_RANGE_EQ(ranges, expected); 200 } 201} 202 203TEST(ExtentRangesTest, MultipleRanges) { 204 ExtentRanges ranges_a, ranges_b; 205 ranges_a.AddBlock(0); 206 ranges_b.AddBlock(4); 207 ranges_b.AddBlock(3); 208 { 209 uint64_t expected[] = {3, 2}; 210 EXPECT_RANGE_EQ(ranges_b, expected); 211 } 212 ranges_a.AddRanges(ranges_b); 213 { 214 uint64_t expected[] = {0, 1, 3, 2}; 215 EXPECT_RANGE_EQ(ranges_a, expected); 216 } 217 ranges_a.SubtractRanges(ranges_b); 218 { 219 uint64_t expected[] = {0, 1}; 220 EXPECT_RANGE_EQ(ranges_a, expected); 221 } 222 { 223 uint64_t expected[] = {3, 2}; 224 EXPECT_RANGE_EQ(ranges_b, expected); 225 } 226} 227 228TEST(ExtentRangesTest, GetExtentsForBlockCountTest) { 229 ExtentRanges ranges; 230 ranges.AddExtents(vector<Extent>(1, ExtentForRange(10, 30))); 231 { 232 vector<Extent> zero_extents = ranges.GetExtentsForBlockCount(0); 233 EXPECT_TRUE(zero_extents.empty()); 234 } 235 ::google::protobuf::RepeatedPtrField<Extent> rep_field; 236 *rep_field.Add() = ExtentForRange(30, 40); 237 ranges.AddRepeatedExtents(rep_field); 238 ranges.SubtractExtents(vector<Extent>(1, ExtentForRange(20, 10))); 239 *rep_field.Mutable(0) = ExtentForRange(50, 10); 240 ranges.SubtractRepeatedExtents(rep_field); 241 EXPECT_EQ(40, ranges.blocks()); 242 243 for (int i = 0; i < 2; i++) { 244 vector<Extent> expected(2); 245 expected[0] = ExtentForRange(10, 10); 246 expected[1] = ExtentForRange(30, i == 0 ? 10 : 20); 247 vector<Extent> actual = 248 ranges.GetExtentsForBlockCount(10 + expected[1].num_blocks()); 249 EXPECT_EQ(expected.size(), actual.size()); 250 for (vector<Extent>::size_type j = 0, e = expected.size(); j != e; ++j) { 251 EXPECT_EQ(expected[j].start_block(), actual[j].start_block()) 252 << "j = " << j; 253 EXPECT_EQ(expected[j].num_blocks(), actual[j].num_blocks()) 254 << "j = " << j; 255 } 256 } 257} 258 259TEST(ExtentRangesTest, FilterExtentRangesEmptyRanges) { 260 ExtentRanges ranges; 261 EXPECT_EQ(vector<Extent>(), 262 FilterExtentRanges(vector<Extent>(), ranges)); 263 EXPECT_EQ( 264 vector<Extent>{ ExtentForRange(50, 10) }, 265 FilterExtentRanges(vector<Extent>{ ExtentForRange(50, 10) }, ranges)); 266 // Check that the empty Extents are ignored. 267 EXPECT_EQ( 268 (vector<Extent>{ ExtentForRange(10, 10), ExtentForRange(20, 10) }), 269 FilterExtentRanges(vector<Extent>{ 270 ExtentForRange(10, 10), 271 ExtentForRange(3, 0), 272 ExtentForRange(20, 10) }, ranges)); 273} 274 275TEST(ExtentRangesTest, FilterExtentRangesMultipleRanges) { 276 // Two overlaping extents, with three ranges to remove. 277 vector<Extent> extents { 278 ExtentForRange(10, 100), 279 ExtentForRange(30, 100) }; 280 ExtentRanges ranges; 281 // This overlaps the beginning of the second extent. 282 ranges.AddExtent(ExtentForRange(28, 3)); 283 ranges.AddExtent(ExtentForRange(50, 10)); 284 ranges.AddExtent(ExtentForRange(70, 10)); 285 // This overlaps the end of the second extent. 286 ranges.AddExtent(ExtentForRange(108, 6)); 287 EXPECT_EQ( 288 (vector<Extent>{ 289 // For the first extent: 290 ExtentForRange(10, 18), 291 ExtentForRange(31, 19), 292 ExtentForRange(60, 10), 293 ExtentForRange(80, 28), 294 // For the second extent: 295 ExtentForRange(31, 19), 296 ExtentForRange(60, 10), 297 ExtentForRange(80, 28), 298 ExtentForRange(114, 16)}), 299 FilterExtentRanges(extents, ranges)); 300} 301 302TEST(ExtentRangesTest, FilterExtentRangesOvelapping) { 303 ExtentRanges ranges; 304 ranges.AddExtent(ExtentForRange(10, 3)); 305 ranges.AddExtent(ExtentForRange(20, 5)); 306 // Requested extent overlaps with one of the ranges. 307 EXPECT_EQ(vector<Extent>(), 308 FilterExtentRanges(vector<Extent>{ 309 ExtentForRange(10, 1), 310 ExtentForRange(22, 1) }, 311 ranges)); 312} 313 314} // namespace chromeos_update_engine 315