[kutil] Fix failing heap allocator tests

The tests clearly haven't even been built in a while. I've added a
helper script to the project root. Also added a kassert() handler that
will allow tests to catch or fail on asserts.
This commit is contained in:
2020-09-07 16:56:07 -07:00
parent 8534d8d3c5
commit 8490472581
6 changed files with 72 additions and 10 deletions

View File

@@ -313,7 +313,6 @@ modules:
deps: deps:
- kutil - kutil
source: source:
- src/tests/address_manager.cpp
- src/tests/constexpr_hash.cpp - src/tests/constexpr_hash.cpp
- src/tests/linked_list.cpp - src/tests/linked_list.cpp
- src/tests/logger.cpp - src/tests/logger.cpp

View File

@@ -77,8 +77,10 @@ heap_allocator::allocate(size_t length)
if (length == 0) if (length == 0)
return nullptr; return nullptr;
const unsigned clz = __builtin_clzll(total); const unsigned clz = __builtin_clzll(total - 1);
const unsigned order = 64 - clz; unsigned order = 64 - clz;
if (order < min_order)
order = min_order;
kassert(order <= max_order, "Tried to allocate a block bigger than max_order"); kassert(order <= max_order, "Tried to allocate a block bigger than max_order");
if (order > max_order) if (order > max_order)

View File

@@ -20,6 +20,10 @@ int signalled = 0;
void *signalled_at = nullptr; void *signalled_at = nullptr;
void *mem_base = nullptr; void *mem_base = nullptr;
size_t mem_size = 4 * max_block;
extern bool ASSERT_EXPECTED;
extern bool ASSERT_HAPPENED;
std::vector<size_t> sizes = { std::vector<size_t> sizes = {
16000, 8000, 4000, 4000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 150, 16000, 8000, 4000, 4000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 150,
@@ -27,9 +31,23 @@ std::vector<size_t> sizes = {
void segfault_handler(int signum, siginfo_t *info, void *ctxp) void segfault_handler(int signum, siginfo_t *info, void *ctxp)
{ {
signalled += 1; uintptr_t start = reinterpret_cast<uintptr_t>(mem_base);
uintptr_t end = start + mem_size;
uintptr_t addr = reinterpret_cast<uintptr_t>(info->si_addr);
if (addr < start || addr >= end) {
CAPTURE( start );
CAPTURE( end );
CAPTURE( addr );
FAIL("Segfaulted outside memory area");
}
signalled_at = info->si_addr; signalled_at = info->si_addr;
mprotect(signalled_at, max_block, PROT_READ|PROT_WRITE); signalled += 1;
if (mprotect(signalled_at, max_block, PROT_READ|PROT_WRITE)) {
perror("mprotect");
exit(100);
}
} }
TEST_CASE( "Buddy blocks tests", "[memory buddy]" ) TEST_CASE( "Buddy blocks tests", "[memory buddy]" )
@@ -38,7 +56,7 @@ TEST_CASE( "Buddy blocks tests", "[memory buddy]" )
unsigned seed = clock::now().time_since_epoch().count(); unsigned seed = clock::now().time_since_epoch().count();
std::default_random_engine rng(seed); std::default_random_engine rng(seed);
mem_base = aligned_alloc(max_block, max_block * 4); mem_base = aligned_alloc(max_block, mem_size);
// Catch segfaults so we can track memory access // Catch segfaults so we can track memory access
struct sigaction sigact; struct sigaction sigact;
@@ -59,8 +77,14 @@ TEST_CASE( "Buddy blocks tests", "[memory buddy]" )
CHECK( signalled == 0 ); CHECK( signalled == 0 );
signalled = 0; signalled = 0;
// Allocating too much should assert
ASSERT_EXPECTED = true;
void *p = mm.allocate(max_block - hs + 1);
REQUIRE( ASSERT_HAPPENED );
ASSERT_HAPPENED = false;
// Allocating should signal just at the first page. // Allocating should signal just at the first page.
void *p = mm.allocate(max_block - hs); p = mm.allocate(max_block - hs);
CHECK( p == offset_pointer(mem_base, hs) ); CHECK( p == offset_pointer(mem_base, hs) );
CHECK( signalled == 1 ); CHECK( signalled == 1 );
CHECK( signalled_at == mem_base ); CHECK( signalled_at == mem_base );

View File

@@ -115,7 +115,7 @@ ListContainsMatcher<T> ListContains(const list_node<T> &item)
return ListContainsMatcher<T>(item); return ListContainsMatcher<T>(item);
} }
TEST_CASE( "Linked list tests", "[containers list]" ) TEST_CASE( "Linked list tests", "[containers] [list]" )
{ {
linked_list<unsortableT> ulist; linked_list<unsortableT> ulist;
@@ -144,7 +144,7 @@ TEST_CASE( "Linked list tests", "[containers list]" )
CHECK_THAT( ulist_reversed, !ListContains(removed) ); CHECK_THAT( ulist_reversed, !ListContains(removed) );
} }
TEST_CASE( "Sorted list tests", "[containers list]" ) TEST_CASE( "Sorted list tests", "[containers] [list]" )
{ {
using clock = std::chrono::system_clock; using clock = std::chrono::system_clock;
unsigned seed = clock::now().time_since_epoch().count(); unsigned seed = clock::now().time_since_epoch().count();

View File

@@ -1,2 +1,29 @@
#define CATCH_CONFIG_MAIN #define CATCH_CONFIG_RUNNER
#include "catch.hpp" #include "catch.hpp"
#include "kutil/assert.h"
bool ASSERT_EXPECTED = false;
bool ASSERT_HAPPENED = false;
void test_assert(const char *file, unsigned line, const char *message)
{
CAPTURE( file );
CAPTURE( line );
INFO( message );
REQUIRE( ASSERT_EXPECTED );
ASSERT_EXPECTED = false;
ASSERT_HAPPENED = true;
}
int main( int argc, char* argv[] ) {
kutil::assert_set_callback(test_assert);
int result = Catch::Session().run( argc, argv );
return result;
}
namespace kutil {
void * kalloc(size_t size) { return malloc(size); }
void kfree(void *p) { return free(p); }
}

10
test.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -o errexit
ROOT=$(realpath $(dirname $0))
BUILD="${ROOT}/build"
TESTS="${BUILD}/native/tests"
ninja -C "${BUILD}" "${TESTS}"
"${TESTS}" $*