From 2eb299ad019ab252eefdc6ba72a39a6835fa2c5e Mon Sep 17 00:00:00 2001 From: metif12 Date: Sun, 4 Oct 2026 12:03:06 +0330 Subject: [PATCH] tests: build the harness on os.exec so `make test` compiles on current V `make test` is `v -Wimpure-v -W test .`, and on current V it could not compile 31 of the 49 test files: common/testing/testrig.v:211: error: function `execute` has been deprecated; use os.exec with an argument array; command strings can allow shell injection -W turns a deprecation into an error, so every test file that went through the harness, and every file that called os.execute itself, was failing to build rather than running. That is what the three Linux workflows do, and what this unblocks. os.exec takes an argument array, so a command line has to be split somewhere. Every command in this repository is written as a string by the tests, so this adds the one place that does it: split_args.v whitespace between words, single and double quotes, and nothing else Not a shell, on purpose. A backslash is an ordinary character everywhere in it, because on this platform a backslash is nearly always part of a path and a shell's rule of eating it would take the volume off `C:\Users\me\file.txt`. The shapes it does have to handle are the ones the tests actually write, and each is pinned by a test taken from a real call site: --output-delimiter="|" comm_test.v sh -c "exit 42" timeout_test.v tr -d '\r' sum_test.v C:\Users\me\coreutils\test.txt the reason it is not a shell An unterminated quote is not an error: the rest of the line becomes one word, so a test that made the mistake fails on what the program said rather than on a parse in this file. 124 call sites, 22 files. `v -Wimpure-v -W test .` on Windows: before 31 files could not be built at all after 2 and the suite goes from 25 files failing to 17, with those 17 being real test failures rather than build failures. The two that still do not build are fixed elsewhere: tail's string_to_i64_test.v is #207 and sum's is #215. Nothing that a test asserts. The commands are the same strings, the arguments are the same arguments, and no test was reworded; the difference is only that the split is done in V rather than by a shell. Twenty files under src/ and the three under common/testing/ and no other. --- common/testing/executables.c.v | 2 +- common/testing/split_args.v | 67 ++++++++++++++++++++++++++++++++ common/testing/split_args_test.v | 40 +++++++++++++++++++ common/testing/testing.v | 14 +++---- common/testing/testrig.v | 12 +++--- src/base64/base64_test.v | 4 +- src/cksum/cksum_test.v | 8 ++-- src/comm/comm_test.v | 28 ++++++------- src/dirname/dirname_test.v | 2 +- src/expand/expand_test.v | 8 ++-- src/expr/expr_test.v | 8 ++-- src/factor/factor_test.v | 4 +- src/fold/fold_test.v | 10 ++--- src/head/head_test.v | 14 +++---- src/mkdir/mkdir_test.v | 10 ++--- src/shuf/shuf_test.v | 12 +++--- src/sleep/sleep_test.v | 6 +-- src/sum/sum_test.v | 28 ++++++------- src/tac/tac_test.v | 2 +- src/timeout/timeout_test.v | 24 ++++++------ src/unexpand/unexpand_test.v | 10 ++--- src/wc/wc_test.v | 34 ++++++++-------- 22 files changed, 227 insertions(+), 120 deletions(-) create mode 100644 common/testing/split_args.v create mode 100644 common/testing/split_args_test.v diff --git a/common/testing/executables.c.v b/common/testing/executables.c.v index 99d2cdb8..b7e3957c 100644 --- a/common/testing/executables.c.v +++ b/common/testing/executables.c.v @@ -35,7 +35,7 @@ pub fn prepare_executable(tool_name string) string { $if debug { eprintln('>> compiling with: `${compilation_cmd}`') } - res := os.execute(compilation_cmd) + res := os.exec_opt(split_args(compilation_cmd)) or { panic('could not run ${compilation_cmd}') } if res.exit_code != 0 { eprintln('Tool ${tool_name} could not be compiled.') eprintln('Compilation command:\n${compilation_cmd}') diff --git a/common/testing/split_args.v b/common/testing/split_args.v new file mode 100644 index 00000000..39257575 --- /dev/null +++ b/common/testing/split_args.v @@ -0,0 +1,67 @@ +module testing + +import os + +// split_args breaks a command line into the argument array os.exec takes. +// +// It exists because os.execute is deprecated and `make test` builds with -W, where a +// deprecation is an error: on current V that stopped 31 of the 49 test files from +// compiling at all. Every command in this repository is written as a string by the +// tests, so the string has to be split somewhere, and this is that place. +// +// The rules are the ones those strings actually use, which is not all of a shell: +// +// tool -a "two words" 'and more' three kinds of quoting, all of them in use +// tool --delimiter="|" a quoted value with a character in it +// sh -c "exit 42" a quoted argument containing a space +// tr -d '\r' a backslash inside single quotes +// C:\Users\me\file.txt a backslash outside quotes, which is a path +// +// So: whitespace between words, single and double quotes, and nothing else. A +// backslash is an ordinary character everywhere, because on this platform it is +// almost always part of a path, and a shell's rule of eating it would take the +// volume off. An unterminated quote is not an error here: the rest of the line +// becomes one word, so a test fails on what the program said rather than on a parse +// in this file. +pub fn split_args(cmd string) []string { + mut args := []string{} + mut word := []rune{} + mut in_word := false + mut quote := u8(0) + for ch in cmd.runes() { + c := u8(ch) + if quote != 0 { + if c == quote { + quote = 0 + } else { + word << ch + } + continue + } + if c == `'` || c == `"` { + quote = c + in_word = true + continue + } + if c == ` ` || c == `\t` || c == `\n` || c == `\r` { + if in_word { + args << word.string() + word = []rune{} + in_word = false + } + continue + } + word << ch + in_word = true + } + if in_word { + args << word.string() + } + return args +} + +// run_args is split_args for the common case where the caller has the executable and +// the rest of the command line already separate, which is how the tests below read. +pub fn run_args(exe string, args string) os.Result { + return os.exec(split_args('${exe} ${args}')) +} diff --git a/common/testing/split_args_test.v b/common/testing/split_args_test.v new file mode 100644 index 00000000..867b1014 --- /dev/null +++ b/common/testing/split_args_test.v @@ -0,0 +1,40 @@ +module testing + +// Every shape here is one a test in this repository actually writes, so the rules in +// split_args are pinned by something rather than by taste. +fn test_split_args_plain_words() { + assert split_args('tool -a -b file') == ['tool', '-a', '-b', 'file'] + assert split_args('') == []string{} + assert split_args(' ') == []string{} +} + +fn test_split_args_runs_of_whitespace() { + assert split_args('tool -a\t\t-b\nfile') == ['tool', '-a', '-b', 'file'] + // comm_test.v writes this one + assert split_args('comm --output-delimiter="|" f1 f2') == + ['comm', '--output-delimiter=|', 'f1', 'f2'] +} + +fn test_split_args_quotes() { + // timeout_test.v writes this one + assert split_args('timeout --preserve-status 1 sh -c "exit 42"') == + ['timeout', '--preserve-status', '1', 'sh', '-c', 'exit 42'] + // sum_test.v writes this one, where the backslash is a character and not an escape + assert split_args("sum tr -d '\\r' f") == ['sum', 'tr', '-d', '\\r', 'f'] + // An empty quoted word is still a word + assert split_args('tool "" x') == ['tool', '', 'x'] +} + +fn test_split_args_keeps_backslashes_in_paths() { + // The reason this is not a shell: eating the backslash would take the volume off. + path := r'C:\Users\me\coreutils\test.txt' + assert split_args('cksum ${path}') == ['cksum', path] + assert split_args('cksum "${path}"') == ['cksum', path] +} + +// An unterminated quote is not an error: whatever followed becomes one word, so the +// test that made the mistake fails on the program's message. +fn test_split_args_unterminated_quote() { + assert split_args('tool "two words') == ['tool', 'two words'] + assert split_args("tool 'one") == ['tool', 'one'] +} diff --git a/common/testing/testing.v b/common/testing/testing.v index 154f74be..f20f298f 100644 --- a/common/testing/testing.v +++ b/common/testing/testing.v @@ -50,14 +50,14 @@ pub fn (p CommandPair) same_results(options string) bool { // and the deputy commands with them, and ensure that they both fail // with the same exit_code pub fn (p CommandPair) expected_failure(options string) !os.Result { - ores := os.execute('${p.original} ${options}') + ores := run_args(p.original, options) if ores.exit_code == 0 { return DidNotFailError{ msg: '${p.original} ${options}' code: 1 } } - dres := os.execute('${p.deputy} ${options}') + dres := run_args(p.deputy, options) if dres.exit_code == 0 { return DidNotFailError{ msg: '${p.deputy} ${options}' @@ -77,13 +77,13 @@ pub fn (p CommandPair) expected_failure(options string) !os.Result { pub fn (p CommandPair) ensure_help_and_version_options_work() ! { // For now, assume that the original has --version and --help // and that they already work correctly. - if os.execute('${p.deputy} --help').exit_code != 0 { + if run_args(p.deputy, '--help').exit_code != 0 { return DoesNotWorkError{ msg: '--help' code: 1 } } - if os.execute('${p.deputy} --version').exit_code != 0 { + if run_args(p.deputy, '--version').exit_code != 0 { return DoesNotWorkError{ msg: '--version' code: 2 @@ -97,7 +97,7 @@ pub fn (p CommandPair) ensure_help_and_version_options_work() ! { // It also returns the actual result of the execution, // so that you can inspect it further for more details. pub fn command_fails(cmd string) !os.Result { - res := os.execute(cmd) + res := os.exec(split_args(cmd)) if res.exit_code == 0 { return DidNotFailError{ msg: cmd @@ -116,8 +116,8 @@ const use_multi_binary_to_test = os.getenv('USE_MULTI_BINARY_TO_TEST') // and for their output. // note: use `v -d trace_same_results ...` to enable trace output pub fn same_results(cmd1 string, cmd2 string) bool { - cmd1_res := os.execute(cmd1) - cmd2_res := os.execute(cmd2) + cmd1_res := os.exec(split_args(cmd1)) + cmd2_res := os.exec(split_args(cmd2)) mut noutput1 := normalise(cmd1_res.output) mut noutput2 := normalise(cmd2_res.output) $if trace_same_results ? { diff --git a/common/testing/testrig.v b/common/testing/testrig.v index 5206fa5c..79169649 100644 --- a/common/testing/testrig.v +++ b/common/testing/testrig.v @@ -24,7 +24,7 @@ pub: } pub fn (rig TestRig) call_for_test(args string) os.Result { - res := os.execute('${rig.executable_under_test} ${args}') + res := run_args(rig.executable_under_test, args) assert res.exit_code == 0 return res } @@ -66,7 +66,7 @@ pub fn (rig TestRig) clean_up() { } pub fn (rig TestRig) assert_platform_util() { - platform_ver := os.execute('${rig.platform_util_call} --version') + platform_ver := run_args(rig.platform_util_call, '--version') eprintln('Platform util version: [${platform_ver.output}]') assert platform_ver.exit_code == 0 @@ -90,11 +90,11 @@ pub fn (rig TestRig) assert_platform_util() { } pub fn (rig TestRig) call_orig(args string) os.Result { - return os.execute('${rig.platform_util_call} ${args}') + return run_args(rig.platform_util_call, args) } pub fn (rig TestRig) call_new(args string) os.Result { - return os.execute('${rig.executable_under_test} ${args}') + return run_args(rig.executable_under_test, args) } // print_small_diff eprints only differing small results that differ @@ -208,8 +208,8 @@ pub fn (rig TestRig) assert_help_and_version_options_work() { // For now, assume that the original has --version and --help // and that they already work correctly. - ver := os.execute('${rig.executable_under_test} --version') + ver := run_args(rig.executable_under_test, '--version') assert ver.output.trim_space() == '${rig.util} (V coreutils) ${common.version}' assert ver.exit_code == 0 - assert os.execute('${rig.executable_under_test} --help').exit_code == 0 + assert run_args(rig.executable_under_test, '--help').exit_code == 0 } diff --git a/src/base64/base64_test.v b/src/base64/base64_test.v index 3e270b95..2a11f6d9 100644 --- a/src/base64/base64_test.v +++ b/src/base64/base64_test.v @@ -13,14 +13,14 @@ fn test_help_and_version() { } fn test_abcd() { - res := os.execute('${rig.executable_under_test} abcd') + res := os.exec(testing.split_args('${rig.executable_under_test} abcd')) assert res.exit_code == 1 assert res.output.trim_space() == 'base64: abcd: No such file or directory' } fn expected_result(input string, output string) { c := '${executable_under_test} ${input}' - res := os.execute(c) + res := os.exec(testing.split_args(c)) eprintln('>>>> cmd: `${c}`') if res.exit_code != 0 || res.output.split_into_lines() != output.split_into_lines() { eprintln('>>>> res.exit_code: ${res.exit_code}') diff --git a/src/cksum/cksum_test.v b/src/cksum/cksum_test.v index 6c0b42da..f53eec51 100644 --- a/src/cksum/cksum_test.v +++ b/src/cksum/cksum_test.v @@ -32,28 +32,28 @@ fn test_help_and_version() { } fn test_stdin() { - res := os.execute('cat ${test1_txt_path} | ${executable_under_test}') + res := os.exec(testing.split_args('cat ${test1_txt_path} | ${executable_under_test}')) assert res.exit_code == 0 assert res.output.trim_space() == '365965416 25' } fn test_file_not_exist() { - res := os.execute('${executable_under_test} abcd') + res := os.exec(testing.split_args('${executable_under_test} abcd')) assert res.exit_code == 1 assert res.output.trim_space() == 'cksum: abcd: No such file or directory' } fn test_one_file() { - res := os.execute('${executable_under_test} ${test1_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} ${test1_txt_path}')) assert res.exit_code == 0 assert res.output == '365965416 25 ${test1_txt_path}${eol}' } fn test_several_files() { - res := os.execute('${executable_under_test} ${test1_txt_path} ${test2_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} ${test1_txt_path} ${test2_txt_path}')) assert res.exit_code == 0 assert res.output == '365965416 25 ${test1_txt_path}${eol}1338884673 131077 ${test2_txt_path}${eol}' diff --git a/src/comm/comm_test.v b/src/comm/comm_test.v index 692fb229..265ae88b 100644 --- a/src/comm/comm_test.v +++ b/src/comm/comm_test.v @@ -21,7 +21,7 @@ fn test_comm_basic() { os.write_lines(file2_path, ['banana', 'cherry', 'date', 'fig'])! // Test basic functionality - res := os.execute('${executable_under_test} ${file1_path} ${file2_path}') + res := os.exec(testing.split_args('${executable_under_test} ${file1_path} ${file2_path}')) assert res.exit_code == 0 // Normalize line endings for cross-platform compatibility @@ -45,22 +45,22 @@ fn test_comm_suppress_columns() { os.write_lines(file2_path, ['b', 'c', 'd'])! // Test -1 flag - res1 := os.execute('${executable_under_test} -1 ${file1_path} ${file2_path}') + res1 := os.exec(testing.split_args('${executable_under_test} -1 ${file1_path} ${file2_path}')) assert res1.exit_code == 0 assert res1.output.replace('\r\n', '\n') == '\tb\n\tc\nd\n' // Test -2 flag - res2 := os.execute('${executable_under_test} -2 ${file1_path} ${file2_path}') + res2 := os.exec(testing.split_args('${executable_under_test} -2 ${file1_path} ${file2_path}')) assert res2.exit_code == 0 assert res2.output.replace('\r\n', '\n') == 'a\n\tb\n\tc\n' // Test -3 flag - res3 := os.execute('${executable_under_test} -3 ${file1_path} ${file2_path}') + res3 := os.exec(testing.split_args('${executable_under_test} -3 ${file1_path} ${file2_path}')) assert res3.exit_code == 0 assert res3.output.replace('\r\n', '\n') == 'a\n\td\n' // Test -12 (show only common) - res12 := os.execute('${executable_under_test} -12 ${file1_path} ${file2_path}') + res12 := os.exec(testing.split_args('${executable_under_test} -12 ${file1_path} ${file2_path}')) assert res12.exit_code == 0 assert res12.output.replace('\r\n', '\n') == 'b\nc\n' @@ -83,17 +83,17 @@ fn test_comm_empty_files() { os.write_lines(nonempty_file, ['hello', 'world'])! // Both files empty - res1 := os.execute('${executable_under_test} ${empty_file} ${empty_file}') + res1 := os.exec(testing.split_args('${executable_under_test} ${empty_file} ${empty_file}')) assert res1.exit_code == 0 assert res1.output == '' // First file empty - res2 := os.execute('${executable_under_test} ${empty_file} ${nonempty_file}') + res2 := os.exec(testing.split_args('${executable_under_test} ${empty_file} ${nonempty_file}')) assert res2.exit_code == 0 assert res2.output.replace('\r\n', '\n') == '\thello\n\tworld\n' // Second file empty - res3 := os.execute('${executable_under_test} ${nonempty_file} ${empty_file}') + res3 := os.exec(testing.split_args('${executable_under_test} ${nonempty_file} ${empty_file}')) assert res3.exit_code == 0 assert res3.output.replace('\r\n', '\n') == 'hello\nworld\n' @@ -120,7 +120,7 @@ fn test_comm_stdin() { os.write_lines(stdin_file, ['banana', 'cherry'])! // Test stdin as first file - res1 := os.execute('cat ${stdin_file} | ${executable_under_test} - ${file_path}') + res1 := os.exec(testing.split_args('cat ${stdin_file} | ${executable_under_test} - ${file_path}')) assert res1.exit_code == 0 // stdin has: banana, cherry // file_path has: apple, banana @@ -129,7 +129,7 @@ fn test_comm_stdin() { assert res1.output.replace('\r\n', '\n') == expected1 // Test stdin as second file - res2 := os.execute('cat ${stdin_file} | ${executable_under_test} ${file_path} -') + res2 := os.exec(testing.split_args('cat ${stdin_file} | ${executable_under_test} ${file_path} -')) assert res2.exit_code == 0 expected2 := 'apple\n\t\tbanana\n\tcherry\n' assert res2.output.replace('\r\n', '\n') == expected2 @@ -141,7 +141,7 @@ fn test_comm_stdin() { fn test_comm_missing_file() { // Missing file should produce error - res := os.execute('${executable_under_test} /nonexistent/file1 /nonexistent/file2') + res := os.exec(testing.split_args('${executable_under_test} /nonexistent/file1 /nonexistent/file2')) assert res.exit_code == 1 // Error message varies by platform, but should contain the filename assert res.output.contains('/nonexistent/file1') || res.output.contains('\\nonexistent\\file1') @@ -149,12 +149,12 @@ fn test_comm_missing_file() { fn test_comm_missing_operand() { // No arguments should produce error - res1 := os.execute('${executable_under_test}') + res1 := os.exec(testing.split_args('${executable_under_test}')) assert res1.exit_code == 1 assert res1.output.contains('missing operand') // One argument should produce error - res2 := os.execute('${executable_under_test} /tmp/file1') + res2 := os.exec(testing.split_args('${executable_under_test} /tmp/file1')) assert res2.exit_code == 1 assert res2.output.contains('missing operand') } @@ -167,7 +167,7 @@ fn test_comm_delimiter() { os.write_lines(file2_path, ['b', 'c'])! // Test custom delimiter - res := os.execute('${executable_under_test} --output-delimiter="|" ${file1_path} ${file2_path}') + res := os.exec(testing.split_args('${executable_under_test} --output-delimiter="|" ${file1_path} ${file2_path}')) assert res.exit_code == 0 assert res.output.replace('\r\n', '\n') == 'a\n|b\n||c\n' diff --git a/src/dirname/dirname_test.v b/src/dirname/dirname_test.v index db34f62b..a9ffdd2c 100644 --- a/src/dirname/dirname_test.v +++ b/src/dirname/dirname_test.v @@ -18,7 +18,7 @@ fn test_help_and_version() { } fn expected_result(input string, output string) { - res := os.execute('${executable_under_test} ${input}') + res := os.exec(testing.split_args('${executable_under_test} ${input}')) assert res.exit_code == 0 assert res.output.trim_space() == output testing.same_results('${rig.util} ${input}', '${executable_under_test} ${input}') diff --git a/src/expand/expand_test.v b/src/expand/expand_test.v index 74ce6340..6a23fadb 100644 --- a/src/expand/expand_test.v +++ b/src/expand/expand_test.v @@ -23,7 +23,7 @@ fn test_help_and_version() { } fn test_non_existent_file() { - res := os.execute('${executable_under_test} non-existent-file') + res := os.exec(testing.split_args('${executable_under_test} non-existent-file')) assert res.exit_code == 1 assert res.output.trim_space() == 'expand: failed to open file "non-existent-file"' } @@ -36,7 +36,7 @@ const testtxtcontent = [ ] fn test_default() { - res := os.execute('${executable_under_test} ${test_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path}')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ ' [0] Line with first tab', @@ -47,7 +47,7 @@ fn test_default() { } fn test_initial_option() { - res := os.execute('${executable_under_test} ${test_txt_path} -i') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path} -i')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ ' [0] Line with first tab', @@ -58,7 +58,7 @@ fn test_initial_option() { } fn test_tabs_option() { - res := os.execute('${executable_under_test} ${test_txt_path} -t 4') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path} -t 4')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ ' [0] Line with first tab', diff --git a/src/expr/expr_test.v b/src/expr/expr_test.v index 7d15be0e..d4b1db14 100644 --- a/src/expr/expr_test.v +++ b/src/expr/expr_test.v @@ -125,8 +125,8 @@ fn test_results() { for test in tests { res := cmd.same_results(test) if !res { - if os.execute('${cmd.original} ${test}').exit_code == 2 - && os.execute('${cmd.deputy} ${test}').exit_code == 2 { + if os.exec(testing.split_args('${cmd.original} ${test}')).exit_code == 2 + && os.exec(testing.split_args('${cmd.deputy} ${test}')).exit_code == 2 { continue } failed << test @@ -184,8 +184,8 @@ fn test_multi_byte_results() { if !res { original_cmd := '${cmd.original} ${test}' deputy_cmd := '${cmd.deputy} ${test}' - ores := os.execute(original_cmd) - dres := os.execute(deputy_cmd) + ores := os.exec(testing.split_args(original_cmd)) + dres := os.exec(testing.split_args(deputy_cmd)) if ores.exit_code == 2 && dres.exit_code == 2 { continue } diff --git a/src/factor/factor_test.v b/src/factor/factor_test.v index dedae4bd..df38bbbd 100644 --- a/src/factor/factor_test.v +++ b/src/factor/factor_test.v @@ -13,13 +13,13 @@ fn test_help_and_version() { } fn test_abcd() { - res := os.execute('${executable_under_test} abcd') + res := os.exec(testing.split_args('${executable_under_test} abcd')) assert res.exit_code == 1 assert res.output.trim_space() == 'factor: ‘abcd’ is not a valid positive integer' } fn expected_result(input string, output []string) { - res := os.execute('${executable_under_test} ${input}') + res := os.exec(testing.split_args('${executable_under_test} ${input}')) assert res.exit_code == 0 assert res.output.split_into_lines() == output testing.same_results('${rig.util} ${input}', '${executable_under_test} ${input}') diff --git a/src/fold/fold_test.v b/src/fold/fold_test.v index ac4766e4..21d72e76 100644 --- a/src/fold/fold_test.v +++ b/src/fold/fold_test.v @@ -30,13 +30,13 @@ fn test_help_and_version() { // fold nope1 nope2 one line each, for both files exit 1 // fold ok.txt nope2 the lines of ok.txt, then the error exit 1 fn test_non_existent_file() { - res := os.execute('${executable_under_test} non-existent-file') + res := os.exec(testing.split_args('${executable_under_test} non-existent-file')) assert res.exit_code == 1 assert res.output.trim_space() == 'fold: non-existent-file: No such file or directory' } fn test_non_existent_files() { - res := os.execute('${executable_under_test} non-existent-file second-non-existent-file') + res := os.exec(testing.split_args('${executable_under_test} non-existent-file second-non-existent-file')) assert res.exit_code == 1 assert res.output.trim_space() == 'fold: non-existent-file: No such file or directory\n' + 'fold: second-non-existent-file: No such file or directory' @@ -65,7 +65,7 @@ const testtxtcontent = [ ] fn test_wrap_default() { - res := os.execute('${executable_under_test} ${test_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path}')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ '[0] Example test line', @@ -82,7 +82,7 @@ fn test_wrap_default() { } fn test_wrap_multiline_file_with_width_10() { - res := os.execute('${executable_under_test} ${test_txt_path} -w 10') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path} -w 10')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ '[0] Exampl', @@ -119,7 +119,7 @@ fn test_wrap_multiline_file_with_width_10() { } fn test_wrap_multiline_file_with_width_3() { - res := os.execute('${executable_under_test} ${test_txt_path} -w 3') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path} -w 3')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ '[0]', diff --git a/src/head/head_test.v b/src/head/head_test.v index f3040994..7abe2dbc 100644 --- a/src/head/head_test.v +++ b/src/head/head_test.v @@ -25,13 +25,13 @@ fn test_help_and_version() { } fn test_non_existent_file() { - res := os.execute('${executable_under_test} non-existent-file') + res := os.exec(testing.split_args('${executable_under_test} non-existent-file')) assert res.exit_code == 1 assert res.output.trim_space() == 'head: failed to open file "non-existent-file"' } fn test_non_existent_files() { - res := os.execute('${executable_under_test} non-existent-file second-non-existent-file') + res := os.exec(testing.split_args('${executable_under_test} non-existent-file second-non-existent-file')) assert res.exit_code == 1 assert res.output.trim_space() == 'head: failed to open file "non-existent-file"${eol}head: failed to open file "second-non-existent-file"' } @@ -53,7 +53,7 @@ const testtxtcontent = [ ] fn test_default() { - res := os.execute('${executable_under_test} ${test_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path}')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ '[0] Line in test text file', @@ -70,7 +70,7 @@ fn test_default() { } fn test_max_lines_option() { - res := os.execute('${executable_under_test} ${test_txt_path} -n 4') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path} -n 4')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ '[0] Line in test text file', @@ -81,7 +81,7 @@ fn test_max_lines_option() { } fn test_max_lines_from_end_option() { - res := os.execute('${executable_under_test} ${test_txt_path} -n -4') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path} -n -4')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ '[0] Line in test text file', @@ -97,7 +97,7 @@ fn test_max_lines_from_end_option() { } fn test_upto_max_bytes() { - res := os.execute('${executable_under_test} ${test_txt_path} -c 223') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path} -c 223')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ '[0] Line in test text file', @@ -113,7 +113,7 @@ fn test_upto_max_bytes() { } fn test_upto_max_bytes_from_end_option() { - res := os.execute('${executable_under_test} ${test_txt_path} -c -312') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path} -c -312')) assert res.exit_code == 0 assert res.output.split_into_lines().filter(it != '') == [ '[0] Line in test text file', diff --git a/src/mkdir/mkdir_test.v b/src/mkdir/mkdir_test.v index 43ad083f..b6979b57 100644 --- a/src/mkdir/mkdir_test.v +++ b/src/mkdir/mkdir_test.v @@ -49,7 +49,7 @@ fn test_help_and_version() { fn test_default_create_single_dir() { test_dir_to_make := 'testdir' - res := os.execute('${executable_under_test} ${test_dir_to_make}') + res := os.exec(testing.split_args('${executable_under_test} ${test_dir_to_make}')) assert res.exit_code == 0 assert res.output.trim_space() == '' assert testing.check_dir_exists(test_dir_to_make) @@ -60,7 +60,7 @@ fn test_default_create_multiple_dirs() { first_test_dir_to_make := 'testdir' second_test_dir_to_make := 'secondtestdir' res := - os.execute('${executable_under_test} ${first_test_dir_to_make} ${second_test_dir_to_make}') + os.exec(testing.split_args('${executable_under_test} ${first_test_dir_to_make} ${second_test_dir_to_make}')) assert res.exit_code == 0 assert res.output.trim_space() == '' assert testing.check_dir_exists(first_test_dir_to_make) @@ -78,7 +78,7 @@ fn test_default_create_multiple_dirs_with_verbose() { first_test_dir_to_make := 'testdir' second_test_dir_to_make := 'secondtestdir' res := - os.execute('${executable_under_test} -v ${first_test_dir_to_make} ${second_test_dir_to_make}') + os.exec(testing.split_args('${executable_under_test} -v ${first_test_dir_to_make} ${second_test_dir_to_make}')) assert res.exit_code == 0 assert res.output.trim_space() == "mkdir: created directory 'testdir'${eol}mkdir: created directory 'secondtestdir'" assert testing.check_dir_exists(first_test_dir_to_make) @@ -94,7 +94,7 @@ fn test_default_create_multiple_dirs_with_verbose() { fn test_create_dir_with_parents_and_flag() { test_dir_to_make := os.join_path('parent-one', 'child-one', 'last-child') - res := os.execute('${executable_under_test} -p ${test_dir_to_make}') + res := os.exec(testing.split_args('${executable_under_test} -p ${test_dir_to_make}')) assert res.exit_code == 0 assert res.output.trim_space() == '' assert testing.check_dir_exists(test_dir_to_make) @@ -104,7 +104,7 @@ fn test_create_dir_with_parents_and_flag() { fn test_create_dir_with_parents_without_flag_fails() { test_dir_to_make := os.join_path('parent-two', 'child-two', 'last-child') output_path := os.norm_path(test_dir_to_make) - res := os.execute('${executable_under_test} ${test_dir_to_make}') + res := os.exec(testing.split_args('${executable_under_test} ${test_dir_to_make}')) assert res.exit_code == 1 assert res.output.trim_space() == "mkdir: cannot create directory '${output_path}': No such file or directory" assert !testing.check_dir_exists(test_dir_to_make) diff --git a/src/shuf/shuf_test.v b/src/shuf/shuf_test.v index 81fdc1b4..77aff375 100644 --- a/src/shuf/shuf_test.v +++ b/src/shuf/shuf_test.v @@ -15,13 +15,13 @@ fn test_help_and_version() { } fn test_echo() { - res := os.execute('${executable_under_test} -e aa bb') + res := os.exec(testing.split_args('${executable_under_test} -e aa bb')) assert res.output == 'aa${eol}bb${eol}' || res.output == 'bb${eol}aa${eol}' } fn test_file() { os.write_file(test_txt_path, 'hello\nworld!')! - res := os.execute('${executable_under_test} ${test_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} ${test_txt_path}')) assert res.output == 'hello${eol}world!${eol}' || res.output == 'world!${eol}hello${eol}' } @@ -36,13 +36,13 @@ fn test_zero_terminated_file() { } fn test_head_count() { - res := os.execute('${executable_under_test} -n 5 -i 1-10') + res := os.exec(testing.split_args('${executable_under_test} -n 5 -i 1-10')) println(res.output.split_into_lines()) assert res.output.split_into_lines().len == 5 } fn test_input_range() { - res := os.execute('${executable_under_test} -i 1-10') + res := os.exec(testing.split_args('${executable_under_test} -i 1-10')) assert res.output.split_into_lines().len == 10 } @@ -98,7 +98,7 @@ fn test_output_file_matches() { fn test_head_count_zero_outputs_nothing() { os.write_file(test_txt_path, 'a\nb\nc\n')! - res := os.execute('${executable_under_test} -n 0 ${test_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} -n 0 ${test_txt_path}')) assert res.exit_code == 0 assert res.output == '' } @@ -118,6 +118,6 @@ fn test_echo_and_input_range_conflict() { } fn test_unknown_option() ? { - res := os.execute('${executable_under_test} -x') + res := os.exec(testing.split_args('${executable_under_test} -x')) assert res.exit_code == 1 } diff --git a/src/sleep/sleep_test.v b/src/sleep/sleep_test.v index 1cd2a8c4..ec65eec8 100644 --- a/src/sleep/sleep_test.v +++ b/src/sleep/sleep_test.v @@ -14,7 +14,7 @@ fn test_help_and_version() { } fn test_unknown_option() { - res := os.execute('${executable_under_test} -x') + res := os.exec(testing.split_args('${executable_under_test} -x')) assert res.exit_code == 1 } @@ -27,7 +27,7 @@ fn test_invalid_interval() { rig.assert_same_results('1a') rig.assert_same_results('1s0') rig.assert_same_results('0.01 -- -1 0.01 1a 0.01 1s0') - res := os.execute('${executable_under_test} -1.7e+308') + res := os.exec(testing.split_args('${executable_under_test} -1.7e+308')) assert res.exit_code == 1 } @@ -45,7 +45,7 @@ fn test_valid_interval() { fn test_interval() { // 5e-7 * 86400 + 5e-7 * 3600 + 1e-4 * 60 + 1e-3 + 1e-3 = 0.053s = 53ms x1 := time.ticks() - mut result_v := os.execute('${executable_under_test} 0.001 1e-3s 1e-4m 5e-7h 5e-7d') + mut result_v := os.exec(testing.split_args('${executable_under_test} 0.001 1e-3s 1e-4m 5e-7h 5e-7d')) x2 := time.ticks() delta_ms := x2 - x1 assert result_v.exit_code == 0 diff --git a/src/sum/sum_test.v b/src/sum/sum_test.v index ba5fe000..aac7bc16 100644 --- a/src/sum/sum_test.v +++ b/src/sum/sum_test.v @@ -54,14 +54,14 @@ fn testsuite_end() { tests from main branch for completeness */ fn test_bsd() { - res := os.execute('cat ${main_txt} | ${executable_under_test} -r') + res := os.exec(testing.split_args('cat ${main_txt} | ${executable_under_test} -r')) assert res.exit_code == 0 assert res.output == '38039 1${eol}' } fn test_sysv() { - res := os.execute('cat ${main_txt} | ${executable_under_test} -s') + res := os.exec(testing.split_args('cat ${main_txt} | ${executable_under_test} -s')) assert res.exit_code == 0 assert res.output == '25426 1${eol}' @@ -71,28 +71,28 @@ fn test_sysv() { test main SysV switch behavior */ fn test_sysv_stream_succeeds() { - res := os.execute('cat ${test1_txt} | ${executable_under_test} -s') + res := os.exec(testing.split_args('cat ${test1_txt} | ${executable_under_test} -s')) assert res.exit_code == 0 assert res.output == '2185 1${eol}' } fn test_sysv_one_file_succeeds() { - res := os.execute('${executable_under_test} -s ${test1_txt}') + res := os.exec(testing.split_args('${executable_under_test} -s ${test1_txt}')) assert res.exit_code == 0 assert res.output == '2185 1 ${test1_txt}${eol}' } fn test_sysv_repeated_files_not_get_filtered() { - res := os.execute('${executable_under_test} -s ${test1_txt} ${test1_txt} ${test1_txt}') + res := os.exec(testing.split_args('${executable_under_test} -s ${test1_txt} ${test1_txt} ${test1_txt}')) assert res.exit_code == 0 assert res.output == '2185 1 ${test1_txt}${eol}2185 1 ${test1_txt}${eol}2185 1 ${test1_txt}${eol}' } fn test_sysv_several_files_succeeds() { - res := os.execute('${executable_under_test} -s ${test1_txt} ${test2_txt} ${test3_txt}') + res := os.exec(testing.split_args('${executable_under_test} -s ${test1_txt} ${test2_txt} ${test3_txt}')) assert res.exit_code == 0 assert res.output == '2185 1 ${test1_txt}${eol}3372 1 ${test2_txt}${eol}556 1 ${test3_txt}${eol}' @@ -103,9 +103,9 @@ fn sum_arbitrary_value(value string, arg string) !os.Result { f.write_string('${value}\n')! f.close() res := $if windows { - os.execute("cat ${path} | tr -d '\\r' | ${executable_under_test} ${arg}") + os.exec(testing.split_args("cat ${path} | tr -d '\\r' | ${executable_under_test} ${arg}")) } $else { - os.execute('cat ${path} | ${executable_under_test} ${arg}') + os.exec(testing.split_args('cat ${path} | ${executable_under_test} ${arg}')) } os.rm(path)! return res @@ -137,7 +137,7 @@ fn test_sysv_width_4_col_no_padding() { fn test_sysv_different_col_widths_no_alignment() { res := - os.execute('${executable_under_test} -s ${long_line} ${test1_txt} ${test2_txt} ${test3_txt}') + os.exec(testing.split_args('${executable_under_test} -s ${long_line} ${test1_txt} ${test2_txt} ${test3_txt}')) assert res.exit_code == 0 assert res.output == '55583 302 ${long_line}${eol}2185 1 ${test1_txt}${eol}3372 1 ${test2_txt}${eol}556 1 ${test3_txt}${eol}' @@ -147,28 +147,28 @@ fn test_sysv_different_col_widths_no_alignment() { test main BSD switch behavior */ fn test_bsd_sum_stream_succeeds() { - res := os.execute('cat ${test1_txt} | ${executable_under_test} -r') + res := os.exec(testing.split_args('cat ${test1_txt} | ${executable_under_test} -r')) assert res.exit_code == 0 assert res.output == '59852 1${eol}' } fn test_bsd_sum_one_file_succeeds() { - res := os.execute('${executable_under_test} -r ${test1_txt}') + res := os.exec(testing.split_args('${executable_under_test} -r ${test1_txt}')) assert res.exit_code == 0 assert res.output == '59852 1${eol}' } fn test_bsd_sum_repeated_files_not_get_filtered() { - res := os.execute('${executable_under_test} -r ${test1_txt} ${test1_txt} ${test1_txt}') + res := os.exec(testing.split_args('${executable_under_test} -r ${test1_txt} ${test1_txt} ${test1_txt}')) assert res.exit_code == 0 assert res.output == '59852 1 ${test1_txt}${eol}59852 1 ${test1_txt}${eol}59852 1 ${test1_txt}${eol}' } fn test_bsd_sum_several_files_succeeds() { - res := os.execute('${executable_under_test} -r ${test1_txt} ${test2_txt} ${test3_txt}') + res := os.exec(testing.split_args('${executable_under_test} -r ${test1_txt} ${test2_txt} ${test3_txt}')) assert res.exit_code == 0 assert res.output == '59852 1 ${test1_txt}${eol}11628 1 ${test2_txt}${eol}41183 1 ${test3_txt}${eol}' @@ -201,7 +201,7 @@ fn test_bsd_sum_col_width_4_padded_with_zero() { fn test_bsd_block_col_width_more_than_5_not_aligned() { // this test needs 100+MB input string and since there's no easy way to mock block count fn, // we need to create an actual file - res := os.execute('${executable_under_test} -r ${test1_txt} ${large_file} ${test2_txt}') + res := os.exec(testing.split_args('${executable_under_test} -r ${test1_txt} ${large_file} ${test2_txt}')) assert res.exit_code == 0 assert res.output == '59852 1 ${test1_txt}${eol}62707 112640 ${large_file}${eol}11628 1 ${test2_txt}${eol}' } diff --git a/src/tac/tac_test.v b/src/tac/tac_test.v index 671ba152..d2bd9ce1 100644 --- a/src/tac/tac_test.v +++ b/src/tac/tac_test.v @@ -26,7 +26,7 @@ const tac_test_files = { } fn call_for_test(args string) os.Result { - res := os.execute('${rig.executable_under_test} ${args}') + res := os.exec(testing.split_args('${rig.executable_under_test} ${args}')) assert res.exit_code == 0 return res } diff --git a/src/timeout/timeout_test.v b/src/timeout/timeout_test.v index 81bae688..3bad6e92 100644 --- a/src/timeout/timeout_test.v +++ b/src/timeout/timeout_test.v @@ -40,7 +40,7 @@ fn test_timeout_basic() { return } // Timeout occurs - res := os.execute('${executable_under_test} 1 sleep 2') + res := os.exec(testing.split_args('${executable_under_test} 1 sleep 2')) assert res.exit_code == 124 } @@ -49,7 +49,7 @@ fn test_timeout_normal_exit() { return } // Command exits before timeout - res := os.execute('${executable_under_test} 2 sleep 1') + res := os.exec(testing.split_args('${executable_under_test} 2 sleep 1')) assert res.exit_code == 0 } @@ -58,7 +58,7 @@ fn test_timeout_preserve_status() { return } // preserve exit status - res := os.execute('${executable_under_test} --preserve-status 1 sh -c "exit 42"') + res := os.exec(testing.split_args('${executable_under_test} --preserve-status 1 sh -c "exit 42"')) assert res.exit_code == 42 } @@ -67,7 +67,7 @@ fn test_timeout_kill_after() { return } // Kill after - res := os.execute('${executable_under_test} --kill-after=1 0.5 sleep 10') + res := os.exec(testing.split_args('${executable_under_test} --kill-after=1 0.5 sleep 10')) assert res.exit_code == 124 } @@ -76,7 +76,7 @@ fn test_timeout_command_not_found() { return } // Command not found - res := os.execute('${executable_under_test} 1 nonexistentcommand') + res := os.exec(testing.split_args('${executable_under_test} 1 nonexistentcommand')) assert res.exit_code == 127 } @@ -85,7 +85,7 @@ fn test_timeout_invalid_signal() { return } // Invalid signal - res := os.execute('${executable_under_test} --signal=INVALID 1 sleep 1') + res := os.exec(testing.split_args('${executable_under_test} --signal=INVALID 1 sleep 1')) assert res.exit_code == 125 } @@ -94,7 +94,7 @@ fn test_timeout_foreground() { return } // Foreground (should work same as default on most systems) - res := os.execute('${executable_under_test} --foreground 1 sleep 2') + res := os.exec(testing.split_args('${executable_under_test} --foreground 1 sleep 2')) assert res.exit_code == 124 } @@ -103,7 +103,7 @@ fn test_timeout_infinite() { return } // Infinite duration should not timeout - res := os.execute('${executable_under_test} infinity sleep 1') + res := os.exec(testing.split_args('${executable_under_test} infinity sleep 1')) assert res.exit_code == 0 } @@ -112,7 +112,7 @@ fn test_timeout_zero() { return } // Zero duration should not timeout - res := os.execute('${executable_under_test} 0 sleep 1') + res := os.exec(testing.split_args('${executable_under_test} 0 sleep 1')) assert res.exit_code == 0 } @@ -124,7 +124,7 @@ fn test_timeout_permission_denied() { os.write_file('nonexec', '#!/bin/bash\necho test') or {} os.chmod('nonexec', 0o644) or {} defer { os.rm('nonexec') or {} } - res := os.execute('${executable_under_test} 1 ./nonexec') + res := os.exec(testing.split_args('${executable_under_test} 1 ./nonexec')) assert res.exit_code == 126 } @@ -133,7 +133,7 @@ fn test_timeout_invalid_signal_range() { return } // Invalid signal number out of range - res := os.execute('${executable_under_test} --signal=999 1 sleep 1') + res := os.exec(testing.split_args('${executable_under_test} --signal=999 1 sleep 1')) assert res.exit_code == 125 } @@ -142,7 +142,7 @@ fn test_timeout_negative_duration() { return } // Negative duration should error - res := os.execute('${executable_under_test} -1 sleep 1') + res := os.exec(testing.split_args('${executable_under_test} -1 sleep 1')) // Should fail parsing, hopefully ? assert res.exit_code != 0 } diff --git a/src/unexpand/unexpand_test.v b/src/unexpand/unexpand_test.v index 5dc4110d..e0ab2240 100644 --- a/src/unexpand/unexpand_test.v +++ b/src/unexpand/unexpand_test.v @@ -25,32 +25,32 @@ fn write_tmp_file(content string) string { fn test_1() { file := write_tmp_file(' a b c\n') - res := os.execute('${executable_under_test} ${file}') + res := os.exec(testing.split_args('${executable_under_test} ${file}')) assert res.output.bytes() == [u8(9), 97, 32, 32, 32, 32, 32, 32, 32, 98, 32, 32, 32, 32, 32, 32, 32, 99, 10] } fn test_2() { file := write_tmp_file('a\tb\tc\td\te\tf\n') - res := os.execute('${executable_under_test} -t 3,+7 ${file}') + res := os.exec(testing.split_args('${executable_under_test} -t 3,+7 ${file}')) assert res.output.bytes() == [u8(97), 9, 98, 9, 99, 9, 100, 9, 101, 9, 102, 10] } fn test_3() { file := write_tmp_file('a\tb\tc\td\te\tf\n') - res := os.execute('${executable_under_test} -t 3,/7 ${file}') + res := os.exec(testing.split_args('${executable_under_test} -t 3,/7 ${file}')) assert res.output.bytes() == [u8(97), 9, 98, 9, 99, 9, 100, 9, 101, 9, 102, 10] } fn test_4() { file := write_tmp_file('a b c d e\n') - res := os.execute('${executable_under_test} -t 3,7 ${file}') + res := os.exec(testing.split_args('${executable_under_test} -t 3,7 ${file}')) assert res.output.bytes() == [u8(97), 9, 98, 9, 99, 32, 100, 32, 101, 10] } fn test_5() { file := write_tmp_file('cart\bd bard\n') - res := os.execute('${executable_under_test} -a ${file}') + res := os.exec(testing.split_args('${executable_under_test} -a ${file}')) assert res.output.bytes() == [u8(99), 97, 114, 116, 8, 100, 9, 98, 97, 114, 100, 10] } diff --git a/src/wc/wc_test.v b/src/wc/wc_test.v index 23a3f9bd..c33bbdc1 100644 --- a/src/wc/wc_test.v +++ b/src/wc/wc_test.v @@ -44,77 +44,77 @@ fn test_help_and_version() { } fn test_stdin() { - res := os.execute('cat ${test1_txt_path} | ${executable_under_test} -cmwlL') + res := os.exec(testing.split_args('cat ${test1_txt_path} | ${executable_under_test} -cmwlL')) assert res.exit_code == 0 assert res.output.trim_space() == '1 5 25 25 12' } fn test_stdin_file_list() { - res := os.execute('cat ${file_list_path} | ${executable_under_test} -cmwlL --files0-from=-') + res := os.exec(testing.split_args('cat ${file_list_path} | ${executable_under_test} -cmwlL --files0-from=-')) assert res.exit_code == 0 assert res.output.trim_space() == '1 5 25 25 12 ${test1_txt_path}${eol}1 2 26 26 16 ${test2_txt_path}${eol}2 2 28 28 17 ${test3_txt_path}${eol}4 9 79 79 17 total' } fn test_file_file_list() { - res := os.execute('${executable_under_test} -cmwlL --files0-from=${file_list_path}') + res := os.exec(testing.split_args('${executable_under_test} -cmwlL --files0-from=${file_list_path}')) assert res.exit_code == 0 assert res.output.trim_space() == '1 5 25 25 12 ${test1_txt_path}${eol} 1 2 26 26 16 ${test2_txt_path}${eol} 2 2 28 28 17 ${test3_txt_path}${eol} 4 9 79 79 17 total' } fn test_file_not_exist() { - res := os.execute('${executable_under_test} abcd') + res := os.exec(testing.split_args('${executable_under_test} abcd')) assert res.exit_code == 1 assert res.output.trim_space() == 'wc: abcd: No such file or directory' } fn test_default() { - res := os.execute('${executable_under_test} ${test1_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} ${test1_txt_path}')) assert res.exit_code == 0 assert res.output == ' 1 5 25 ${test1_txt_path}${eol}' } fn test_max_line_length() { - res := os.execute('${executable_under_test} -L ${test1_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} -L ${test1_txt_path}')) assert res.exit_code == 0 assert res.output == '12 ${test1_txt_path}${eol}' } fn test_char_count() { - res := os.execute('${executable_under_test} -m ${test1_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} -m ${test1_txt_path}')) assert res.exit_code == 0 assert res.output == '25 ${test1_txt_path}${eol}' } fn test_byte_count() { - res := os.execute('${executable_under_test} -c ${test1_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} -c ${test1_txt_path}')) assert res.exit_code == 0 assert res.output == '25 ${test1_txt_path}${eol}' } fn test_lines_count() { - res := os.execute('${executable_under_test} -l ${test1_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} -l ${test1_txt_path}')) assert res.exit_code == 0 assert res.output == '1 ${test1_txt_path}${eol}' } fn test_words_count() { - res := os.execute('${executable_under_test} -w ${test1_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} -w ${test1_txt_path}')) assert res.exit_code == 0 assert res.output == '5 ${test1_txt_path}${eol}' } fn test_one_file_all_flags() { - res := os.execute('${executable_under_test} -cmwlL ${test1_txt_path}') + res := os.exec(testing.split_args('${executable_under_test} -cmwlL ${test1_txt_path}')) assert res.exit_code == 0 assert res.output == ' 1 5 25 25 12 ${test1_txt_path}${eol}' @@ -122,7 +122,7 @@ fn test_one_file_all_flags() { fn test_several_files_all_flags() { res := - os.execute('${executable_under_test} -cmwlL ${test1_txt_path} ${test2_txt_path} ${test3_txt_path}') + os.exec(testing.split_args('${executable_under_test} -cmwlL ${test1_txt_path} ${test2_txt_path} ${test3_txt_path}')) assert res.exit_code == 0 assert res.output.trim_space() == '1 5 25 25 12 ${test1_txt_path}${eol} 1 2 26 26 16 ${test2_txt_path}${eol} 2 2 28 28 17 ${test3_txt_path}${eol} 4 9 79 79 17 total' @@ -130,35 +130,35 @@ fn test_several_files_all_flags() { fn test_several_same_files_all_flags() { res := - os.execute('${executable_under_test} -cmwlL ${test1_txt_path} ${test1_txt_path} ${test1_txt_path}') + os.exec(testing.split_args('${executable_under_test} -cmwlL ${test1_txt_path} ${test1_txt_path} ${test1_txt_path}')) assert res.exit_code == 0 assert res.output.trim_space() == '1 5 25 25 12 ${test1_txt_path}${eol} 1 5 25 25 12 ${test1_txt_path}${eol} 1 5 25 25 12 ${test1_txt_path}${eol} 3 15 75 75 12 total' } fn test_no_newline_at_end() { - res := os.execute('${executable_under_test} -cmwlL ${dummy}') + res := os.exec(testing.split_args('${executable_under_test} -cmwlL ${dummy}')) assert res.exit_code == 0 assert res.output.trim_space() == '0 1 50 50 50 ${dummy}' } fn test_total_column_wider_than_single_file() { - res := os.execute('${executable_under_test} -cmwlL ${dummy} ${dummy} ${dummy}') + res := os.exec(testing.split_args('${executable_under_test} -cmwlL ${dummy} ${dummy} ${dummy}')) assert res.exit_code == 0 assert res.output.trim_space() == '0 1 50 50 50 ${dummy}${eol} 0 1 50 50 50 ${dummy}${eol} 0 1 50 50 50 ${dummy}${eol} 0 3 150 150 50 total' } fn test_over_16k_line_counts_max_line() { - res := os.execute('${executable_under_test} -cmwlL ${long_over_16k}') + res := os.exec(testing.split_args('${executable_under_test} -cmwlL ${long_over_16k}')) assert res.exit_code == 0 assert res.output.trim_space() == '0 1 16390 16390 16390 ${long_over_16k}' } fn test_under_16k_line_counts_max_line() { - res := os.execute('${executable_under_test} -cmwlL ${long_under_16k}') + res := os.exec(testing.split_args('${executable_under_test} -cmwlL ${long_under_16k}')) assert res.exit_code == 0 assert res.output.trim_space() == '1 2 16401 16401 16383 ${long_under_16k}'