diff options
| author | gingerBill <bill@gingerbill.org> | 2021-03-14 18:01:31 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-03-14 18:01:31 +0000 |
| commit | 2aa588209e784274136b516224372fdd677d3e8f (patch) | |
| tree | d7fb6dd1051e34cd039cd49cc6895e4e58391afc /core/testing | |
| parent | 10f91a0d3f64902687683ac53dd286b25d3f7d5e (diff) | |
`odin test` to work with the new `core:testing` package
Diffstat (limited to 'core/testing')
| -rw-r--r-- | core/testing/runner.odin | 60 | ||||
| -rw-r--r-- | core/testing/testing.odin | 68 |
2 files changed, 128 insertions, 0 deletions
diff --git a/core/testing/runner.odin b/core/testing/runner.odin new file mode 100644 index 000000000..35f7afde1 --- /dev/null +++ b/core/testing/runner.odin @@ -0,0 +1,60 @@ +//+private +package testing + +import "core:io" +import "core:os" +import "core:strings" + +reset_t :: proc(t: ^T) { + clear(&t.cleanups); + t.error_count = 0; +} +end_t :: proc(t: ^T) { + for i := len(t.cleanups)-1; i >= 0; i -= 1 { + c := t.cleanups[i]; + c.procedure(c.user_data); + } +} + +runner :: proc(internal_tests: []Internal_Test) -> bool { + stream := os.stream_from_handle(os.stdout); + w, _ := io.to_writer(stream); + + t := &T{}; + t.w = w; + reserve(&t.cleanups, 1024); + defer delete(t.cleanups); + + total_success_count := 0; + total_test_count := len(internal_tests); + + for it in internal_tests { + if it.p == nil { + total_test_count -= 1; + continue; + } + + free_all(context.temp_allocator); + reset_t(t); + defer end_t(t); + + name := strings.trim_prefix(it.name, "test_"); + + logf(t, "[Test: %q]", name); + + // TODO(bill): Catch panics + { + it.p(t); + } + + if t.error_count != 0 { + logf(t, "[%q : FAILURE]", name); + } else { + logf(t, "[%q : SUCCESS]", name); + total_success_count += 1; + } + } + logf(t, "----------------------------------------"); + logf(t, "%d/%d SUCCESSFUL", total_success_count, total_test_count); + return total_success_count == total_test_count; +} diff --git a/core/testing/testing.odin b/core/testing/testing.odin new file mode 100644 index 000000000..d9d4a53a3 --- /dev/null +++ b/core/testing/testing.odin @@ -0,0 +1,68 @@ +package testing + +import "core:fmt" +import "core:io" + +Test_Signature :: proc(^T); + +Internal_Test :: struct { + name: string, + p: Test_Signature, +} + + +Internal_Cleanup :: struct { + procedure: proc(rawptr), + user_data: rawptr, +} + +T :: struct { + error_count: int, + + w: io.Writer, + + cleanups: [dynamic]Internal_Cleanup, +} + + +error :: proc(t: ^T, args: ..any, loc := #caller_location) { + log(t=t, args=args, loc=loc); + t.error_count += 1; +} + +errorf :: proc(t: ^T, format: string, args: ..any, loc := #caller_location) { + logf(t=t, format=format, args=args, loc=loc); + t.error_count += 1; +} + +fail :: proc(t: ^T) { + error(t, "FAIL"); + t.error_count += 1; +} + +failed :: proc(t: ^T) -> bool { + return t.error_count != 0; +} + +log :: proc(t: ^T, args: ..any, loc := #caller_location) { + fmt.wprintln(t.w, ..args); +} + +logf :: proc(t: ^T, format: string, args: ..any, loc := #caller_location) { + fmt.wprintf(t.w, format, ..args); + fmt.wprintln(t.w); +} + + +// cleanup registers a procedure and user_data, which will be called when the test, and all its subtests, complete +// cleanup proceduers will be called in LIFO (last added, first called) order. +cleanup :: proc(t: ^T, procedure: proc(rawptr), user_data: rawptr) { + append(&t.cleanups, Internal_Cleanup{procedure, user_data}); +} + +expect :: proc(t: ^T, ok: bool, msg: string = "", loc := #caller_location) -> bool { + if !ok { + error(t=t, args={msg}, loc=loc); + } + return ok; +} |