v2 / vlib / v / preludes / test_runner.c.v
120 lines · 103 sloc · 4.21 KB · 38e23a76f3e48679cc029cf0e9904566e94c5df9
Raw
1@[has_globals]
2module main
3
4__global test_runner TestRunner
5
6///////////////////////////////////////////////////////////////////////////////
7// This file will be compiled as part of the main program, for a _test.v file.
8// The methods defined here are called back by the test program's assert
9// statements, on each success/fail. The goal is to make customizing the look &
10// feel of the assertions results easier, since it is done in normal V code.
11///////////////////////////////////////////////////////////////////////////////
12
13interface TestRunner {
14mut:
15 file_test_info VTestFileMetaInfo // filled in by generated code, before .start() is called.
16 fn_test_info VTestFnMetaInfo // filled in by generated code, before .fn_start() is called.
17 fn_assert_passes u64 // reset this to 0 in .fn_start(), increase it in .assert_pass()
18 fn_passes u64 // increase this in .fn_pass()
19 fn_fails u64 // increase this in .fn_fails()
20 total_assert_passes u64 // increase this in .assert_pass()
21 total_assert_fails u64 // increase this in .assert_fail()
22
23 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.
24 finish() // called after all tests are finished, you can print some stats if you want here.
25 exit_code() int // called right after finish(), it should return the exit code, that the test program will exit with.
26
27 fn_start() bool // called before the start of each test_ function. Return false, if the function should be skipped.
28 fn_pass() // called after the end of each test_ function, with NO failed assertion.
29 fn_fail() // called after the end of each test_ function, with a failed assertion, *or* returning an error.
30 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.
31
32 assert_pass(i &VAssertMetaInfo) // called after each `assert true`.
33 assert_fail(i &VAssertMetaInfo) // called after each `assert false`.
34
35 free() // you should free all the private data of your runner here.
36}
37
38struct VTestFileMetaInfo {
39 file string
40 tests int
41}
42
43// vtest_new_filemetainfo will be called right before .start(ntests),
44// to fill in the .file_test_info field of the runner interface.
45fn vtest_new_filemetainfo(file string, tests int) VTestFileMetaInfo {
46 return VTestFileMetaInfo{
47 file: file
48 tests: tests
49 }
50}
51
52@[unsafe]
53fn (i &VTestFileMetaInfo) free() {
54 unsafe {
55 i.file.free()
56 }
57}
58
59struct VTestFnMetaInfo {
60 name string
61 mod string
62 file string
63 line_nr int
64}
65
66// vtest_new_metainfo will be called once per each test function.
67fn vtest_new_metainfo(name string, mod string, file string, line_nr int) VTestFnMetaInfo {
68 return VTestFnMetaInfo{
69 name: name
70 mod: mod
71 file: file
72 line_nr: line_nr
73 }
74}
75
76@[unsafe]
77fn (i &VTestFnMetaInfo) free() {
78 unsafe {
79 i.name.free()
80 i.mod.free()
81 i.file.free()
82 }
83}
84
85@[typedef]
86pub struct C.main__TestRunner {
87mut:
88 _object voidptr
89}
90
91// change_test_runner should be called by preludes that implement the
92// the TestRunner interface, in their vtest_init fn (see below), to
93// customize the way that V shows test results
94@[manualfree]
95pub fn change_test_runner(x &TestRunner) {
96 pobj := unsafe { &C.main__TestRunner(&test_runner)._object }
97 if pobj != 0 {
98 unsafe {
99 test_runner.free()
100 (&C.main__TestRunner(&test_runner))._object = nil
101 }
102 }
103 test_runner = *x
104}
105
106// vtest_init will be called *before* the normal _vinit() function,
107// to give a chance to the test runner implementation to change the
108// test_runner global variable. The reason vtest_init is called before
109// _vinit, is because a _test.v file can define consts, and they in turn
110// may use function calls in their declaration, which may do assertions.
111// fn vtest_init() {
112// change_test_runner(&TestRunner(AnotherTestRunner{}))
113// }
114
115// TODO: remove vtest_option_cludge, it is only here so that
116// `vlib/sync/channel_close_test.v` compiles with simpler runners,
117// that do not `import os` (which has other `fn()?`). Without it,
118// the C `Option_void` type is undefined -> C compilation error.
119fn vtest_option_cludge() ! {
120}
121