Skip to content

Commit 26af3ce

Browse files
committed
chore: add complex cmd and env tests
1 parent 73c2d7b commit 26af3ce

3 files changed

Lines changed: 114 additions & 19 deletions

File tree

Cargo.lock

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ debugid = "0.8.0"
5454
memmap2 = "0.9.5"
5555
nix = { version = "0.29.0", features = ["fs", "user"] }
5656
futures = "0.3.31"
57+
shell-quote = "0.7.2"
5758

5859
[target.'cfg(target_os = "linux")'.dependencies]
5960
procfs = "0.17.0"

src/run/runner/tests.rs

Lines changed: 92 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::run::runner::executor::Executor;
44
use crate::run::runner::interfaces::RunData;
55
use crate::run::runner::valgrind::executor::ValgrindExecutor;
66
use crate::run::{RunnerMode, runner::wall_time::executor::WallTimeExecutor};
7+
use shell_quote::{Bash, QuoteRefExt};
78
use tempfile::TempDir;
89
use tokio::sync::{OnceCell, Semaphore, SemaphorePermit};
910

@@ -19,19 +20,66 @@ const DIRECTORY_CHECK_SCRIPT: &str = "cd /tmp
1920
if [ $(basename $(pwd)) != \"tmp\" ]; then
2021
exit 1
2122
fi";
22-
const ENV_VAR_VALIDATION_SCRIPT: &str = "
23-
output=$(echo \"$MY_ENV_VAR\")
24-
if [ \"$output\" != \"Hello\" ]; then
25-
echo \"Assertion failed: Expected 'Hello' but got '$output'\"
23+
const QUOTE_ESCAPE_SCRIPT: &str = "#!/bin/bash
24+
VALUE=\"He said \\\"Hello 'world'\\\" & echo \\$HOME\"
25+
if [ \"$VALUE\" = \"He said \\\"Hello 'world'\\\" & echo \\$HOME\" ]; then
26+
echo \"Quote test passed\"
27+
else
28+
echo \"ERROR: Quote handling failed\"
29+
exit 1
30+
fi";
31+
const COMMAND_SUBSTITUTION_SCRIPT: &str = "#!/bin/bash
32+
RESULT=$(echo \"test 'nested' \\\"quotes\\\" here\")
33+
COUNT=$(echo \"$RESULT\" | wc -w)
34+
if [ \"$COUNT\" -eq \"4\" ]; then
35+
echo \"Command substitution test passed\"
36+
else
37+
echo \"ERROR: Expected 4 words, got $COUNT\"
2638
exit 1
2739
fi";
2840

29-
const TESTS: [&str; 5] = [
41+
const TESTS: [&str; 6] = [
3042
SIMPLE_ECHO_SCRIPT,
3143
MULTILINE_ECHO_SCRIPT,
3244
MULTILINE_ECHO_WITH_SEMICOLONS,
3345
DIRECTORY_CHECK_SCRIPT,
34-
ENV_VAR_VALIDATION_SCRIPT,
46+
QUOTE_ESCAPE_SCRIPT,
47+
COMMAND_SUBSTITUTION_SCRIPT,
48+
];
49+
50+
fn env_var_validation_script(env: &str, expected: &str) -> String {
51+
let expected: String = expected.quoted(Bash);
52+
format!(
53+
r#"
54+
if [ "${env}" != {expected} ]; then
55+
echo "FAIL: Environment variable not set correctly"
56+
echo "Got: '${env}'"
57+
exit 1
58+
fi
59+
"#
60+
)
61+
}
62+
63+
const QUOTES_AND_ESCAPES: &str = r#""'He said "Hello 'world' `date`" & echo "done" with \\n\\t\\"#;
64+
const MULTILINE_AND_WHITESPACE: &str = "Line 1\nLine 2\tTabbed\n \t ";
65+
const SHELL_METACHARACTERS: &str =
66+
r#"*.txt | grep "test" && echo "found" || echo "error" ; ls > /tmp/out"#;
67+
const VARIABLES_AND_COMMANDS: &str =
68+
r#"$HOME ${PATH} $((1+1)) $(echo "embedded") VAR="value with spaces""#;
69+
const UNICODE_AND_SPECIAL: &str = "🚀 café naïve\u{200b}hidden\x1b[31mRed\x1b[0m\x01\x02";
70+
const COMPLEX_MIXED: &str = r#"start'single'middle"double"end $VAR | cmd && echo "done" || fail"#;
71+
const EMPTY: &str = "";
72+
const SPACE_ONLY: &str = " ";
73+
74+
const ENV_TESTS: [(&str, &str); 8] = [
75+
("quotes_and_escapes", QUOTES_AND_ESCAPES),
76+
("multiline_and_whitespace", MULTILINE_AND_WHITESPACE),
77+
("shell_metacharacters", SHELL_METACHARACTERS),
78+
("variables_and_commands", VARIABLES_AND_COMMANDS),
79+
("unicode_and_special", UNICODE_AND_SPECIAL),
80+
("complex_mixed", COMPLEX_MIXED),
81+
("empty", EMPTY),
82+
("space_only", SPACE_ONLY),
3583
];
3684

3785
async fn create_test_setup() -> (SystemInfo, RunData, TempDir) {
@@ -73,6 +121,8 @@ mod valgrind {
73121
#[case(TESTS[1])]
74122
#[case(TESTS[2])]
75123
#[case(TESTS[3])]
124+
#[case(TESTS[4])]
125+
#[case(TESTS[5])]
76126
#[tokio::test]
77127
async fn test_valgrind_executor(#[case] cmd: &str) {
78128
let (system_info, run_data, _temp_dir) = create_test_setup().await;
@@ -86,18 +136,23 @@ mod valgrind {
86136
}
87137

88138
#[rstest::rstest]
89-
#[case("MY_ENV_VAR", "Hello", ENV_VAR_VALIDATION_SCRIPT)]
139+
#[case(ENV_TESTS[0])]
140+
#[case(ENV_TESTS[1])]
141+
#[case(ENV_TESTS[2])]
142+
#[case(ENV_TESTS[3])]
143+
#[case(ENV_TESTS[4])]
144+
#[case(ENV_TESTS[5])]
145+
#[case(ENV_TESTS[6])]
146+
#[case(ENV_TESTS[7])]
90147
#[tokio::test]
91-
async fn test_valgrind_executor_with_env(
92-
#[case] env_var: &str,
93-
#[case] env_value: &str,
94-
#[case] cmd: &str,
95-
) {
148+
async fn test_valgrind_executor_with_env(#[case] env_case: (&str, &str)) {
96149
let (system_info, run_data, _temp_dir) = create_test_setup().await;
97150
let executor = get_valgrind_executor().await;
98151

152+
let (env_var, env_value) = env_case;
99153
temp_env::async_with_vars(&[(env_var, Some(env_value))], async {
100-
let config = valgrind_config(cmd);
154+
let cmd = env_var_validation_script(env_var, env_value);
155+
let config = valgrind_config(&cmd);
101156
executor
102157
.run(&config, &system_info, &run_data, &None)
103158
.await
@@ -150,6 +205,10 @@ mod walltime {
150205
#[case(TESTS[2], true)]
151206
#[case(TESTS[3], false)]
152207
#[case(TESTS[3], true)]
208+
#[case(TESTS[4], false)]
209+
#[case(TESTS[4], true)]
210+
#[case(TESTS[5], false)]
211+
#[case(TESTS[5], true)]
153212
#[tokio::test]
154213
async fn test_walltime_executor(#[case] cmd: &str, #[case] enable_perf: bool) {
155214
let (system_info, run_data, _temp_dir) = create_test_setup().await;
@@ -163,20 +222,34 @@ mod walltime {
163222
}
164223

165224
#[rstest::rstest]
166-
#[case("MY_ENV_VAR", "Hello", ENV_VAR_VALIDATION_SCRIPT, false)]
167-
#[case("MY_ENV_VAR", "Hello", ENV_VAR_VALIDATION_SCRIPT, true)]
225+
#[case(ENV_TESTS[0], false)]
226+
#[case(ENV_TESTS[0], true)]
227+
#[case(ENV_TESTS[1], false)]
228+
#[case(ENV_TESTS[1], true)]
229+
#[case(ENV_TESTS[2], false)]
230+
#[case(ENV_TESTS[2], true)]
231+
#[case(ENV_TESTS[3], false)]
232+
#[case(ENV_TESTS[3], true)]
233+
#[case(ENV_TESTS[4], false)]
234+
#[case(ENV_TESTS[4], true)]
235+
#[case(ENV_TESTS[5], false)]
236+
#[case(ENV_TESTS[5], true)]
237+
#[case(ENV_TESTS[6], false)]
238+
#[case(ENV_TESTS[6], true)]
239+
#[case(ENV_TESTS[7], false)]
240+
#[case(ENV_TESTS[7], true)]
168241
#[tokio::test]
169242
async fn test_walltime_executor_with_env(
170-
#[case] env_var: &str,
171-
#[case] env_value: &str,
172-
#[case] cmd: &str,
243+
#[case] env_case: (&str, &str),
173244
#[case] enable_perf: bool,
174245
) {
175246
let (system_info, run_data, _temp_dir) = create_test_setup().await;
176247
let (_permit, executor) = get_walltime_executor().await;
177248

249+
let (env_var, env_value) = env_case;
178250
temp_env::async_with_vars(&[(env_var, Some(env_value))], async {
179-
let config = walltime_config(cmd, enable_perf);
251+
let cmd = env_var_validation_script(env_var, env_value);
252+
let config = walltime_config(&cmd, enable_perf);
180253
executor
181254
.run(&config, &system_info, &run_data, &None)
182255
.await

0 commit comments

Comments
 (0)