152 lines
5.0 KiB
C++
152 lines
5.0 KiB
C++
//
|
|
// Copyright (C) 2021 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <optional>
|
|
#include <vector>
|
|
|
|
#include "update_engine/payload_consumer/extent_map.h"
|
|
#include "update_engine/payload_generator/extent_ranges.h"
|
|
#include "update_engine/payload_generator/extent_utils.h"
|
|
|
|
namespace chromeos_update_engine {
|
|
|
|
class ExtentMapTest : public ::testing::Test {
|
|
public:
|
|
ExtentMap<int> map_;
|
|
};
|
|
|
|
TEST_F(ExtentMapTest, QueryExactExtent) {
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7));
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 1));
|
|
auto ret = map_.Get(ExtentForRange(0, 5));
|
|
ASSERT_NE(ret, std::nullopt);
|
|
ASSERT_EQ(*ret, 7);
|
|
}
|
|
|
|
TEST_F(ExtentMapTest, QuerySubset) {
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7));
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 1));
|
|
auto ret = map_.Get(ExtentForRange(1, 2));
|
|
ASSERT_EQ(ret, std::nullopt);
|
|
}
|
|
|
|
TEST_F(ExtentMapTest, QueryTouching) {
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7));
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 1));
|
|
auto ret = map_.Get(ExtentForRange(3, 2));
|
|
ASSERT_EQ(ret, std::nullopt);
|
|
ret = map_.Get(ExtentForRange(4, 1));
|
|
ASSERT_EQ(ret, std::nullopt);
|
|
ret = map_.Get(ExtentForRange(5, 5));
|
|
ASSERT_EQ(ret, std::nullopt);
|
|
ret = map_.Get(ExtentForRange(5, 6));
|
|
ASSERT_EQ(ret, std::nullopt);
|
|
}
|
|
|
|
TEST_F(ExtentMapTest, GetIntersectingExtents) {
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7));
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 7));
|
|
auto ret = std::vector<Extent>{};
|
|
ret = map_.GetIntersectingExtents(ExtentForRange(2, 10));
|
|
ASSERT_EQ(ret.size(), 2U);
|
|
ASSERT_EQ(ret[0].start_block(), 2U);
|
|
ASSERT_EQ(ret[0].num_blocks(), 3U);
|
|
|
|
ASSERT_EQ(ret[1].start_block(), 10U);
|
|
ASSERT_EQ(ret[1].num_blocks(), 2U);
|
|
|
|
ret = map_.GetIntersectingExtents(ExtentForRange(2, 17));
|
|
ASSERT_EQ(ret.size(), 2U);
|
|
ASSERT_EQ(ret[0].start_block(), 2U);
|
|
ASSERT_EQ(ret[0].num_blocks(), 3U);
|
|
|
|
ASSERT_EQ(ret[1].start_block(), 10U);
|
|
ASSERT_EQ(ret[1].num_blocks(), 5U);
|
|
|
|
ret = map_.GetIntersectingExtents(ExtentForRange(2, 2));
|
|
ASSERT_EQ(ret, std::vector<Extent>{ExtentForRange(2, 2)});
|
|
|
|
ret = map_.GetIntersectingExtents(ExtentForRange(10, 5));
|
|
ASSERT_EQ(ret, std::vector<Extent>{ExtentForRange(10, 5)});
|
|
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(20, 5), 7));
|
|
ret = map_.GetIntersectingExtents(ExtentForRange(0, 30));
|
|
ASSERT_EQ(ret.size(), 3U);
|
|
ASSERT_EQ(ret[0].start_block(), 0U);
|
|
ASSERT_EQ(ret[0].num_blocks(), 5U);
|
|
|
|
ASSERT_EQ(ret[1].start_block(), 10U);
|
|
ASSERT_EQ(ret[1].num_blocks(), 5U);
|
|
|
|
ASSERT_EQ(ret[2].start_block(), 20U);
|
|
ASSERT_EQ(ret[2].num_blocks(), 5U);
|
|
}
|
|
|
|
TEST_F(ExtentMapTest, GetNonIntersectingExtents) {
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7));
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 7));
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(20, 5), 7));
|
|
|
|
auto ret = std::vector<Extent>{};
|
|
ret = map_.GetNonIntersectingExtents(ExtentForRange(2, 13));
|
|
|
|
ASSERT_EQ(ret.size(), 1U);
|
|
ASSERT_EQ(ret[0].start_block(), 5U);
|
|
ASSERT_EQ(ret[0].num_blocks(), 5U);
|
|
|
|
ret = map_.GetNonIntersectingExtents(ExtentForRange(7, 20));
|
|
ASSERT_EQ(ret.size(), 3U);
|
|
ASSERT_EQ(ret[0].start_block(), 7U);
|
|
ASSERT_EQ(ret[0].num_blocks(), 3U);
|
|
|
|
ASSERT_EQ(ret[1].start_block(), 15U);
|
|
ASSERT_EQ(ret[1].num_blocks(), 5U);
|
|
|
|
ASSERT_EQ(ret[2].start_block(), 25U);
|
|
ASSERT_EQ(ret[2].num_blocks(), 2U);
|
|
}
|
|
|
|
TEST_F(ExtentMapTest, GetSameStartBlock) {
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(0, 5), 7));
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 12));
|
|
|
|
const auto ret = map_.Get(ExtentForRange(0, 10));
|
|
// ASSERT_FALSE(ret.has_value()) << ret.value() won't work, because when |ret|
|
|
// doesn't have value, the part after '<<' after still evaluated, resulting in
|
|
// undefined behavior.
|
|
if (ret.has_value()) {
|
|
FAIL() << ret.value();
|
|
}
|
|
}
|
|
|
|
TEST_F(ExtentMapTest, GetTouchingExtents) {
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(5, 5), 7));
|
|
ASSERT_TRUE(map_.AddExtent(ExtentForRange(10, 5), 12));
|
|
const auto ret = map_.Get(ExtentForRange(5, 10));
|
|
if (ret.has_value()) {
|
|
ASSERT_FALSE(ret.has_value()) << ret.value();
|
|
}
|
|
const auto extents = map_.GetIntersectingExtents(ExtentForRange(0, 20));
|
|
ASSERT_GT(extents.size(), 0UL);
|
|
ASSERT_EQ(extents.size(), 2UL)
|
|
<< "Expecting unmerged extents [5-9] and [10-14], actual: " << extents;
|
|
ASSERT_EQ(extents[0], ExtentForRange(5, 5));
|
|
ASSERT_EQ(extents[1], ExtentForRange(10, 5));
|
|
}
|
|
|
|
} // namespace chromeos_update_engine
|