WinTer 0.1.1
Windows Terminal Emulator
Loading...
Searching...
No Matches
test_memory.c
Go to the documentation of this file.
2#include "memory/mem_arena.h"
3
4#include "test_harness.h"
5
6TEST_CASE(arena_allocation)
7{
8 Arena a = arena_create(GB(1));
9 EXPECT(a.base != NULL);
10 EXPECT(a.cap == GB(1));
11 EXPECT(a.pos == 0);
12 EXPECT(a.cmt == 0);
13
14 // Push a single int. arena_push_zero aligns to ARENA_DEFAULT_ALIGN (8),
15 // so pos advances to sizeof(int) == 4, not 8 (alignment affects the
16 // *start* of the next allocation, not the current one).
17 int *num = PUSH_STRUCT(&a, int);
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.
24
25 // Push an array and verify zero-initialization.
26 int *arr = PUSH_ARRAY(&a, int, 10);
27 EXPECT(arr[0] == 0);
28 EXPECT(arr[9] == 0);
29
30 // pos was 4 after the int. Next alloc aligns up to 8, then adds 10*4=40 -> pos == 48.
31 EXPECT(a.pos == 48);
32
33 arena_clear(&a);
34 EXPECT(a.pos == 0); // pos resets; committed RAM stays mapped.
35
36 arena_release(&a);
37 EXPECT(a.base == NULL);
38 EXPECT(a.cap == 0);
39}
40
41TEST_CASE(arena_aligned_push)
42{
43 Arena a = arena_create(MB(1));
44 EXPECT(a.base != NULL);
45
46 // Bump pos to a non-aligned starting point by pushing 1 byte.
47 u8 *byte = (u8 *)arena_push(&a, 1);
48 EXPECT(byte != NULL);
49
50 // Push with 16-byte alignment (e.g., for SIMD).
51 float *simd = PUSH_ARRAY_ALIGNED(&a, float, 4, 16);
52 EXPECT(simd != NULL);
53 EXPECT(((usize)simd & 15) == 0); // pointer must be 16-byte aligned
54 EXPECT(simd[0] == 0.0f); // must be zeroed
55
56 arena_release(&a);
57}
58
59TEST_CASE(arena_temp)
60{
61 Arena a = arena_create(MB(1));
62 EXPECT(a.base != NULL);
63
64 int *persistent = PUSH_STRUCT(&a, int);
65 *persistent = 99;
66 usize pos_before = a.pos;
67
69
70 u8 *scratch = PUSH_ARRAY(&a, u8, 512);
71 EXPECT(scratch != NULL);
72 EXPECT(a.pos > pos_before);
73
74 arena_temp_end(tmp);
75 EXPECT(a.pos == pos_before); // must snap back
76 EXPECT(*persistent == 99); // persistent alloc survives
77
78 arena_release(&a);
79}
80
81TEST_CASE(arena_allocator_interface)
82{
83 Arena a = arena_create(MB(1));
84 Allocator ally = arena_allocator(&a);
85
86 int *val = (int *)allocator_alloc(&ally, sizeof(int));
87 EXPECT(val != NULL);
88 EXPECT(*val == 0); // zero-initialized
89 *val = 7;
90 EXPECT(*val == 7);
91
92 allocator_free(&ally, val, sizeof(int)); // no-op, must not crash
93
94 usize old_size = sizeof(int) * 4;
95 usize new_size = sizeof(int) * 8;
96 int *arr = (int *)allocator_alloc(&ally, old_size);
97 arr[0] = 1;
98 arr[3] = 4;
99
100 int *grown = (int *)allocator_realloc(&ally, arr, old_size, new_size);
101 EXPECT(grown != NULL);
102 EXPECT(grown[0] == 1); // old data copied
103 EXPECT(grown[3] == 4);
104 EXPECT(grown[4] == 0); // new bytes zeroed
105 EXPECT(grown[7] == 0);
106
107 arena_release(&a);
108}
INTERNAL void allocator_free(Allocator *a, void *ptr, usize size)
Frees a previously allocated block through the allocator.
INTERNAL void * allocator_realloc(Allocator *a, void *ptr, usize old_size, usize new_size)
Resizes a previously allocated block through the allocator.
INTERNAL Allocator arena_allocator(Arena *arena)
Constructs an Allocator interface backed by an existing Arena.
INTERNAL void * allocator_alloc(Allocator *a, usize size)
Allocates size zero-initialized bytes through the allocator.
Arena arena_create(usize reserve_size)
Creates and initializes a new arena, reserving virtual address space.
Definition mem_arena.c:60
void arena_release(Arena *arena)
Releases the entire arena back to the OS, invalidating all pointers into it.
Definition mem_arena.c:71
void arena_temp_end(ArenaTemp temp)
Restores the arena to the position saved in temp.
Definition mem_arena.c:132
#define PUSH_ARRAY(arena, type, count)
Allocates and zero-initializes an array of count elements on the arena.
Definition mem_arena.h:252
#define ARENA_COMMIT_SIZE
The granularity at which physical RAM is committed from the OS (64 KB).
Definition mem_arena.h:75
#define PUSH_STRUCT(arena, type)
Allocates and zero-initializes a single struct on the arena.
Definition mem_arena.h:237
#define PUSH_ARRAY_ALIGNED(arena, type, count, alignment)
Allocates a zero-initialized array with an explicit power-of-2 alignment.
Definition mem_arena.h:269
void arena_clear(Arena *arena)
Resets the arena to empty by setting pos back to 0.
Definition mem_arena.c:117
void * arena_push(Arena *arena, usize size)
Allocates size bytes from the arena, aligned to ARENA_DEFAULT_ALIGN.
Definition mem_arena.c:83
ArenaTemp arena_temp_begin(Arena *arena)
Saves the current arena position as a rewind checkpoint.
Definition mem_arena.c:123
uint8_t u8
Definition base_types.h:22
#define MB(x)
Definition base_types.h:84
#define GB(x)
Definition base_types.h:85
size_t usize
Definition base_types.h:43
Generic allocator interface (vtable) for polymorphic memory allocation.
High-performance Virtual Memory Linear (Arena) Allocator.
A generic allocator backed by function pointers (vtable).
Represents a linear memory arena backed by OS virtual memory.
Definition mem_arena.h:83
usize cap
Definition mem_arena.h:85
u8 * base
Definition mem_arena.h:84
usize pos
Definition mem_arena.h:86
usize cmt
Definition mem_arena.h:87
A saved checkpoint into an arena, used for scoped temporary allocations.
Definition mem_arena.h:105
A lightweight, dependency-free unit testing harness.
#define EXPECT(cond)
Evaluates a condition. If it fails, prints the file/line and increments the fail count.
#define TEST_CASE(name)
Defines a test case function.