v2 / vlib / v / slow_tests / valgrind / valgrind_test.v
143 lines · 132 sloc · 4.64 KB · 5dd162f919796411306b434869fd8c77a53bc161
Raw
1// vtest build: !musl? && !sanitized_job?
2import os
3import term
4import benchmark
5import v.util.vtest
6
7@[markused]
8const turn_off_vcolors = os.setenv('VCOLORS', 'never', true)
9
10fn bold(s string) string {
11 return term.colorize(term.bold, s)
12}
13
14//
15// Note: skip_compile_files can be used for totally skipping .v files temporarily.
16// .v files in skip_valgrind_files will be compiled, but will not be run under
17// valgrind. This ensures that at least the generated code does not have C syntax
18// errors.
19// Use: `./v -d noskipcompile vlib/v/slow_tests/valgrind/valgrind_test.v` to ignore the
20// skip_compile_files list.
21// Use: `./v -d noskip vlib/v/slow_tests/valgrind/valgrind_test.v` to ignore skip_valgrind_files
22// Use: `./v -d noskipcompile -d noskip vlib/v/slow_tests/valgrind/valgrind_test.v` to ignore both
23//
24const skip_compile_files = [
25 'vlib/v/slow_tests/valgrind/option_reassigned.v',
26]
27
28const skip_valgrind_files = [
29 'vlib/v/slow_tests/valgrind/1.strings_and_arrays.v',
30 'vlib/v/slow_tests/valgrind/autofree_or_block_string_interp.v',
31 'vlib/v/slow_tests/valgrind/struct_field.v',
32 'vlib/v/slow_tests/valgrind/fn_returning_string_param.v',
33 'vlib/v/slow_tests/valgrind/fn_with_return_should_free_local_vars.v',
34 'vlib/v/slow_tests/valgrind/multiple_fn_calls.v',
35 'vlib/v/slow_tests/valgrind/option_simple.v',
36 'vlib/v/slow_tests/valgrind/string_plus_string_plus.v',
37 'vlib/v/slow_tests/valgrind/import_x_json2.v',
38 'vlib/v/slow_tests/valgrind/comptime_selector.v',
39 'vlib/v/slow_tests/valgrind/2.heap_objects.v',
40 'vlib/v/slow_tests/valgrind/logging.v',
41 'vlib/v/slow_tests/valgrind/rand_module.v',
42 'vlib/v/slow_tests/valgrind/struct_of_array_of_same_struct.v',
43 'vlib/v/slow_tests/valgrind/sync.v',
44]
45
46fn vprintln(s string) {
47 $if verbose ? {
48 eprintln(s)
49 }
50}
51
52fn test_all() {
53 if os.user_os() != 'linux' && os.getenv('FORCE_VALGRIND_TEST').len == 0 {
54 eprintln('Valgrind tests can only be run reliably on Linux for now.')
55 eprintln('You can still do it by setting FORCE_VALGRIND_TEST=1 .')
56 exit(0)
57 }
58
59 if os.getenv('V_CI_UBUNTU_MUSL').len > 0 {
60 eprintln('This test is disabled for musl.')
61 exit(0)
62 }
63
64 res_valgrind := os.execute('valgrind --version')
65 if res_valgrind.exit_code != 0 {
66 eprintln('This test needs `valgrind` to be installed.')
67 exit(0)
68 }
69
70 bench_message := 'memory leak checking with valgrind'
71 mut bench := benchmark.new_benchmark()
72 eprintln(term.header(bench_message, '-'))
73 vexe := os.getenv('VEXE')
74 vroot := os.dir(vexe)
75 valgrind_test_path := 'vlib/v/slow_tests/valgrind'
76 dir := os.join_path(vroot, valgrind_test_path)
77 mut files := os.ls(dir) or { panic(err) }
78 files.sort()
79
80 wrkdir := os.join_path(os.vtmp_dir(), 'valgrind_tests')
81 os.mkdir_all(wrkdir) or { panic(err) }
82 os.chdir(wrkdir) or {}
83
84 only_ordinary_v_files := files.filter(it.ends_with('.v') && !it.ends_with('_test.v'))
85 tests := vtest.filter_vtest_only(only_ordinary_v_files, basepath: valgrind_test_path)
86 bench.set_total_expected_steps(tests.len)
87 for test in tests {
88 bench.step()
89 if test in skip_compile_files {
90 $if !noskipcompile ? {
91 bench.skip()
92 eprintln(bench.step_message_skip(test))
93 continue
94 }
95 }
96 //
97 mut base_filename := os.file_name(test)
98 if base_filename.ends_with('.c.v') {
99 base_filename = base_filename#[..-4]
100 } else if base_filename.ends_with('.v') {
101 base_filename = base_filename#[..-2]
102 }
103 exe_filename := '${wrkdir}/${base_filename}'
104 full_path_to_source_file := os.join_path(vroot, test)
105 compile_cmd := '${os.quoted_path(vexe)} -o ${os.quoted_path(exe_filename)} -cg -cflags ' +
106 ' "-w" -experimental -autofree ${os.quoted_path(full_path_to_source_file)}'
107 vprintln('compile cmd: ${bold(compile_cmd)}')
108 res := os.execute(compile_cmd)
109 if res.exit_code != 0 {
110 bench.fail()
111 eprintln(bench.step_message_fail('file: ${test} could not be compiled.'))
112 eprintln(res.output)
113 eprintln('You can reproduce the failure with:\n${compile_cmd}')
114 continue
115 }
116 if test in skip_valgrind_files {
117 $if !noskip ? {
118 bench.skip()
119 eprintln(bench.step_message_skip(test))
120 continue
121 }
122 }
123 valgrind_cmd := 'valgrind --error-exitcode=1 --leak-check=full ${os.quoted_path(exe_filename)}'
124 vprintln('valgrind cmd: ${bold(valgrind_cmd)}')
125 valgrind_res := os.execute(valgrind_cmd)
126 if valgrind_res.exit_code != 0 {
127 bench.fail()
128 eprintln(bench.step_message_fail('failed valgrind check for ${bold(test)}'))
129 eprintln(valgrind_res.output)
130 eprintln('You can reproduce the failure with:\n${compile_cmd} && ${valgrind_cmd}')
131 continue
132 }
133 bench.ok()
134 eprintln(bench.step_message_ok(test))
135 }
136 bench.stop()
137 eprintln(term.h_divider('-'))
138 eprintln(bench.total_message(bench_message))
139 if bench.nfail > 0 {
140 exit(1)
141 }
142 os.rmdir_all(wrkdir) or {}
143}
144