| 1 | import os |
| 2 | |
| 3 | const vexe = @VEXE |
| 4 | |
| 5 | fn missing_boehm_lib(output string) bool { |
| 6 | mentions_gc := output.contains('libgc') || output.contains('-lgc') |
| 7 | || output.contains("library 'gc'") || output.contains('bdw-gc') |
| 8 | return mentions_gc && (output.contains('was not found') |
| 9 | || output.contains('cannot find') || output.contains('not found') |
| 10 | || output.contains('No such file')) |
| 11 | } |
| 12 | |
| 13 | fn closure_skip_unused_source() string { |
| 14 | return [ |
| 15 | 'module main', |
| 16 | 'import builtin.closure', |
| 17 | '', |
| 18 | 'fn make_cb(seed int) fn () int {', |
| 19 | '\tvalues := []int{len: 8, init: seed + index}', |
| 20 | '\treturn fn [values] () int {', |
| 21 | '\t\treturn values[0] + values[7]', |
| 22 | '\t}', |
| 23 | '}', |
| 24 | '', |
| 25 | 'fn no_capture_work() {}', |
| 26 | '', |
| 27 | 'fn consume(i int) int {', |
| 28 | '\th := fn [i] (x int) int {', |
| 29 | '\t\treturn i + x', |
| 30 | '\t}', |
| 31 | '\treturn h(i + 1)', |
| 32 | '}', |
| 33 | '', |
| 34 | 'fn run() ! {', |
| 35 | '\tmut lifetime := closure.new_lifetime()', |
| 36 | '\tmut total := 0', |
| 37 | '\tlifetime.frame(fn () {', |
| 38 | '\t\tcb := make_cb(20)', |
| 39 | '\t\tassert cb() == 47', |
| 40 | '\t})!', |
| 41 | '\tlifetime.suspend(fn () {', |
| 42 | '\t\tcb := make_cb(30)', |
| 43 | '\t\tassert cb() == 67', |
| 44 | '\t})!', |
| 45 | '\tlifetime.suspend(no_capture_work)!', |
| 46 | '\tfor i in 0 .. 64 {', |
| 47 | '\t\ttotal += consume(i)', |
| 48 | '\t}', |
| 49 | '\tlifetime.reclaim_all()!', |
| 50 | '\tlifetime.dispose()!', |
| 51 | '\tassert total == 4096', |
| 52 | '\tprintln(total)', |
| 53 | '}', |
| 54 | '', |
| 55 | 'fn main() {', |
| 56 | '\trun() or { panic(err) }', |
| 57 | '}', |
| 58 | ].join('\n') |
| 59 | } |
| 60 | |
| 61 | fn run_closure_skip_unused_case(tmp_dir string, mode string) { |
| 62 | source_path := os.join_path(tmp_dir, 'closure_skip_unused_${mode}.v') |
| 63 | binary_path := os.join_path(tmp_dir, 'closure_skip_unused_${mode}') |
| 64 | os.write_file(source_path, closure_skip_unused_source()) or { panic(err) } |
| 65 | compile_cmd := '${os.quoted_path(vexe)} -skip-unused -gc ${mode} -o ${os.quoted_path(binary_path)} ${os.quoted_path(source_path)}' |
| 66 | compile_res := os.execute(compile_cmd) |
| 67 | if mode != 'none' && compile_res.exit_code != 0 && missing_boehm_lib(compile_res.output) { |
| 68 | eprintln('skipping ${mode} closure skip-unused test: missing libgc') |
| 69 | return |
| 70 | } |
| 71 | assert compile_res.exit_code == 0, compile_res.output |
| 72 | if mode == 'boehm_leak' { |
| 73 | return |
| 74 | } |
| 75 | run_res := os.execute(os.quoted_path(binary_path)) |
| 76 | assert run_res.exit_code == 0, run_res.output |
| 77 | assert run_res.output.contains('4096'), run_res.output |
| 78 | } |
| 79 | |
| 80 | fn test_closure_context_helpers_are_kept_with_skip_unused() { |
| 81 | tmp_dir := os.join_path(os.vtmp_dir(), 'v_closure_context_skip_unused_${os.getpid()}') |
| 82 | os.mkdir_all(tmp_dir) or { panic(err) } |
| 83 | defer { |
| 84 | os.rmdir_all(tmp_dir) or {} |
| 85 | } |
| 86 | for mode in ['boehm', 'boehm_leak', 'none'] { |
| 87 | run_closure_skip_unused_case(tmp_dir, mode) |
| 88 | } |
| 89 | } |
| 90 | |