blob: 74d91eefd6ae749660969b61ad797001784f4787 [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/memalloc/range.h>
#include <lib/memalloc/testing/range.h>
#include <span>
#include <vector>
#include <gtest/gtest.h>
namespace {
using Range = memalloc::Range;
using Type = memalloc::Type;
constexpr uint64_t kChunkSize = 0x1000;
TEST(MemallocRangeTests, NormalizeRanges) {
constexpr Range kRanges[] = {
// RAM: [0, kChunkSize)
{
.addr = 0,
.size = kChunkSize,
.type = Type::kPoolBookkeeping,
},
// data ZBI: [kChunkSize, 2*kChunkSize)
{
.addr = kChunkSize,
.size = kChunkSize,
.type = Type::kDataZbi,
},
// test payload: [2*kChunkSize, 3*kChunkSize)
{
.addr = 2 * kChunkSize,
.size = kChunkSize,
.type = Type::kPoolTestPayload,
},
// peripheral: [3*kChunkSize, 4*kChunkSize)
{
.addr = 3 * kChunkSize,
.size = kChunkSize,
.type = Type::kPeripheral,
},
// test payload: [5*kChunkSize, 6*kChunkSize)
{
.addr = 5 * kChunkSize,
.size = kChunkSize,
.type = Type::kPoolTestPayload,
},
// phys kernel: [6*kChunkSize, 7*kChunkSize)
{
.addr = 6 * kChunkSize,
.size = kChunkSize,
.type = Type::kPhysKernel,
},
};
// Normalize away all ranges.
{
std::vector<Range> normalized;
memalloc::NormalizeRanges(
std::span{kRanges},
[&normalized](const Range& range) {
normalized.push_back(range);
return true;
},
[](Type) { return std::nullopt; });
EXPECT_TRUE(normalized.empty());
}
// Bail after the first range.
{
std::vector<Range> normalized;
memalloc::NormalizeRanges(
std::span{kRanges},
[&normalized](const Range& range) {
normalized.push_back(range);
return false;
},
[](Type type) { return type; });
EXPECT_EQ(1u, normalized.size());
}
// Normalize just RAM.
{
std::vector<Range> normalized;
memalloc::NormalizeRam(std::span{kRanges}, [&normalized](const Range& range) {
normalized.push_back(range);
return true;
});
constexpr Range kExpected[] = {
{
.addr = 0,
.size = 3 * kChunkSize,
.type = Type::kFreeRam,
},
{
.addr = 5 * kChunkSize,
.size = 2 * kChunkSize,
.type = Type::kFreeRam,
},
};
memalloc::testing::CompareRanges(std::span{kExpected}, {normalized});
}
// Discard RAM.
{
std::vector<Range> normalized;
memalloc::NormalizeRanges(
std::span{kRanges},
[&normalized](const Range& range) {
normalized.push_back(range);
return true;
},
[](Type type) {
return (IsAllocatedType(type) || type == Type::kFreeRam) ? std::nullopt
: std::make_optional(type);
});
constexpr Range kExpected[] = {
{
.addr = 3 * kChunkSize,
.size = kChunkSize,
.type = Type::kPeripheral,
},
};
memalloc::testing::CompareRanges(std::span{kExpected}, {normalized});
}
// Just keep pool test payloads and bookkeeping.
{
std::vector<Range> normalized;
memalloc::NormalizeRanges(
std::span{kRanges},
[&normalized](const Range& range) {
normalized.push_back(range);
return true;
},
[](Type type) {
return (type == Type::kPoolBookkeeping || type == Type::kPoolTestPayload)
? std::make_optional(type)
: std::nullopt;
});
constexpr Range kExpected[] = {
{
.addr = 0,
.size = kChunkSize,
.type = Type::kPoolBookkeeping,
},
{
.addr = 2 * kChunkSize,
.size = kChunkSize,
.type = Type::kPoolTestPayload,
},
{
.addr = 5 * kChunkSize,
.size = kChunkSize,
.type = Type::kPoolTestPayload,
},
};
memalloc::testing::CompareRanges(std::span{kExpected}, {normalized});
}
}
} // namespace