126 lines
4.1 KiB
V
126 lines
4.1 KiB
V
[has_globals]
|
|
module main
|
|
|
|
__global test_runner TestRunner
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// This file will be compiled as part of the main program, for a _test.v file.
|
|
// The methods defined here are called back by the test program's assert
|
|
// statements, on each success/fail. The goal is to make customizing the look &
|
|
// feel of the assertions results easier, since it is done in normal V code.
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
interface TestRunner {
|
|
mut:
|
|
file_test_info VTestFileMetaInfo // filled in by generated code, before .start() is called.
|
|
fn_test_info VTestFnMetaInfo // filled in by generated code, before .fn_start() is called.
|
|
fn_assert_passes u64 // reset this to 0 in .fn_start(), increase it in .assert_pass()
|
|
fn_passes u64 // increase this in .fn_pass()
|
|
fn_fails u64 // increase this in .fn_fails()
|
|
total_assert_passes u64 // increase this in .assert_pass()
|
|
total_assert_fails u64 // increase this in .assert_fail()
|
|
start(ntests int) // called before all tests, you can initialise private data here. ntests is the number of test functions in the _test.v file.
|
|
finish() // called after all tests are finished, you can print some stats if you want here.
|
|
exit_code() int // called right after finish(), it should return the exit code, that the test program will exit with.
|
|
//
|
|
fn_start() bool // called before the start of each test_ function. Return false, if the function should be skipped.
|
|
fn_pass() // called after the end of each test_ function, with NO failed assertion.
|
|
fn_fail() // called after the end of each test_ function, with a failed assertion, *or* returning an error.
|
|
fn_error(line_nr int, file string, mod string, fn_name string, errmsg string) // called only for `fn test_xyz() ? { return error('message') }`, before .fn_fail() is called.
|
|
//
|
|
assert_pass(i &VAssertMetaInfo) // called after each `assert true`.
|
|
assert_fail(i &VAssertMetaInfo) // called after each `assert false`.
|
|
//
|
|
free() // you should free all the private data of your runner here.
|
|
}
|
|
|
|
//
|
|
|
|
struct VTestFileMetaInfo {
|
|
file string
|
|
tests int
|
|
}
|
|
|
|
// vtest_new_filemetainfo will be called right before .start(ntests),
|
|
// to fill in the .file_test_info field of the runner interface.
|
|
fn vtest_new_filemetainfo(file string, tests int) VTestFileMetaInfo {
|
|
return VTestFileMetaInfo{
|
|
file: file
|
|
tests: tests
|
|
}
|
|
}
|
|
|
|
[unsafe]
|
|
fn (i &VTestFileMetaInfo) free() {
|
|
unsafe {
|
|
i.file.free()
|
|
}
|
|
}
|
|
|
|
//
|
|
|
|
struct VTestFnMetaInfo {
|
|
name string
|
|
mod string
|
|
file string
|
|
line_nr int
|
|
}
|
|
|
|
// vtest_new_metainfo will be called once per each test function.
|
|
fn vtest_new_metainfo(name string, mod string, file string, line_nr int) VTestFnMetaInfo {
|
|
return VTestFnMetaInfo{
|
|
name: name
|
|
mod: mod
|
|
file: file
|
|
line_nr: line_nr
|
|
}
|
|
}
|
|
|
|
[unsafe]
|
|
fn (i &VTestFnMetaInfo) free() {
|
|
unsafe {
|
|
i.name.free()
|
|
i.mod.free()
|
|
i.file.free()
|
|
}
|
|
}
|
|
|
|
//
|
|
|
|
[typedef]
|
|
struct C.main__TestRunner {
|
|
mut:
|
|
_object voidptr
|
|
}
|
|
|
|
// change_test_runner should be called by preludes that implement the
|
|
// the TestRunner interface, in their vtest_init fn (see below), to
|
|
// customize the way that V shows test results
|
|
[manualfree]
|
|
pub fn change_test_runner(x &TestRunner) {
|
|
pobj := unsafe { &C.main__TestRunner(&test_runner)._object }
|
|
if pobj != 0 {
|
|
test_runner.free()
|
|
unsafe {
|
|
(&C.main__TestRunner(&test_runner))._object = voidptr(0)
|
|
}
|
|
}
|
|
test_runner = *x
|
|
}
|
|
|
|
// vtest_init will be caled *before* the normal _vinit() function,
|
|
// to give a chance to the test runner implemenation to change the
|
|
// test_runner global variable. The reason vtest_init is called before
|
|
// _vinit, is because a _test.v file can define consts, and they in turn
|
|
// may use function calls in their declaration, which may do assertions.
|
|
// fn vtest_init() {
|
|
// change_test_runner(&TestRunner(AnotherTestRunner{}))
|
|
// }
|
|
|
|
// TODO: remove vtest_option_cludge, it is only here so that
|
|
// `vlib/sync/channel_close_test.v` compiles with simpler runners,
|
|
// that do not `import os` (which has other `fn()?`). Without it,
|
|
// the C `Option_void` type is undefined -> C compilation error.
|
|
fn vtest_option_cludge() ? {
|
|
}
|