mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-28 18:30:06 +00:00
Allow testing for intentional leaks in test runner
Adds `expect_leak_or_bad_free :: proc(t: ^T, client_test: proc(t: ^T), verifier: Memory_Verifier_Proc)`. It sets up its own `Tracking_Allocator`, runs the `client_test`, and then calls the `verifier` procedure. The verifier can then inspect the contents of the tracking allocator and call `testing.expect*` as sensible for the test in question. Any allocations are then cleared so that the test runner doesn't itself complain about leaks. Additionally, `ODIN_TEST_LOG_LEVEL_MEMORY` has been added as a define to set the severity of the test runner's memory tracker. You can use `-define:ODIN_TEST_LOG_LEVEL_MEMORY=error` to make tests fail rather than warn if leaks or bad frees have been found.
This commit is contained in:
@@ -4,8 +4,10 @@ import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
import pkg_log "core:log"
|
||||
import "core:reflect"
|
||||
import "core:sync"
|
||||
import "core:sync/chan"
|
||||
import "core:time"
|
||||
import "core:mem"
|
||||
|
||||
_ :: reflect // alias reflect to nothing to force visibility for -vet
|
||||
|
||||
@@ -136,10 +138,28 @@ expect_value :: proc(t: ^T, value, expected: $T, loc := #caller_location) -> boo
|
||||
return ok
|
||||
}
|
||||
|
||||
Memory_Verifier_Proc :: #type proc(t: ^T, ta: ^mem.Tracking_Allocator)
|
||||
|
||||
expect_leaks :: proc(t: ^T, client_test: proc(t: ^T), verifier: Memory_Verifier_Proc) {
|
||||
{
|
||||
ta: mem.Tracking_Allocator
|
||||
mem.tracking_allocator_init(&ta, context.allocator)
|
||||
defer mem.tracking_allocator_destroy(&ta)
|
||||
context.allocator = mem.tracking_allocator(&ta)
|
||||
|
||||
client_test(t)
|
||||
sync.mutex_lock(&ta.mutex)
|
||||
// The verifier can inspect this local tracking allocator.
|
||||
// And then call `testing.expect_*` as makes sense for the client test.
|
||||
verifier(t, &ta)
|
||||
sync.mutex_unlock(&ta.mutex)
|
||||
}
|
||||
free_all(context.allocator)
|
||||
}
|
||||
|
||||
set_fail_timeout :: proc(t: ^T, duration: time.Duration, loc := #caller_location) {
|
||||
chan.send(t.channel, Event_Set_Fail_Timeout {
|
||||
at_time = time.time_add(time.now(), duration),
|
||||
location = loc,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user