blob: 9f6ba4c98280f055317a90ffe711e254afc99d77 [file] [log] [blame]
// Copyright 2021 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
#ifndef ZIRCON_KERNEL_PHYS_LIB_MEMALLOC_TEST_H_
#define ZIRCON_KERNEL_PHYS_LIB_MEMALLOC_TEST_H_
#include <lib/memalloc/pool.h>
#include <lib/memalloc/range.h>
#include <lib/stdcompat/span.h>
#include <stdio.h>
#include <algorithm>
#include <memory>
#include <random>
#include <sstream>
#include <string>
#include <vector>
#include <gtest/gtest.h>
#include "algorithm.h"
#include "ostream.h" // Enables Range auto-stringification in gtest error messages
//
// Shared test utilities.
//
// PoolContext holds both a Pool and the memory that backs its bookkeeping.
// To decouple memory ranges that are tracked from memory ranges that are
// actually used, we translate any nominal bookkeeping space to the heap.
struct PoolContext {
std::vector<std::unique_ptr<std::byte[]>> bookkeeping;
memalloc::Pool pool = memalloc::Pool([this](uint64_t addr, uint64_t size) {
bookkeeping.push_back(std::make_unique<std::byte[]>(size));
return bookkeeping.back().get();
});
};
inline std::string ToString(const memalloc::Range& range) {
std::stringstream ss;
ss << range;
return ss.str();
}
template <typename RangeIter>
inline std::string ToString(RangeIter first, RangeIter last) {
std::string s;
for (auto it = first; it != last; ++it) {
s += " " + ToString(*it) + "\n";
}
return s;
}
inline std::string ToString(const std::vector<const memalloc::Range>& ranges) {
return ToString(ranges.begin(), ranges.end());
}
inline std::string ToString(const cpp20::span<const memalloc::Range>& ranges) {
return ToString(ranges.begin(), ranges.end());
}
template <size_t N>
inline void Shuffle(memalloc::Range (&ranges)[N]) {
static std::default_random_engine engine{0xc0ffee};
std::shuffle(std::begin(ranges), std::end(ranges), engine);
}
inline void CompareRanges(cpp20::span<const memalloc::Range> expected,
cpp20::span<const memalloc::Range> actual) {
EXPECT_EQ(expected.size(), actual.size());
size_t num_comparable = std::min(expected.size(), actual.size());
for (size_t i = 0; i < num_comparable; ++i) {
EXPECT_EQ(expected[i], actual[i]);
}
if (expected.size() > num_comparable) {
printf("Unaccounted for expected ranges:\n%s",
ToString(expected.begin() + num_comparable, expected.end()).c_str());
}
if (actual.size() > num_comparable) {
printf("Unaccounted for actual ranges:\n%s",
ToString(actual.begin() + num_comparable, actual.end()).c_str());
}
}
inline cpp20::span<memalloc::Range> RangesFromBytes(const std::vector<std::byte>& bytes) {
void* ptr = const_cast<void*>(static_cast<const void*>(bytes.data()));
size_t space = bytes.size();
for (size_t size = space; size > 0; --size) {
if (void* aligned = std::align(alignof(memalloc::Range), size, ptr, space); aligned) {
return {static_cast<memalloc::Range*>(aligned), size / sizeof(memalloc::Range)};
}
}
return {};
}
#endif // ZIRCON_KERNEL_PHYS_LIB_MEMALLOC_TEST_H_