cbase 1.50.0
C/C++ Static Template
Loading...
Searching...
No Matches
test_memory.c
2#include "memory/mem_arena.h"
3#include "test/test.h"
4
5TEST_CASE(mem_arena_allocation)
6{
8 EXPECT_FATAL(a.base != NULL);
9 EXPECT(a.reserve == GB(1));
10 EXPECT(a.pos == 0);
11 EXPECT(a.commit == 0);
12
13 // Push a single int. The allocator aligns the *start* of this allocation
14 // to MEM_ARENA_ALIGNMENT (8), but pos only advances by sizeof(int) == 4
15 // bytes of actual data. So pos == 4, not 8.
16 int *num = PUSH_STRUCT(&a, int);
17 EXPECT_FATAL(num != NULL);
18 *num = 42;
19 EXPECT(a.pos == 4);
20 EXPECT(*num == 42);
21
22 // Physical RAM should now be committed in at least one 64 KB chunk.
23 EXPECT(a.commit >= KB(64));
24
25 // Push an array and verify zero-initialization.
26 int *arr = PUSH_ARRAY(&a, int, 10);
27 EXPECT_FATAL(arr != NULL);
28 EXPECT(arr[0] == 0);
29 EXPECT(arr[9] == 0);
30
31 // pos was 4 after the int. Next alloc aligns up to 8, then adds 10*4=40 -> pos == 48.
32 EXPECT(a.pos == 48);
33
35 EXPECT(a.pos == 0); // pos resets; committed RAM stays mapped.
36
38 EXPECT(a.base == NULL);
39 EXPECT(a.reserve == 0);
40}
41
42TEST_CASE(mem_arena_aligned_push)
43{
45 EXPECT_FATAL(a.base != NULL);
46
47 // Bump pos to a non-aligned starting point by pushing 1 byte.
48 u8 *byte = (u8 *)mem_arena_push(&a, 1);
49 EXPECT_FATAL(byte != NULL);
50
51 // Push with 16-byte alignment (e.g., for SIMD).
52 float *simd = PUSH_ARRAY_ALIGNED(&a, float, 4, 16);
53 EXPECT_FATAL(simd != NULL);
54 EXPECT(((usize)simd & 15) == 0); // pointer must be 16-byte aligned
55 EXPECT(simd[0] == 0.0f); // must be zeroed
56
58}
59
60TEST_CASE(mem_arena_temp)
61{
63 EXPECT_FATAL(a.base != NULL);
64
65 int *persistent = PUSH_STRUCT(&a, int);
66 EXPECT_FATAL(persistent != NULL);
67 *persistent = 99;
68 usize pos_before = a.pos;
69
71
72 u8 *scratch = PUSH_ARRAY(&a, u8, 512);
73 EXPECT_FATAL(scratch != NULL);
74 EXPECT(a.pos > pos_before);
75
77 EXPECT(a.pos == pos_before); // must snap back
78 EXPECT(*persistent == 99); // persistent alloc survives
79
81}
82
83TEST_CASE(mem_arena_allocator_interface)
84{
87
88 int *val = (int *)mem_alloc(&ally, sizeof(int));
89 EXPECT_FATAL(val != NULL);
90 EXPECT(*val == 0); // zero-initialized
91 *val = 7;
92 EXPECT(*val == 7);
93
94 mem_free(&ally, val, sizeof(int)); // no-op, must not crash
95
96 usize old_size = sizeof(int) * 4;
97 usize new_size = sizeof(int) * 8;
98 int *old_arr = (int *)mem_alloc(&ally, old_size);
99 EXPECT_FATAL(old_arr != NULL);
100 old_arr[0] = 1;
101 old_arr[3] = 4;
102
103 int *grown = (int *)mem_realloc(&ally, old_arr, old_size, new_size);
104 EXPECT_FATAL(grown != NULL);
105 EXPECT(grown != old_arr); // arena realloc must always return a new pointer
106 EXPECT(grown[0] == 1); // old data copied
107 EXPECT(grown[3] == 4);
108 EXPECT(grown[4] == 0); // new bytes zeroed
109 EXPECT(grown[7] == 0);
110
112}
uint8_t u8
Definition base_types.h:46
function void mem_free(MemAllocator *alloc, void *ptr, usize size)
Frees a previously allocated block through the allocator.
function void * mem_alloc(MemAllocator *alloc, usize size)
Allocator Helper Functions.
function void * mem_realloc(MemAllocator *alloc, void *old_ptr, usize old_size, usize new_size)
Resizes a previously allocated block through the allocator.
void mem_arena_clear(MemArena *arena)
Resets the arena pointer to zero, freeing all allocations in O(1).
Definition mem_arena.c:105
void mem_arena_temp_end(MemArenaTemp temp)
Restores the arena to the position saved in temp.
Definition mem_arena.c:141
void mem_arena_release(MemArena *arena)
Returns all virtual memory back to the operating system.
Definition mem_arena.c:59
#define PUSH_ARRAY(arena, type, count)
Pushes an array of structs of type T onto the arena.
Definition mem_arena.h:343
void * mem_arena_push(MemArena *arena, usize size)
Allocates bytes sequentially on the arena without zeroing.
Definition mem_arena.c:71
#define PUSH_STRUCT(arena, type)
Type-Safe Allocation Macros.
Definition mem_arena.h:331
#define PUSH_ARRAY_ALIGNED(arena, type, count, alignment)
Pushes an array of structs with custom memory alignment.
Definition mem_arena.h:366
struct MemAllocator mem_arena_allocator(MemArena *arena)
Wraps a MemArena in the generic MemAllocator interface.
Definition mem_arena.c:172
MemArenaTemp mem_arena_temp_begin(MemArena *arena)
Temporary Memory API.
Definition mem_arena.c:132
MemArena mem_arena_create(usize reserve_size)
Initializes a new virtual memory Arena.
Definition mem_arena.c:48
#define MB(x)
Definition base_types.h:120
#define KB(x)
Definition base_types.h:119
#define GB(x)
Definition base_types.h:121
size_t usize
Definition base_types.h:68
Generic interface for abstracting memory allocators.
High-performance virtual memory Arena Allocator.
An abstract allocator interface.
A virtual memory-backed linear allocator.
Definition mem_arena.h:70
usize reserve
Definition mem_arena.h:74
usize commit
Definition mem_arena.h:73
u8 * base
Definition mem_arena.h:71
usize pos
Definition mem_arena.h:72
A temporary snapshot of an arena's state.
Definition mem_arena.h:78
Single-header testing framework with pretty-printed output.
#define EXPECT(cond)
Evaluates a condition. Records and counts the failure if false.
Definition test.h:161
#define TEST_CASE(name)
Declares a test case function.
Definition test.h:205
#define EXPECT_FATAL(cond)
Like EXPECT but aborts immediately on failure.
Definition test.h:175