| Kelvin Zhang | d567c8b | 2021-07-08 14:10:23 -0400 | [diff] [blame] | 1 | // | 
|  | 2 | // Copyright (C) 2021 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 <gtest/gtest.h> | 
|  | 18 | #include <optional> | 
| Colin Cross | 26b82b1 | 2021-12-22 10:09:19 -0800 | [diff] [blame] | 19 | #include <vector> | 
| Kelvin Zhang | d567c8b | 2021-07-08 14:10:23 -0400 | [diff] [blame] | 20 |  | 
|  | 21 | #include "update_engine/payload_consumer/extent_map.h" | 
|  | 22 | #include "update_engine/payload_generator/extent_ranges.h" | 
| Kelvin Zhang | d567c8b | 2021-07-08 14:10:23 -0400 | [diff] [blame] | 23 |  | 
|  | 24 | namespace chromeos_update_engine { | 
|  | 25 |  | 
|  | 26 | class ExtentMapTest : public ::testing::Test { | 
|  | 27 | public: | 
|  | 28 | ExtentMap<int> map_; | 
|  | 29 | }; | 
|  | 30 |  | 
|  | 31 | TEST_F(ExtentMapTest, QueryExactExtent) { | 
|  | 32 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7)); | 
|  | 33 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 1)); | 
|  | 34 | auto ret = map_.Get(ExtentForRange(0, 5)); | 
|  | 35 | ASSERT_NE(ret, std::nullopt); | 
|  | 36 | ASSERT_EQ(*ret, 7); | 
|  | 37 | } | 
|  | 38 |  | 
|  | 39 | TEST_F(ExtentMapTest, QuerySubset) { | 
|  | 40 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7)); | 
|  | 41 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 1)); | 
|  | 42 | auto ret = map_.Get(ExtentForRange(1, 2)); | 
| Kelvin Zhang | cb9932f | 2023-01-20 15:39:33 -0800 | [diff] [blame] | 43 | ASSERT_EQ(ret, 7); | 
|  | 44 | } | 
|  | 45 |  | 
|  | 46 | TEST_F(ExtentMapTest, QueryNoMerge) { | 
|  | 47 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7)); | 
|  | 48 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(5, 5), 1)); | 
|  | 49 | auto ret = map_.Get(ExtentForRange(1, 2)); | 
|  | 50 | ASSERT_EQ(ret, 7); | 
|  | 51 | ret = map_.Get(ExtentForRange(0, 10)); | 
|  | 52 | ASSERT_EQ(ret, std::nullopt); | 
|  | 53 | ret = map_.Get(ExtentForRange(4, 3)); | 
| Kelvin Zhang | d567c8b | 2021-07-08 14:10:23 -0400 | [diff] [blame] | 54 | ASSERT_EQ(ret, std::nullopt); | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 | TEST_F(ExtentMapTest, QueryTouching) { | 
|  | 58 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7)); | 
|  | 59 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 1)); | 
|  | 60 | auto ret = map_.Get(ExtentForRange(3, 2)); | 
| Kelvin Zhang | cb9932f | 2023-01-20 15:39:33 -0800 | [diff] [blame] | 61 | ASSERT_EQ(ret, 7); | 
| Kelvin Zhang | d567c8b | 2021-07-08 14:10:23 -0400 | [diff] [blame] | 62 | ret = map_.Get(ExtentForRange(4, 1)); | 
| Kelvin Zhang | cb9932f | 2023-01-20 15:39:33 -0800 | [diff] [blame] | 63 | ASSERT_EQ(ret, 7); | 
| Kelvin Zhang | d567c8b | 2021-07-08 14:10:23 -0400 | [diff] [blame] | 64 | ret = map_.Get(ExtentForRange(5, 5)); | 
|  | 65 | ASSERT_EQ(ret, std::nullopt); | 
|  | 66 | ret = map_.Get(ExtentForRange(5, 6)); | 
|  | 67 | ASSERT_EQ(ret, std::nullopt); | 
|  | 68 | } | 
|  | 69 |  | 
|  | 70 | TEST_F(ExtentMapTest, GetIntersectingExtents) { | 
|  | 71 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7)); | 
|  | 72 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 7)); | 
|  | 73 | auto ret = std::vector<Extent>{}; | 
|  | 74 | ret = map_.GetIntersectingExtents(ExtentForRange(2, 10)); | 
|  | 75 | ASSERT_EQ(ret.size(), 2U); | 
|  | 76 | ASSERT_EQ(ret[0].start_block(), 2U); | 
|  | 77 | ASSERT_EQ(ret[0].num_blocks(), 3U); | 
|  | 78 |  | 
|  | 79 | ASSERT_EQ(ret[1].start_block(), 10U); | 
|  | 80 | ASSERT_EQ(ret[1].num_blocks(), 2U); | 
|  | 81 |  | 
|  | 82 | ret = map_.GetIntersectingExtents(ExtentForRange(2, 17)); | 
|  | 83 | ASSERT_EQ(ret.size(), 2U); | 
|  | 84 | ASSERT_EQ(ret[0].start_block(), 2U); | 
|  | 85 | ASSERT_EQ(ret[0].num_blocks(), 3U); | 
|  | 86 |  | 
|  | 87 | ASSERT_EQ(ret[1].start_block(), 10U); | 
|  | 88 | ASSERT_EQ(ret[1].num_blocks(), 5U); | 
|  | 89 |  | 
|  | 90 | ret = map_.GetIntersectingExtents(ExtentForRange(2, 2)); | 
|  | 91 | ASSERT_EQ(ret, std::vector<Extent>{ExtentForRange(2, 2)}); | 
|  | 92 |  | 
|  | 93 | ret = map_.GetIntersectingExtents(ExtentForRange(10, 5)); | 
|  | 94 | ASSERT_EQ(ret, std::vector<Extent>{ExtentForRange(10, 5)}); | 
|  | 95 |  | 
|  | 96 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(20, 5), 7)); | 
|  | 97 | ret = map_.GetIntersectingExtents(ExtentForRange(0, 30)); | 
|  | 98 | ASSERT_EQ(ret.size(), 3U); | 
|  | 99 | ASSERT_EQ(ret[0].start_block(), 0U); | 
|  | 100 | ASSERT_EQ(ret[0].num_blocks(), 5U); | 
|  | 101 |  | 
|  | 102 | ASSERT_EQ(ret[1].start_block(), 10U); | 
|  | 103 | ASSERT_EQ(ret[1].num_blocks(), 5U); | 
|  | 104 |  | 
|  | 105 | ASSERT_EQ(ret[2].start_block(), 20U); | 
|  | 106 | ASSERT_EQ(ret[2].num_blocks(), 5U); | 
|  | 107 | } | 
|  | 108 |  | 
|  | 109 | TEST_F(ExtentMapTest, GetNonIntersectingExtents) { | 
|  | 110 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7)); | 
|  | 111 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 7)); | 
|  | 112 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(20, 5), 7)); | 
|  | 113 |  | 
|  | 114 | auto ret = std::vector<Extent>{}; | 
|  | 115 | ret = map_.GetNonIntersectingExtents(ExtentForRange(2, 13)); | 
|  | 116 |  | 
|  | 117 | ASSERT_EQ(ret.size(), 1U); | 
|  | 118 | ASSERT_EQ(ret[0].start_block(), 5U); | 
|  | 119 | ASSERT_EQ(ret[0].num_blocks(), 5U); | 
|  | 120 |  | 
|  | 121 | ret = map_.GetNonIntersectingExtents(ExtentForRange(7, 20)); | 
|  | 122 | ASSERT_EQ(ret.size(), 3U); | 
|  | 123 | ASSERT_EQ(ret[0].start_block(), 7U); | 
|  | 124 | ASSERT_EQ(ret[0].num_blocks(), 3U); | 
|  | 125 |  | 
|  | 126 | ASSERT_EQ(ret[1].start_block(), 15U); | 
|  | 127 | ASSERT_EQ(ret[1].num_blocks(), 5U); | 
|  | 128 |  | 
|  | 129 | ASSERT_EQ(ret[2].start_block(), 25U); | 
|  | 130 | ASSERT_EQ(ret[2].num_blocks(), 2U); | 
|  | 131 | } | 
|  | 132 |  | 
| Kelvin Zhang | 9351f5d | 2021-08-17 19:29:49 -0700 | [diff] [blame] | 133 | TEST_F(ExtentMapTest, GetSameStartBlock) { | 
|  | 134 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7)); | 
|  | 135 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 12)); | 
|  | 136 |  | 
|  | 137 | const auto ret = map_.Get(ExtentForRange(0, 10)); | 
|  | 138 | // ASSERT_FALSE(ret.has_value()) << ret.value() won't work, because when |ret| | 
|  | 139 | // doesn't have value, the part after '<<' after still evaluated, resulting in | 
|  | 140 | // undefined behavior. | 
|  | 141 | if (ret.has_value()) { | 
|  | 142 | FAIL() << ret.value(); | 
|  | 143 | } | 
|  | 144 | } | 
|  | 145 |  | 
| Kelvin Zhang | bef99c3 | 2021-08-18 09:57:02 -0700 | [diff] [blame] | 146 | TEST_F(ExtentMapTest, GetTouchingExtents) { | 
|  | 147 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(5, 5), 7)); | 
|  | 148 | ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 12)); | 
|  | 149 | const auto ret = map_.Get(ExtentForRange(5, 10)); | 
|  | 150 | if (ret.has_value()) { | 
|  | 151 | ASSERT_FALSE(ret.has_value()) << ret.value(); | 
|  | 152 | } | 
|  | 153 | const auto extents = map_.GetIntersectingExtents(ExtentForRange(0, 20)); | 
|  | 154 | ASSERT_GT(extents.size(), 0UL); | 
|  | 155 | ASSERT_EQ(extents.size(), 2UL) | 
|  | 156 | << "Expecting unmerged extents [5-9] and [10-14], actual: " << extents; | 
|  | 157 | ASSERT_EQ(extents[0], ExtentForRange(5, 5)); | 
|  | 158 | ASSERT_EQ(extents[1], ExtentForRange(10, 5)); | 
|  | 159 | } | 
|  | 160 |  | 
| Kelvin Zhang | d567c8b | 2021-07-08 14:10:23 -0400 | [diff] [blame] | 161 | }  // namespace chromeos_update_engine |