mirror of
https://github.com/odin-lang/Odin.git
synced 2026-05-04 03:54:41 +00:00
Merge pull request #5344 from Feoramund/fix-2694
Review `core/mem/allocators.odin`
This commit is contained in:
@@ -193,3 +193,111 @@ fail_if_allocations_overlap :: proc(t: ^testing.T, a, b: []byte) {
|
||||
testing.fail_now(t, "Allocations overlapped")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This merely does a few simple operations to test basic sanity.
|
||||
//
|
||||
// A serious test of an allocator would require hooking it up to a benchmark or
|
||||
// a large, complicated program in order to get all manner of usage patterns.
|
||||
basic_sanity_test :: proc(t: ^testing.T, allocator: mem.Allocator, limit: int, loc := #caller_location) -> bool {
|
||||
context.allocator = allocator
|
||||
|
||||
{
|
||||
a := make([dynamic]u8)
|
||||
for i in 0..<limit {
|
||||
append(&a, u8(i))
|
||||
}
|
||||
testing.expect_value(t, len(a), limit, loc) or_return
|
||||
for i in 0..<limit {
|
||||
testing.expect_value(t, a[i], u8(i), loc) or_return
|
||||
}
|
||||
delete(a)
|
||||
}
|
||||
|
||||
{
|
||||
v := make([]u8, limit)
|
||||
testing.expect_value(t, len(v), limit, loc) or_return
|
||||
for i in 0..<limit {
|
||||
v[i] = u8(i)
|
||||
testing.expect_value(t, v[i], u8(i), loc) or_return
|
||||
}
|
||||
delete(v)
|
||||
}
|
||||
|
||||
{
|
||||
for i in 0..<limit {
|
||||
v := make([]u8, 1)
|
||||
v[0] = u8(i)
|
||||
testing.expect_value(t, v[0], u8(i), loc) or_return
|
||||
delete(v)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@test
|
||||
test_scratch :: proc(t: ^testing.T) {
|
||||
N :: 4096
|
||||
sa: mem.Scratch_Allocator
|
||||
mem.scratch_init(&sa, N)
|
||||
defer mem.scratch_destroy(&sa)
|
||||
basic_sanity_test(t, mem.scratch_allocator(&sa), N / 4)
|
||||
basic_sanity_test(t, mem.scratch_allocator(&sa), N / 4)
|
||||
}
|
||||
|
||||
@test
|
||||
test_stack :: proc(t: ^testing.T) {
|
||||
N :: 4096
|
||||
buf: [N]u8
|
||||
|
||||
sa: mem.Stack
|
||||
mem.stack_init(&sa, buf[:])
|
||||
basic_sanity_test(t, mem.stack_allocator(&sa), N / 4)
|
||||
basic_sanity_test(t, mem.stack_allocator(&sa), N / 4)
|
||||
}
|
||||
|
||||
@test
|
||||
test_small_stack :: proc(t: ^testing.T) {
|
||||
N :: 4096
|
||||
buf: [N]u8
|
||||
|
||||
ss: mem.Small_Stack
|
||||
mem.small_stack_init(&ss, buf[:])
|
||||
basic_sanity_test(t, mem.small_stack_allocator(&ss), N / 4)
|
||||
// The test cannot be run a second time on top of the last for a Small
|
||||
// Stack because the dynamic array inside will resize and leave a gap, thus
|
||||
// limiting the amount of space.
|
||||
basic_sanity_test(t, mem.small_stack_allocator(&ss), N / 8)
|
||||
}
|
||||
|
||||
@test
|
||||
test_dynamic_arena :: proc(t: ^testing.T) {
|
||||
da: mem.Dynamic_Arena
|
||||
mem.dynamic_arena_init(&da)
|
||||
defer mem.dynamic_arena_destroy(&da)
|
||||
basic_sanity_test(t, mem.dynamic_arena_allocator(&da), da.block_size / 4)
|
||||
basic_sanity_test(t, mem.dynamic_arena_allocator(&da), da.block_size / 4)
|
||||
}
|
||||
|
||||
@test
|
||||
test_buddy :: proc(t: ^testing.T) {
|
||||
N :: 4096
|
||||
buf: [N]u8
|
||||
|
||||
ba: mem.Buddy_Allocator
|
||||
mem.buddy_allocator_init(&ba, buf[:], align_of(u8))
|
||||
basic_sanity_test(t, mem.buddy_allocator(&ba), N / 8)
|
||||
basic_sanity_test(t, mem.buddy_allocator(&ba), N / 8)
|
||||
}
|
||||
|
||||
@test
|
||||
test_rollback :: proc(t: ^testing.T) {
|
||||
N :: 4096
|
||||
buf: [N]u8
|
||||
|
||||
rb: mem.Rollback_Stack
|
||||
mem.rollback_stack_init(&rb, buf[:])
|
||||
basic_sanity_test(t, mem.rollback_stack_allocator(&rb), N / 8)
|
||||
basic_sanity_test(t, mem.rollback_stack_allocator(&rb), N / 8)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style
|
||||
..\..\..\odin test ..\test_issue_2615.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_2637.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_2666.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_2694.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_4210.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_4364.odin %COMMON% || exit /b
|
||||
..\..\..\odin test ..\test_issue_4584.odin %COMMON% || exit /b
|
||||
|
||||
@@ -17,6 +17,7 @@ $ODIN test ../test_issue_2466.odin $COMMON
|
||||
$ODIN test ../test_issue_2615.odin $COMMON
|
||||
$ODIN test ../test_issue_2637.odin $COMMON
|
||||
$ODIN test ../test_issue_2666.odin $COMMON
|
||||
$ODIN test ../test_issue_2694.odin $COMMON
|
||||
$ODIN test ../test_issue_4210.odin $COMMON
|
||||
$ODIN test ../test_issue_4364.odin $COMMON
|
||||
$ODIN test ../test_issue_4584.odin $COMMON
|
||||
|
||||
42
tests/issues/test_issue_2694.odin
Normal file
42
tests/issues/test_issue_2694.odin
Normal file
@@ -0,0 +1,42 @@
|
||||
package test_issues
|
||||
|
||||
import "core:fmt"
|
||||
import "core:encoding/json"
|
||||
import "core:log"
|
||||
import "core:mem"
|
||||
import "core:testing"
|
||||
|
||||
// This is a minimal reproduction of the code in #2694.
|
||||
// It exemplifies the original problem as briefly as possible.
|
||||
|
||||
SAMPLE_JSON :: `
|
||||
{
|
||||
"foo": 0,
|
||||
"things": [
|
||||
{ "a": "ZZZZ"},
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
@test
|
||||
test_issue_2694 :: proc(t: ^testing.T) {
|
||||
into: struct {
|
||||
foo: int,
|
||||
things: []json.Object,
|
||||
}
|
||||
|
||||
scratch := new(mem.Scratch_Allocator)
|
||||
defer free(scratch)
|
||||
if mem.scratch_allocator_init(scratch, 4 * mem.Megabyte) != .None {
|
||||
log.error("unable to initialize scratch allocator")
|
||||
return
|
||||
}
|
||||
defer mem.scratch_allocator_destroy(scratch)
|
||||
|
||||
err := json.unmarshal_string(SAMPLE_JSON, &into, allocator = mem.scratch_allocator(scratch))
|
||||
testing.expect(t, err == nil)
|
||||
|
||||
output := fmt.tprintf("%v", into)
|
||||
expected := `{foo = 0, things = [map[a="ZZZZ"]]}`
|
||||
testing.expectf(t, output == expected, "\n\texpected: %q\n\tgot: %q", expected, output)
|
||||
}
|
||||
Reference in New Issue
Block a user