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