aboutsummaryrefslogtreecommitdiff
path: root/tests/core/mem/test_mem_dynamic_pool.odin
blob: 82cee89af05d215d649ab1e1cf988fd8e801b63a (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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package test_core_mem

import "core:testing"
import "core:mem"


expect_pool_allocation :: proc(t: ^testing.T, expected_used_bytes, num_bytes, alignment: int) {
	pool: mem.Dynamic_Pool
	mem.dynamic_pool_init(&pool, alignment = alignment)
	pool_allocator := mem.dynamic_pool_allocator(&pool)

	element, err := mem.alloc(num_bytes, alignment, pool_allocator)
	testing.expect(t, err == .None)
	testing.expect(t, element != nil)

	expected_bytes_left := pool.block_size - expected_used_bytes
	testing.expectf(t, pool.bytes_left == expected_bytes_left,
		`
		Allocated data with size %v bytes, expected %v bytes left, got %v bytes left, off by %v bytes.
		Pool:
		block_size = %v
		out_band_size = %v
		alignment = %v
		unused_blocks = %v
		used_blocks = %v
		out_band_allocations = %v
		current_block = %v
		current_pos = %v
		bytes_left = %v
		`,
		num_bytes, expected_bytes_left, pool.bytes_left, expected_bytes_left - pool.bytes_left,
		pool.block_size,
		pool.out_band_size,
		pool.alignment,
		pool.unused_blocks,
		pool.used_blocks,
		pool.out_band_allocations,
		pool.current_block,
		pool.current_pos,
		pool.bytes_left,
	)

	mem.dynamic_pool_destroy(&pool)
	testing.expect(t, pool.used_blocks == nil)
}

expect_pool_allocation_out_of_band :: proc(t: ^testing.T, num_bytes, block_size, out_band_size: int) {
	testing.expect(t, num_bytes >= out_band_size, "Sanity check failed, your test call is flawed! Make sure that num_bytes >= out_band_size!")

	pool: mem.Dynamic_Pool
	mem.dynamic_pool_init(&pool, block_size = block_size, out_band_size = out_band_size)
	pool_allocator := mem.dynamic_pool_allocator(&pool)

	element, err := mem.alloc(num_bytes, allocator = pool_allocator)
	testing.expect(t, err == .None)
	testing.expect(t, element != nil)
	testing.expectf(t, pool.out_band_allocations != nil,
		"Allocated data with size %v bytes, which is >= out_of_band_size and it should be in pool.out_band_allocations, but isn't!",
	)

	mem.dynamic_pool_destroy(&pool)
	testing.expect(t, pool.out_band_allocations == nil)
}

@(test)
test_dynamic_pool_alloc_aligned :: proc(t: ^testing.T) {
	expect_pool_allocation(t, expected_used_bytes = 16, num_bytes = 16, alignment=8)
}

@(test)
test_dynamic_pool_alloc_unaligned :: proc(t: ^testing.T) {
	expect_pool_allocation(t, expected_used_bytes = 8,  num_bytes = 1, alignment = 8)
	expect_pool_allocation(t, expected_used_bytes = 16, num_bytes = 9, alignment = 8)
}

@(test)
test_dynamic_pool_alloc_out_of_band :: proc(t: ^testing.T) {
	expect_pool_allocation_out_of_band(t, num_bytes = 128, block_size = 512, out_band_size = 128)
	expect_pool_allocation_out_of_band(t, num_bytes = 129, block_size = 512, out_band_size = 128)
	expect_pool_allocation_out_of_band(t, num_bytes = 513, block_size = 512, out_band_size = 128)
}

@(test)
test_intentional_leaks :: proc(t: ^testing.T) {
	testing.expect_leaks(t, intentionally_leaky_test, leak_verifier)
}

// Not tagged with @(test) because it's run through `test_intentional_leaks`
intentionally_leaky_test :: proc(t: ^testing.T) {
	a: [dynamic]int
	// Intentional leak
	append(&a, 42)

	// Intentional bad free
	b := uintptr(&a[0]) + 42
	free(rawptr(b))
}

leak_verifier :: proc(t: ^testing.T, ta: ^mem.Tracking_Allocator) {
	testing.expect_value(t, len(ta.allocation_map), 1)
	testing.expect_value(t, len(ta.bad_free_array), 1)
}