1 | module main |
2 | |
3 | // This program verifies that `v test` propagates errors |
4 | // and that it exits with code 1, when at least 1 FAIL happen. |
5 | import os |
6 | import rand |
7 | |
8 | const ( |
9 | vexe = os.quoted_path(get_vexe_path()) |
10 | vroot = os.dir(vexe) |
11 | tdir = new_tdir() |
12 | ) |
13 | |
14 | fn get_vexe_path() string { |
15 | env_vexe := os.getenv('VEXE') |
16 | if env_vexe != '' { |
17 | return env_vexe |
18 | } |
19 | me := os.executable() |
20 | eprintln('me: ${me}') |
21 | mut vexe_ := os.join_path(os.dir(os.dir(os.dir(me))), 'v') |
22 | if os.user_os() == 'windows' { |
23 | vexe_ += '.exe' |
24 | } |
25 | return vexe_ |
26 | } |
27 | |
28 | fn new_tdir() string { |
29 | dir := os.join_path(os.vtmp_dir(), 'v', rand.ulid()) |
30 | os.rmdir_all(dir) or {} |
31 | os.mkdir_all(dir) or { panic(err) } |
32 | C.atexit(cleanup_tdir) |
33 | return dir |
34 | } |
35 | |
36 | fn cleanup_tdir() { |
37 | println('... removing tdir: ${tdir}') |
38 | os.rmdir_all(tdir) or { eprintln(err) } |
39 | } |
40 | |
41 | type MyResult = string |
42 | |
43 | [noreturn] |
44 | fn (result MyResult) fail(reason string) { |
45 | eprintln('> ${reason}, but it does not. Result:\n${result}') |
46 | exit(1) |
47 | } |
48 | |
49 | fn (result MyResult) has(sub string) MyResult { |
50 | if !result.contains(sub) { |
51 | result.fail(' result should have the substring `${sub}`') |
52 | } |
53 | return result |
54 | } |
55 | |
56 | fn (result MyResult) matches(gpattern string) MyResult { |
57 | if !result.match_glob(gpattern) { |
58 | result.fail('result should match the glob pattern `${gpattern}`') |
59 | } |
60 | return result |
61 | } |
62 | |
63 | fn create_test(tname string, tcontent string) !string { |
64 | tpath := os.join_path(tdir, tname) |
65 | os.write_file(tpath, tcontent)! |
66 | eprintln('>>>>>>>> tpath: ${tpath} | tcontent: ${tcontent}') |
67 | return os.quoted_path(tpath) |
68 | } |
69 | |
70 | fn check_assert_continues_works() ! { |
71 | os.chdir(tdir)! |
72 | create_test('assert_continues_option_works_test.v', 'fn test_fail1() { assert 2==4\nassert 2==1\nassert 2==0 }\nfn test_ok(){ assert true }\nfn test_fail2() { assert false }')! |
73 | result := check_fail('${vexe} -assert continues assert_continues_option_works_test.v') |
74 | result.has('assert_continues_option_works_test.v:1: fn test_fail1') |
75 | result.has('assert_continues_option_works_test.v:2: fn test_fail1') |
76 | result.has('assert_continues_option_works_test.v:3: fn test_fail1') |
77 | result.has('assert_continues_option_works_test.v:5: fn test_fail2') |
78 | result.has('> assert 2 == 4').has('> assert 2 == 1').has('> assert 2 == 0') |
79 | // Check if a test function, tagged with [assert_continues], has the same behaviour, without needing additional options |
80 | create_test('assert_continues_tag_works_test.v', '[assert_continues]fn test_fail1() { assert 2==4\nassert 2==1\nassert 2==0 }\nfn test_ok(){ assert true }\nfn test_fail2() { assert false\n assert false }')! |
81 | tag_res := check_fail('${vexe} assert_continues_tag_works_test.v') |
82 | tag_res.has('assert_continues_tag_works_test.v:1: fn test_fail1') |
83 | tag_res.has('assert_continues_tag_works_test.v:2: fn test_fail1') |
84 | tag_res.has('assert_continues_tag_works_test.v:3: fn test_fail1') |
85 | tag_res.has('assert_continues_tag_works_test.v:5: fn test_fail2') |
86 | if tag_res.contains('assert_continues_tag_works_test.v:6: fn test_fail2') { |
87 | exit(1) |
88 | } |
89 | } |
90 | |
91 | fn check_ok(cmd string) MyResult { |
92 | println('> check_ok cmd: ${cmd}') |
93 | res := os.execute(cmd) |
94 | if res.exit_code != 0 { |
95 | eprintln('> check_ok failed.\n${res.output}') |
96 | exit(1) |
97 | } |
98 | return res.output |
99 | } |
100 | |
101 | fn check_fail(cmd string) MyResult { |
102 | println('> check_fail cmd: ${cmd}') |
103 | res := os.execute(cmd) |
104 | if res.exit_code == 0 { |
105 | eprintln('> check_fail succeeded, but it should have failed.\n${res.output}') |
106 | exit(1) |
107 | } |
108 | return res.output |
109 | } |
110 | |
111 | fn main() { |
112 | defer { |
113 | os.chdir(os.wd_at_startup) or {} |
114 | } |
115 | println('> vroot: ${vroot} | vexe: ${vexe} | tdir: ${tdir}') |
116 | ok_fpath := create_test('a_single_ok_test.v', 'fn test_ok(){ assert true }')! |
117 | if check_ok('${vexe} ${ok_fpath}') != '' { |
118 | exit(1) |
119 | } |
120 | check_ok('${vexe} test ${ok_fpath}').matches('*OK*a_single_ok_test.v*') |
121 | check_ok('${vexe} test "${tdir}"').matches('*OK*a_single_ok_test.v*') |
122 | // |
123 | fail_fpath := create_test('a_single_failing_test.v', 'fn test_fail(){ assert 1 == 2 }')! |
124 | check_fail('${vexe} ${fail_fpath}').has('> assert 1 == 2').has('a_single_failing_test.v:1: fn test_fail') |
125 | check_fail('${vexe} test ${fail_fpath}').has('> assert 1 == 2').has('a_single_failing_test.v:1: fn test_fail') |
126 | check_fail('${vexe} test "${tdir}"').has('> assert 1 == 2') |
127 | rel_dir := os.join_path(tdir, rand.ulid()) |
128 | os.mkdir(rel_dir)! |
129 | os.chdir(rel_dir)! |
130 | relative_path := '..' + os.path_separator + 'a_single_ok_test.v' |
131 | check_ok('${vexe} test ${os.quoted_path(relative_path)}').has('OK').has('a_single_ok_test.v') |
132 | // |
133 | check_assert_continues_works()! |
134 | println('> all done') |
135 | } |