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
86
|
#ifndef SAND_UNIT_ALLOCATOR_UTILS_H
#define SAND_UNIT_ALLOCATOR_UTILS_H
// This module defines some tests for running against allocators.
#include "../core/allocator.h"
#include "greatest.h"
inline TEST test_allocator_basic_usage(SandAllocator *a) {
size_t count = 100;
int *ptr = sand_allocate(a, sizeof(int) * count);
ASSERT_NEQm("Small allocation should not fail", ptr, NULL);
// Unit tests are run under address sanitizer, so this should catch when
// returned memory isn't actually writable.
for (size_t i = 0; i < count; ++i) {
ptr[i] = 123;
}
// FIXME: I don't really know how to test this.
sand_deallocate(a, ptr, sizeof(int) * count);
PASS();
}
inline TEST test_allocator_reallocation(SandAllocator *a) {
size_t count = 50;
int *ptr = sand_allocate(a, sizeof(int) * count);
ASSERT_NEQm("Small allocation should not fail", ptr, NULL);
for (size_t i = 0; i < count; ++i) {
ptr[i] = 123;
}
size_t new_count = 100;
int *new_ptr = sand_reallocate(a, ptr, sizeof(int) * count, sizeof(int) * new_count);
ASSERT_NEQm("Small reallocation should not fail", new_ptr, NULL);
for (size_t i = 0; i < count; ++i) {
ASSERT_EQm("Reallocated memory is copied over", new_ptr[i], 123);
}
// Just like `test_std_allocator_basic_usage` this should
// ensure newly allocated memory is reallocated.
for (size_t i = count; i < new_count; ++i) {
new_ptr[i] = 456;
}
sand_deallocate(a, new_ptr, sizeof(int) * new_count);
PASS();
}
inline TEST test_allocator_weird_alignments(SandAllocator *a) {
size_t alignments[] = {2,4,8,16,32,64,128,256,1024};
for (unsigned i = 0; i < sizeof(alignments)/sizeof((alignments)[0]); ++i) {
int *allocation = sand_allocate_aligned(a, sizeof(*allocation), alignments[i]);
*allocation = 123; // ASAN will crash us if invalid memory is returned.
sand_deallocate(a, allocation, sizeof(*allocation));
}
PASS();
}
inline TEST test_allocator_unreasonably_large_allocation_fails_gracefully(SandAllocator *a) {
#if defined(__has_feature)
# if __has_feature(address_sanitizer)
SKIPm("Test does not work under address_sanitizer");
# endif
#endif
// Compute a request size which is very unlikely to be available.
// kibi mebi gibi tebi -byte
size_t size = (size_t)1024 * 1024 * 1024 * 1024;
void *result = sand_allocate(a, size);
ASSERT_EQm("Allocation should fail", result, NULL);
PASS();
}
#define RUN_ALLOCATOR_TESTS(DO) \
DO(test_allocator_basic_usage) \
DO(test_allocator_reallocation) \
DO(test_allocator_weird_alignments) \
DO(test_allocator_unreasonably_large_allocation_fails_gracefully)
#endif
|