blob: 3de4333277269c8a83abad0a7757b07bc1ec97f1 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/trivial-allocator/page-allocator.h>
#include <lib/trivial-allocator/posix.h>
#include <unistd.h>
#ifdef __Fuchsia__
#include <lib/trivial-allocator/zircon.h>
#endif
#include <gtest/gtest.h>
namespace {
template <class Memory, typename... Args>
void PageAllocatorTest(Args&&... args) {
trivial_allocator::PageAllocator<Memory> allocator(std::forward<Args>(args)...);
auto& memory = allocator.memory();
static_assert(std::is_same_v<decltype(memory), Memory&>);
const size_t pagesize = memory.page_size();
const auto& const_allocator = allocator;
auto& const_memory = const_allocator.memory();
static_assert(std::is_same_v<decltype(const_memory), const Memory&>);
size_t size = 1;
auto allocation = allocator(size, 1);
EXPECT_TRUE(allocation);
EXPECT_EQ(pagesize, size);
int* iptr = reinterpret_cast<int*>(allocation.get());
EXPECT_EQ(0, *iptr);
*iptr = 17;
volatile int* vptr = iptr;
EXPECT_EQ(17, *vptr);
// Reset should unmap the page.
allocation.reset();
ASSERT_DEATH({ [[maybe_unused]] int i = *vptr; }, "");
allocation = allocator(size, 1);
EXPECT_TRUE(allocation);
iptr = reinterpret_cast<int*>(allocation.get());
int* release_iptr = reinterpret_cast<int*>(allocation.release());
EXPECT_EQ(iptr, release_iptr);
*iptr = 17;
// Reset after release should not unmap the page. (We leak it here.)
vptr = release_iptr;
allocation.reset();
EXPECT_EQ(17, *vptr);
*vptr = 23;
EXPECT_EQ(23, *release_iptr);
// Large and overaligned allocations are OK, though alignment is not met.
size = pagesize + 1;
allocation = allocator(size, pagesize * 2);
EXPECT_TRUE(allocation);
EXPECT_EQ(pagesize * 2, size);
iptr = reinterpret_cast<int*>(allocation.get());
EXPECT_EQ(0, *iptr);
*iptr = 23;
vptr = iptr;
// Make it read-only;
std::move(allocation).Seal();
EXPECT_EQ(23, *vptr);
ASSERT_DEATH({ *vptr = 17; }, "");
}
TEST(TrivialAllocatorDeathTest, PageAllocatorMmap) {
ASSERT_NO_FATAL_FAILURE(PageAllocatorTest<trivial_allocator::PosixMmap>());
}
#ifdef __Fuchsia__
TEST(TrivialAllocatorDeathTest, PageAllocatorVmar) {
ASSERT_NO_FATAL_FAILURE(PageAllocatorTest<trivial_allocator::ZirconVmar>(*zx::vmar::root_self()));
}
#endif
} // namespace