diff --git a/cheat-sheet.md b/cheat-sheet.md new file mode 100644 index 0000000..e3bd10c --- /dev/null +++ b/cheat-sheet.md @@ -0,0 +1,19 @@ +# A simple cheat-sheet to provide a quick reference for the most common commands and operations. + +## Table of Contents + +### Code coverage + +To generate a code coverage report, run the following command: + +```shell +bazel coverage -c dbg --nocache_test_results --combined_report=lcov //... +``` + +To view the report + +```shell +genhtml --branch-coverage --output genhtml "$(bazel info output_path)/_coverage/_coverage_report.dat" +``` + +references [bazel.build/configure/coverage](https://bazel.build/configure/coverage) diff --git a/lib/runtime/BUILD.bazel b/lib/runtime/BUILD.bazel index eb84413..8732d84 100644 --- a/lib/runtime/BUILD.bazel +++ b/lib/runtime/BUILD.bazel @@ -26,7 +26,7 @@ cc_library( ) cc_test( - name = "tests", + name = "common_test", # This is a core library, it must be small and fast. size = "small", timeout = "short", @@ -36,7 +36,23 @@ cc_test( "tests/TypeDefs.cpp", ], linkstatic = True, - shard_count = 6, + deps = [ + ":runtime", + "@catch2//:catch2_main", + ], +) + +cc_test( + name = "allocator_test", + # This is a core library, it must be small and fast. + size = "small", + timeout = "short", + srcs = [ + "source/Memory/SlabAllocatorUtilities.h", + "tests/Allocators/BumpAllocator.cpp", + "tests/Allocators/SlabAllocatorUtilities.cpp", + ], + linkstatic = True, deps = [ ":runtime", "@catch2//:catch2_main", diff --git a/lib/runtime/tests/Allocators/BumpAllocator.cpp b/lib/runtime/tests/Allocators/BumpAllocator.cpp new file mode 100644 index 0000000..32f3aaa --- /dev/null +++ b/lib/runtime/tests/Allocators/BumpAllocator.cpp @@ -0,0 +1,102 @@ +#include + +#include + +TEST_CASE ("AllocatePages", "[BumpAllocator]") { + BUMP_ALLOCATOR allocator { }; + + RtlBumpAllocatorInitialize (&allocator); + + // Setup code + allocator.bumpers[0].heap_start = (UINTN) new UINT8[PAGE_SIZE_4K]; + allocator.bumpers[0].heap_end = allocator.bumpers[0].heap_start + PAGE_SIZE_4K; + allocator.bumpers[0].next = allocator.bumpers[0].heap_start; + + allocator.bumpers[1].heap_start = (UINTN) new UINT8[PAGE_SIZE_4K * 2]; + allocator.bumpers[1].heap_end = allocator.bumpers[1].heap_start + PAGE_SIZE_4K * 2; + allocator.bumpers[1].next = allocator.bumpers[1].heap_start; + + SECTION ("Allocates 4K page") { + VOID* address = NULL; + STATUS status = PA_ALLOCATE (&allocator, &address, 1, PAGE_SIZE_4K); + + REQUIRE (status == STATUS_SUCCESS); + REQUIRE (allocator.bumpers[0].next == allocator.bumpers[0].heap_end); + REQUIRE (address != NULL); + REQUIRE (address == (VOID*)allocator.bumpers[0].heap_start); + } + + SECTION ("Allocate multiple pages") { + VOID* address = NULL; + STATUS status = PA_ALLOCATE (&allocator, &address, 2, PAGE_SIZE_4K); + + REQUIRE (status == STATUS_SUCCESS); + REQUIRE (allocator.bumpers[1].next == allocator.bumpers[1].heap_end); + REQUIRE (address != NULL); + REQUIRE (address == (VOID*)allocator.bumpers[1].heap_start); + } + + SECTION ("Making sure we cannot over-allocate") { + VOID* address = NULL; + STATUS status = PA_ALLOCATE (&allocator, &address, PAGE_SIZE_4K, PAGE_SIZE_4K); + + REQUIRE (status == STATUS_OUT_OF_MEMORY); + REQUIRE (address == NULL); + } + + SECTION ("Try unaligned pages") { + VOID* address = NULL; + STATUS status = PA_ALLOCATE (&allocator, &address, 1, 1025); + + REQUIRE (status == STATUS_INVALID_ALIGNMENT); + REQUIRE (address == NULL); + } + + SECTION ("Make sure zero pages are not allocated") { + VOID* address = NULL; + STATUS status = PA_ALLOCATE (&allocator, &address, 0, PAGE_SIZE_4K); + + REQUIRE (status == STATUS_INVALID_PARAMETER); + REQUIRE (address == NULL); + } + + SECTION ("Make sure NULL Address is not allocated") { + STATUS status = PA_ALLOCATE (&allocator, NULL, 1, PAGE_SIZE_4K); + + REQUIRE (status == STATUS_INVALID_PARAMETER); + } + + SECTION ("Allocate multiple pages, multiple times") { + VOID* address = NULL; + STATUS status; + + // First allocation, this is guaranteed to succeed + status = PA_ALLOCATE (&allocator, &address, 1, PAGE_SIZE_4K); + + REQUIRE (status == STATUS_SUCCESS); + REQUIRE (address != NULL); + REQUIRE (address == (VOID*)allocator.bumpers[0].heap_start); + REQUIRE (allocator.bumpers[0].next == allocator.bumpers[0].heap_end); + + // Second allocation, this is also guaranteed, but we must be on the second bumper + status = PA_ALLOCATE (&allocator, &address, 1, PAGE_SIZE_4K); + + REQUIRE (status == STATUS_SUCCESS); + REQUIRE (address != NULL); + REQUIRE (address == (VOID*)allocator.bumpers[1].heap_start); + + // Same as above, but we should reach the end of the second bumper + status = PA_ALLOCATE (&allocator, &address, 1, PAGE_SIZE_4K); + + REQUIRE (status == STATUS_SUCCESS); + REQUIRE (address != NULL); + REQUIRE (address == (VOID*)(allocator.bumpers[1].heap_start + PAGE_SIZE_4K)); + REQUIRE (allocator.bumpers[1].next == allocator.bumpers[1].heap_end); + + // Third allocation, this should fail as we have no more bumpers available. + status = PA_ALLOCATE (&allocator, &address, 1, PAGE_SIZE_4K); + + REQUIRE (status == STATUS_OUT_OF_MEMORY); + REQUIRE (address == NULL); + } +} diff --git a/lib/runtime/tests/Allocators/SlabAllocatorUtilities.cpp b/lib/runtime/tests/Allocators/SlabAllocatorUtilities.cpp new file mode 100644 index 0000000..dac0fea --- /dev/null +++ b/lib/runtime/tests/Allocators/SlabAllocatorUtilities.cpp @@ -0,0 +1,3 @@ +#include + +#include diff --git a/lib/runtime/tests/Memory.cpp b/lib/runtime/tests/Memory.cpp index cf8163c..ee2a79a 100644 --- a/lib/runtime/tests/Memory.cpp +++ b/lib/runtime/tests/Memory.cpp @@ -121,102 +121,3 @@ TEST_CASE ("RtlCopyMemory", "[Memory]") { REQUIRE (status == STATUS_SUCCESS); } } - -TEST_CASE ("AllocatePages", "[BumpAllocator]") { - BUMP_ALLOCATOR allocator { }; - - RtlBumpAllocatorInitialize (&allocator); - - // Setup code - allocator.bumpers[0].heap_start = (UINTN) new UINT8[PAGE_SIZE_4K]; - allocator.bumpers[0].heap_end = allocator.bumpers[0].heap_start + PAGE_SIZE_4K; - allocator.bumpers[0].next = allocator.bumpers[0].heap_start; - - allocator.bumpers[1].heap_start = (UINTN) new UINT8[PAGE_SIZE_4K * 2]; - allocator.bumpers[1].heap_end = allocator.bumpers[1].heap_start + PAGE_SIZE_4K * 2; - allocator.bumpers[1].next = allocator.bumpers[1].heap_start; - - SECTION ("Allocates 4K page") { - VOID* address = NULL; - STATUS status = PA_ALLOCATE (&allocator, &address, 1, PAGE_SIZE_4K); - - REQUIRE (status == STATUS_SUCCESS); - REQUIRE (allocator.bumpers[0].next == allocator.bumpers[0].heap_end); - REQUIRE (address != NULL); - REQUIRE (address == (VOID*)allocator.bumpers[0].heap_start); - } - - SECTION ("Allocate multiple pages") { - VOID* address = NULL; - STATUS status = PA_ALLOCATE (&allocator, &address, 2, PAGE_SIZE_4K); - - REQUIRE (status == STATUS_SUCCESS); - REQUIRE (allocator.bumpers[1].next == allocator.bumpers[1].heap_end); - REQUIRE (address != NULL); - REQUIRE (address == (VOID*)allocator.bumpers[1].heap_start); - } - - SECTION ("Making sure we cannot over-allocate") { - VOID* address = NULL; - STATUS status = PA_ALLOCATE (&allocator, &address, PAGE_SIZE_4K, PAGE_SIZE_4K); - - REQUIRE (status == STATUS_OUT_OF_MEMORY); - REQUIRE (address == NULL); - } - - SECTION ("Try unaligned pages") { - VOID* address = NULL; - STATUS status = PA_ALLOCATE (&allocator, &address, 1, 1025); - - REQUIRE (status == STATUS_INVALID_ALIGNMENT); - REQUIRE (address == NULL); - } - - SECTION ("Make sure zero pages are not allocated") { - VOID* address = NULL; - STATUS status = PA_ALLOCATE (&allocator, &address, 0, PAGE_SIZE_4K); - - REQUIRE (status == STATUS_INVALID_PARAMETER); - REQUIRE (address == NULL); - } - - SECTION ("Make sure NULL Address is not allocated") { - STATUS status = PA_ALLOCATE (&allocator, NULL, 1, PAGE_SIZE_4K); - - REQUIRE (status == STATUS_INVALID_PARAMETER); - } - - SECTION ("Allocate multiple pages, multiple times") { - VOID* address = NULL; - STATUS status; - - // First allocation, this is guaranteed to succeed - status = PA_ALLOCATE (&allocator, &address, 1, PAGE_SIZE_4K); - - REQUIRE (status == STATUS_SUCCESS); - REQUIRE (address != NULL); - REQUIRE (address == (VOID*)allocator.bumpers[0].heap_start); - REQUIRE (allocator.bumpers[0].next == allocator.bumpers[0].heap_end); - - // Second allocation, this is also guaranteed, but we must be on the second bumper - status = PA_ALLOCATE (&allocator, &address, 1, PAGE_SIZE_4K); - - REQUIRE (status == STATUS_SUCCESS); - REQUIRE (address != NULL); - REQUIRE (address == (VOID*)allocator.bumpers[1].heap_start); - - // Same as above, but we should reach the end of the second bumper - status = PA_ALLOCATE (&allocator, &address, 1, PAGE_SIZE_4K); - - REQUIRE (status == STATUS_SUCCESS); - REQUIRE (address != NULL); - REQUIRE (address == (VOID*)(allocator.bumpers[1].heap_start + PAGE_SIZE_4K)); - REQUIRE (allocator.bumpers[1].next == allocator.bumpers[1].heap_end); - - // Third allocation, this should fail as we have no more bumpers available. - status = PA_ALLOCATE (&allocator, &address, 1, PAGE_SIZE_4K); - - REQUIRE (status == STATUS_OUT_OF_MEMORY); - REQUIRE (address == NULL); - } -}