aboutsummaryrefslogtreecommitdiff
path: root/kernel/src/memory/block_list_allocator.tests.cpp
blob: c5f84c5254eefac9f39177092aea8618ec83e3ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <kernel/memory/block_list_allocator.hpp>

#include <kernel/test_support/memory.hpp>

#include <kapi/memory.hpp>

#include <kstd/units>

#include <catch2/catch_test_macros.hpp>

#include <cstddef>

using namespace kstd::units_literals;

SCENARIO("Block List Allocator Operations", "[memory][allocator]")
{
  GIVEN("A newly initialized block list allocator mapped via the test sandbox")
  {
    kernel::tests::memory::deinit();
    kapi::memory::init();

    auto sandbox_base = kernel::tests::memory::virtual_base();
    kernel::memory::block_list_allocator allocator{sandbox_base};

    WHEN("a basic allocation request is made")
    {
      void * ptr = allocator.allocate(128_B, 8_B);

      THEN("a valid, non-null pointer is returned")
      {
        REQUIRE(ptr != nullptr);
      }

      AND_THEN("the returned memory is writeable without causing segmentation faults")
      {
        auto byte_ptr = static_cast<std::byte *>(ptr);
        byte_ptr[0] = std::byte{0xDE};
        byte_ptr[127] = std::byte{0xAD};
        REQUIRE(byte_ptr[0] == std::byte{0xDE});
        REQUIRE(byte_ptr[127] == std::byte{0xAD});
      }

      allocator.deallocate(ptr);
    }

    WHEN("multiple allocations are made sequentially")
    {
      void * ptr1 = allocator.allocate(64_B, 8_B);
      void * ptr2 = allocator.allocate(64_B, 8_B);
      void * ptr3 = allocator.allocate(1_KiB, 16_B);

      THEN("they return distinct, non-overlapping memory blocks")
      {
        REQUIRE(ptr1 != nullptr);
        REQUIRE(ptr2 != nullptr);
        REQUIRE(ptr3 != nullptr);
        REQUIRE(ptr1 != ptr2);
        REQUIRE(ptr2 != ptr3);
        REQUIRE(ptr1 != ptr3);
      }

      allocator.deallocate(ptr1);
      allocator.deallocate(ptr2);
      allocator.deallocate(ptr3);
    }

    WHEN("a block is allocated and then completely freed")
    {
      void * original_ptr = allocator.allocate(512_B, 16_B);
      allocator.deallocate(original_ptr);

      AND_WHEN("a new allocation of equal or smaller size is requested")
      {
        void * new_ptr = allocator.allocate(128_B, 16_B);

        THEN("the allocator actively reuses the coalesced space")
        {
          REQUIRE(new_ptr == original_ptr);
        }

        allocator.deallocate(new_ptr);
      }
    }
  }
}