diff --git a/modules.yaml b/modules.yaml index f62ed8e..caa08dd 100644 --- a/modules.yaml +++ b/modules.yaml @@ -313,7 +313,6 @@ modules: deps: - kutil source: - - src/tests/address_manager.cpp - src/tests/constexpr_hash.cpp - src/tests/linked_list.cpp - src/tests/logger.cpp diff --git a/src/libraries/kutil/heap_allocator.cpp b/src/libraries/kutil/heap_allocator.cpp index 4c3ca3d..16fb3e2 100644 --- a/src/libraries/kutil/heap_allocator.cpp +++ b/src/libraries/kutil/heap_allocator.cpp @@ -77,8 +77,10 @@ heap_allocator::allocate(size_t length) if (length == 0) return nullptr; - const unsigned clz = __builtin_clzll(total); - const unsigned order = 64 - clz; + const unsigned clz = __builtin_clzll(total - 1); + unsigned order = 64 - clz; + if (order < min_order) + order = min_order; kassert(order <= max_order, "Tried to allocate a block bigger than max_order"); if (order > max_order) diff --git a/src/tests/heap_allocator.cpp b/src/tests/heap_allocator.cpp index e4e2cb7..b88e719 100644 --- a/src/tests/heap_allocator.cpp +++ b/src/tests/heap_allocator.cpp @@ -20,6 +20,10 @@ int signalled = 0; void *signalled_at = nullptr; void *mem_base = nullptr; +size_t mem_size = 4 * max_block; + +extern bool ASSERT_EXPECTED; +extern bool ASSERT_HAPPENED; std::vector sizes = { 16000, 8000, 4000, 4000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 150, @@ -27,9 +31,23 @@ std::vector sizes = { void segfault_handler(int signum, siginfo_t *info, void *ctxp) { - signalled += 1; + uintptr_t start = reinterpret_cast(mem_base); + uintptr_t end = start + mem_size; + uintptr_t addr = reinterpret_cast(info->si_addr); + + if (addr < start || addr >= end) { + CAPTURE( start ); + CAPTURE( end ); + CAPTURE( addr ); + FAIL("Segfaulted outside memory area"); + } + 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]" ) @@ -38,7 +56,7 @@ TEST_CASE( "Buddy blocks tests", "[memory buddy]" ) unsigned seed = clock::now().time_since_epoch().count(); 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 struct sigaction sigact; @@ -59,8 +77,14 @@ TEST_CASE( "Buddy blocks tests", "[memory buddy]" ) CHECK( 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. - void *p = mm.allocate(max_block - hs); + p = mm.allocate(max_block - hs); CHECK( p == offset_pointer(mem_base, hs) ); CHECK( signalled == 1 ); CHECK( signalled_at == mem_base ); diff --git a/src/tests/linked_list.cpp b/src/tests/linked_list.cpp index c93c196..83ccf45 100644 --- a/src/tests/linked_list.cpp +++ b/src/tests/linked_list.cpp @@ -115,7 +115,7 @@ ListContainsMatcher ListContains(const list_node &item) return ListContainsMatcher(item); } -TEST_CASE( "Linked list tests", "[containers list]" ) +TEST_CASE( "Linked list tests", "[containers] [list]" ) { linked_list ulist; @@ -144,7 +144,7 @@ TEST_CASE( "Linked list tests", "[containers list]" ) 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; unsigned seed = clock::now().time_since_epoch().count(); diff --git a/src/tests/main.cpp b/src/tests/main.cpp index 0c7c351..cb2d4e2 100644 --- a/src/tests/main.cpp +++ b/src/tests/main.cpp @@ -1,2 +1,29 @@ -#define CATCH_CONFIG_MAIN +#define CATCH_CONFIG_RUNNER #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); } +} diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..f9d8e53 --- /dev/null +++ b/test.sh @@ -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}" $*