aboutsummaryrefslogtreecommitdiff
path: root/memstack/test/memstack_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'memstack/test/memstack_test.c')
-rw-r--r--memstack/test/memstack_test.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/memstack/test/memstack_test.c b/memstack/test/memstack_test.c
new file mode 100644
index 0000000..2bcffcd
--- /dev/null
+++ b/memstack/test/memstack_test.c
@@ -0,0 +1,171 @@
1#include "memstack.h"
2
3#include "test.h"
4
5#define NUM_INTS 10
6#define CAPACITY (NUM_INTS * sizeof(int))
7
8// Create and destroy a statically-backed stack.
9TEST_CASE(memstack_create) {
10 int memory[CAPACITY];
11
12 memstack stack = {0};
13 memstack_make(&stack, CAPACITY, memory);
14 memstack_del(&stack);
15}
16
17// Create and destroy a dynamically-backed stack.
18TEST_CASE(memstack_create_dyn) {
19 memstack stack = {0};
20 memstack_make(&stack, CAPACITY, nullptr);
21 memstack_del(&stack);
22}
23
24// Clear an uninitialized stack.
25TEST_CASE(memstack_clear_uninitialized) {
26 memstack stack = {0};
27 memstack_clear(&stack);
28}
29
30// Allocate all N ints.
31TEST_CASE(memstack_allocate_until_full) {
32 memstack stack = {0};
33 memstack_make(&stack, CAPACITY, nullptr);
34
35 for (int i = 0; i < NUM_INTS; ++i) {
36 const int* block = memstack_alloc(&stack, sizeof(int));
37 TEST_TRUE(block != nullptr);
38 }
39
40 TEST_TRUE(memstack_size(&stack) == CAPACITY);
41
42 memstack_del(&stack);
43}
44
45// Allocate all N ints, then free them.
46TEST_CASE(memstack_fill_then_free) {
47 memstack stack = {0};
48 memstack_make(&stack, CAPACITY, nullptr);
49
50 int* blocks[NUM_INTS] = {nullptr};
51 for (int i = 0; i < NUM_INTS; ++i) {
52 blocks[i] = memstack_alloc(&stack, sizeof(int));
53 TEST_TRUE(blocks[i] != nullptr);
54 }
55
56 memstack_clear(&stack);
57
58 TEST_EQUAL(memstack_size(&stack), 0);
59
60 memstack_del(&stack);
61}
62
63// Attempt to allocate blocks past the maximum stack size.
64// The stack should handle the failed allocations gracefully.
65TEST_CASE(memstack_allocate_beyond_max_size) {
66 memstack stack = {0};
67 memstack_make(&stack, CAPACITY, nullptr);
68 memstack_enable_traps(&stack, false);
69
70 // Fully allocate the stack.
71 for (int i = 0; i < NUM_INTS; ++i) {
72 TEST_TRUE(memstack_alloc(&stack, sizeof(int)) != nullptr);
73 }
74
75 // Past the end.
76 for (int i = 0; i < NUM_INTS; ++i) {
77 TEST_EQUAL(memstack_alloc(&stack, sizeof(int)), nullptr);
78 }
79
80 TEST_TRUE(memstack_size(&stack) == CAPACITY);
81
82 memstack_del(&stack);
83}
84
85// Free blocks should always remain zeroed out.
86// This tests the invariant right after creating the stack.
87TEST_CASE(memstack_zero_free_blocks_after_creation) {
88 memstack stack = {0};
89 memstack_make(&stack, CAPACITY, nullptr);
90
91 for (int i = 0; i < NUM_INTS; ++i) {
92 const int* block = memstack_alloc(&stack, sizeof(int));
93 TEST_TRUE(block != nullptr);
94 TEST_EQUAL(*block, 0);
95 }
96
97 memstack_del(&stack);
98}
99
100// Free blocks should always remain zeroed out.
101// This tests the invariant after clearing the stack and allocating a new block.
102TEST_CASE(memstack_zero_free_block_after_free) {
103 memstack stack = {0};
104 memstack_make(&stack, CAPACITY, nullptr);
105
106 for (int i = 0; i < NUM_INTS; ++i) {
107 const int* block = memstack_alloc(&stack, sizeof(int));
108 TEST_TRUE(block != nullptr);
109 TEST_EQUAL(*block, 0);
110 }
111
112 memstack_clear(&stack);
113
114 for (int i = 0; i < NUM_INTS; ++i) {
115 const int* block = memstack_alloc(&stack, sizeof(int));
116 TEST_TRUE(block != nullptr);
117 TEST_EQUAL(*block, 0);
118 }
119
120 memstack_del(&stack);
121}
122
123// Aligned allocations should be properly aligned.
124TEST_CASE(memstack_alloc_aligned) {
125 memstack stack = {0};
126 memstack_make(&stack, CAPACITY, nullptr);
127
128 // -1 because the base address of the memory storage might be unaligned.
129 for (int i = 0; i < NUM_INTS - 1; ++i) {
130 const int* block =
131 memstack_alloc_aligned(&stack, sizeof(int), alignof(int));
132 TEST_TRUE(block != nullptr);
133 TEST_EQUAL(*block, 0);
134 TEST_EQUAL((uintptr_t)block % alignof(int), 0);
135 }
136
137 memstack_del(&stack);
138}
139
140// Get and set the watermark.
141TEST_CASE(memstack_watermark) {
142 memstack stack = {0};
143 memstack_make(&stack, CAPACITY, nullptr);
144
145 // Allocate N/2 ints.
146 for (int i = 0; i < NUM_INTS / 2; ++i) {
147 const int* block = memstack_alloc(&stack, sizeof(int));
148 TEST_TRUE(block != nullptr);
149 }
150
151 const size_t watermark = memstack_watermark(&stack);
152
153 // Allocate the remaining N/2 ints.
154 for (int i = 0; i < NUM_INTS / 2; ++i) {
155 const int* block = memstack_alloc(&stack, sizeof(int));
156 TEST_TRUE(block != nullptr);
157 }
158
159 // Now reset the watermark halfway through.
160 memstack_set_watermark(&stack, watermark);
161
162 // Allocate the remaining N/2 ints (again).
163 for (int i = 0; i < NUM_INTS / 2; ++i) {
164 const int* block = memstack_alloc(&stack, sizeof(int));
165 TEST_TRUE(block != nullptr);
166 }
167
168 memstack_del(&stack);
169}
170
171int main() { return 0; }