compiler/
lib/
examples/
std/
arch/
char/
collections/
lang/
alloc/
tests.rad
5.0 KiB
ast/
gen/
il/
module/
parser/
resolver/
scanner/
alloc.rad
5.4 KiB
ast.rad
23.1 KiB
gen.rad
507 B
il.rad
15.3 KiB
lower.rad
271.6 KiB
module.rad
13.5 KiB
package.rad
1.2 KiB
parser.rad
78.7 KiB
resolver.rad
314.0 KiB
scanner.rad
17.4 KiB
sexpr.rad
6.3 KiB
strings.rad
2.2 KiB
types.rad
280 B
sys/
arch.rad
68 B
char.rad
855 B
collections.rad
39 B
fmt.rad
8.1 KiB
intrinsics.rad
683 B
io.rad
1.4 KiB
lang.rad
360 B
mem.rad
2.2 KiB
sys.rad
173 B
testing.rad
2.4 KiB
tests.rad
15.4 KiB
vec.rad
4.8 KiB
std.rad
358 B
scripts/
seed/
sublime/
test/
vim/
.gitignore
336 B
.gitsigners
112 B
LICENSE
1.1 KiB
Makefile
3.7 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.2 KiB
std.lib.test
373 B
lib/std/lang/alloc/tests.rad
raw
| 1 | //! Tests for the bump allocator. |
| 2 | |
| 3 | use std::testing; |
| 4 | |
| 5 | /// Test basic allocation. |
| 6 | @test fn testAllocBasic() throws (testing::TestError) { |
| 7 | static STORAGE: [u8; 64] = undefined; |
| 8 | let mut arena = super::new(&mut STORAGE[..]); |
| 9 | |
| 10 | let ptr = try! super::alloc(&mut arena, 4, 4); |
| 11 | try testing::expect(super::used(&arena) == 4); |
| 12 | try testing::expect(super::remaining(&arena) == 60); |
| 13 | } |
| 14 | |
| 15 | /// Test that allocations are properly aligned. |
| 16 | @test fn testAllocAlignment() throws (testing::TestError) { |
| 17 | static STORAGE: [u8; 64] = undefined; |
| 18 | let mut arena = super::new(&mut STORAGE[..]); |
| 19 | |
| 20 | // Allocate 1 byte with 1-byte alignment. |
| 21 | let p1 = try! super::alloc(&mut arena, 1, 1); |
| 22 | try testing::expect(super::used(&arena) == 1); |
| 23 | |
| 24 | // Allocate 4 bytes with 4-byte alignment - should pad to offset 4. |
| 25 | let p2 = try! super::alloc(&mut arena, 4, 4); |
| 26 | try testing::expect(super::used(&arena) == 8); // 1 + 3 padding + 4 |
| 27 | } |
| 28 | |
| 29 | /// Test multiple allocations. |
| 30 | @test fn testAllocMultiple() throws (testing::TestError) { |
| 31 | static STORAGE: [u8; 128] = undefined; |
| 32 | let mut arena = super::new(&mut STORAGE[..]); |
| 33 | |
| 34 | let p1 = try! super::alloc(&mut arena, 8, 4); |
| 35 | let p2 = try! super::alloc(&mut arena, 16, 4); |
| 36 | let p3 = try! super::alloc(&mut arena, 4, 4); |
| 37 | |
| 38 | try testing::expect(super::used(&arena) == 28); // 8 + 16 + 4 |
| 39 | } |
| 40 | |
| 41 | /// Test that arena throws when exhausted. |
| 42 | @test fn testAllocExhausted() throws (testing::TestError) { |
| 43 | static STORAGE: [u8; 16] = undefined; |
| 44 | let mut arena = super::new(&mut STORAGE[..]); |
| 45 | |
| 46 | // This should succeed. |
| 47 | let p1 = try! super::alloc(&mut arena, 8, 4); |
| 48 | |
| 49 | // This should also succeed. |
| 50 | let p2 = try! super::alloc(&mut arena, 8, 4); |
| 51 | |
| 52 | // Arena is now full, this should fail. |
| 53 | let mut failed = false; |
| 54 | try super::alloc(&mut arena, 1, 1) catch { |
| 55 | set failed = true; |
| 56 | }; |
| 57 | try testing::expect(failed); |
| 58 | } |
| 59 | |
| 60 | /// Test that reset allows reuse of memory. |
| 61 | @test fn testAllocReset() throws (testing::TestError) { |
| 62 | static STORAGE: [u8; 32] = undefined; |
| 63 | let mut arena = super::new(&mut STORAGE[..]); |
| 64 | |
| 65 | let p1 = try! super::alloc(&mut arena, 16, 4); |
| 66 | try testing::expect(super::used(&arena) == 16); |
| 67 | |
| 68 | super::reset(&mut arena); |
| 69 | try testing::expect(super::used(&arena) == 0); |
| 70 | try testing::expect(super::remaining(&arena) == 32); |
| 71 | |
| 72 | // Should be able to allocate again. |
| 73 | let p2 = try! super::alloc(&mut arena, 32, 4); |
| 74 | } |
| 75 | |
| 76 | /// Test alignment when offset is already aligned. |
| 77 | @test fn testAllocAlreadyAligned() throws (testing::TestError) { |
| 78 | static STORAGE: [u8; 64] = undefined; |
| 79 | let mut arena = super::new(&mut STORAGE[..]); |
| 80 | |
| 81 | // Allocate 4 bytes - offset becomes 4, already aligned for next 4-byte alloc. |
| 82 | let p1 = try! super::alloc(&mut arena, 4, 4); |
| 83 | try testing::expect(super::used(&arena) == 4); |
| 84 | |
| 85 | // Next 4-byte aligned allocation should not add padding. |
| 86 | let p2 = try! super::alloc(&mut arena, 4, 4); |
| 87 | try testing::expect(super::used(&arena) == 8); |
| 88 | } |
| 89 | |
| 90 | /// Test allocation that would overflow with alignment padding. |
| 91 | @test fn testAllocOverflowWithPadding() throws (testing::TestError) { |
| 92 | static STORAGE: [u8; 16] = undefined; |
| 93 | let mut arena = super::new(&mut STORAGE[..]); |
| 94 | |
| 95 | // Allocate 1 byte, offset is now 1. |
| 96 | let p1 = try! super::alloc(&mut arena, 1, 1); |
| 97 | |
| 98 | // Try to allocate 16 bytes with 4-byte alignment. |
| 99 | // Aligned offset would be 4, then 4 + 16 = 20 > 16, so should fail. |
| 100 | let mut failed = false; |
| 101 | try super::alloc(&mut arena, 16, 4) catch { |
| 102 | set failed = true; |
| 103 | }; |
| 104 | try testing::expect(failed); |
| 105 | } |
| 106 | |
| 107 | /// Test that a forged arena offset cannot wrap allocation arithmetic. |
| 108 | @test fn testAllocRejectsInvalidOffset() throws (testing::TestError) { |
| 109 | static STORAGE: [u8; 16] = undefined; |
| 110 | let mut arena = super::Arena { data: &mut STORAGE[..], offset: 0xFFFFFFFF }; |
| 111 | let mut failed = false; |
| 112 | |
| 113 | try super::alloc(&mut arena, 1, 1) catch { |
| 114 | set failed = true; |
| 115 | }; |
| 116 | |
| 117 | try testing::expect(failed); |
| 118 | try testing::expect(super::used(&arena) == 0xFFFFFFFF); |
| 119 | } |
| 120 | |
| 121 | /// Test that slice byte extents cannot overflow u32. |
| 122 | @test fn testAllocSliceExtentOverflow() throws (testing::TestError) { |
| 123 | static STORAGE: [u8; 16] = undefined; |
| 124 | let mut arena = super::new(&mut STORAGE[..]); |
| 125 | let count: u32 = 0xFFFFFFFF / 3 + 1; |
| 126 | let mut failed = false; |
| 127 | |
| 128 | try super::allocSlice(&mut arena, 3, 1, count) catch { |
| 129 | set failed = true; |
| 130 | }; |
| 131 | |
| 132 | try testing::expect(failed); |
| 133 | try testing::expect(super::used(&arena) == 0); |
| 134 | } |
| 135 | |
| 136 | /// Test the Allocator interface backed by an arena. |
| 137 | @test fn testAllocator() throws (testing::TestError) { |
| 138 | static STORAGE: [u8; 256] = undefined; |
| 139 | let mut arena = super::new(&mut STORAGE[..]); |
| 140 | let a = super::arenaAllocator(&mut arena); |
| 141 | |
| 142 | // Allocate through the Allocator indirection. |
| 143 | let p1 = a.func(a.ctx, 16, 4); |
| 144 | try testing::expect(super::used(&arena) == 16); |
| 145 | |
| 146 | let p2 = a.func(a.ctx, 8, 8); |
| 147 | try testing::expect(super::used(&arena) == 24); |
| 148 | |
| 149 | // Verify the pointers are distinct. |
| 150 | try testing::expect(p1 as u64 <> p2 as u64); |
| 151 | } |