package test_core_mem import "core:mem" import "core:mem/tlsf" import "core:mem/virtual" import "core:testing" import "core:slice" @test test_tlsf_bitscan :: proc(t: ^testing.T) { Vector :: struct { op: enum{ffs, fls, fls_uint}, v: union{u32, uint}, exp: i32, } Tests := []Vector{ {.ffs, u32 (0x0000_0000_0000_0000), -1}, {.ffs, u32 (0x0000_0000_0000_0000), -1}, {.fls, u32 (0x0000_0000_0000_0000), -1}, {.ffs, u32 (0x0000_0000_0000_0001), 0}, {.fls, u32 (0x0000_0000_0000_0001), 0}, {.ffs, u32 (0x0000_0000_8000_0000), 31}, {.ffs, u32 (0x0000_0000_8000_8000), 15}, {.fls, u32 (0x0000_0000_8000_0008), 31}, {.fls, u32 (0x0000_0000_7FFF_FFFF), 30}, {.fls_uint, uint(0x0000_0000_8000_0000), 31}, {.fls_uint, uint(0x0000_0001_0000_0000), 32}, {.fls_uint, uint(0xffff_ffff_ffff_ffff), 63}, } for test in Tests { switch test.op { case .ffs: res := tlsf.ffs(test.v.?) testing.expectf(t, res == test.exp, "Expected tlsf.ffs(0x%08x) == %v, got %v", test.v, test.exp, res) case .fls: res := tlsf.fls(test.v.?) testing.expectf(t, res == test.exp, "Expected tlsf.fls(0x%08x) == %v, got %v", test.v, test.exp, res) case .fls_uint: res := tlsf.fls_uint(test.v.?) testing.expectf(t, res == test.exp, "Expected tlsf.fls_uint(0x%16x) == %v, got %v", test.v, test.exp, res) } } } @(test) test_align_bumping_block_limit :: proc(t: ^testing.T) { a: virtual.Arena defer virtual.arena_destroy(&a) data, err := virtual.arena_alloc(&a, 4193371, 1) testing.expect_value(t, err, nil) testing.expect(t, len(data) == 4193371) data, err = virtual.arena_alloc(&a, 896, 64) testing.expect_value(t, err, nil) testing.expect(t, len(data) == 896) } @(test) tlsf_test_overlap_and_zero :: proc(t: ^testing.T) { default_allocator := context.allocator alloc: tlsf.Allocator defer tlsf.destroy(&alloc) NUM_ALLOCATIONS :: 1_000 BACKING_SIZE :: NUM_ALLOCATIONS * (1_000 + size_of(uintptr)) if err := tlsf.init_from_allocator(&alloc, default_allocator, BACKING_SIZE); err != .None { testing.fail_now(t, "TLSF init error") } context.allocator = tlsf.allocator(&alloc) allocations := make([dynamic][]byte, 0, NUM_ALLOCATIONS, default_allocator) defer delete(allocations) err: mem.Allocator_Error s: []byte for size := 1; err == .None && size <= NUM_ALLOCATIONS; size += 1 { s, err = make([]byte, size) append(&allocations, s) } slice.sort_by(allocations[:], proc(a, b: []byte) -> bool { return uintptr(raw_data(a)) < uintptr(raw_data((b))) }) for i in 0.. bool { return uintptr(raw_data(a)) < uintptr(raw_data((b))) }) for i in 0..= 10) free_all(tlsf.allocator(&alloc)) for { s := make([]byte, ALLOCATION_SIZE) or_break append(&allocations[1], s) } testing.expect(t, len(allocations[1]) >= 10) for i in 0..= b_end && b_end >= a_start { 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..