Skip to content

Commit 5ff1b29

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

3 files changed

Lines changed: 133 additions & 35 deletions

File tree

Cargo.lock

Lines changed: 33 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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ temp-env = { version = "0.3.6", features = ["async_closure"] }
6363
insta = { version = "1.29.0", features = ["json", "redactions"] }
6464
test-with = { version = "0.15", default-features = false, features = [] }
6565
rstest = { version = "0.25.0", default-features = false }
66+
rstest_reuse = "0.7.0"
67+
shell-quote = "0.7.2"
6668

6769
[workspace.metadata.release]
6870
sign-tag = true

src/run/runner/tests.rs

Lines changed: 98 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ 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 rstest_reuse::{self, *};
8+
use shell_quote::{Bash, QuoteRefExt};
79
use tempfile::TempDir;
810
use tokio::sync::{OnceCell, Semaphore, SemaphorePermit};
911

@@ -19,21 +21,97 @@ const DIRECTORY_CHECK_SCRIPT: &str = "cd /tmp
1921
if [ $(basename $(pwd)) != \"tmp\" ]; then
2022
exit 1
2123
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'\"
24+
const QUOTE_ESCAPE_SCRIPT: &str = "#!/bin/bash
25+
VALUE=\"He said \\\"Hello 'world'\\\" & echo \\$HOME\"
26+
if [ \"$VALUE\" = \"He said \\\"Hello 'world'\\\" & echo \\$HOME\" ]; then
27+
echo \"Quote test passed\"
28+
else
29+
echo \"ERROR: Quote handling failed\"
30+
exit 1
31+
fi";
32+
const COMMAND_SUBSTITUTION_SCRIPT: &str = "#!/bin/bash
33+
RESULT=$(echo \"test 'nested' \\\"quotes\\\" here\")
34+
COUNT=$(echo \"$RESULT\" | wc -w)
35+
if [ \"$COUNT\" -eq \"4\" ]; then
36+
echo \"Command substitution test passed\"
37+
else
38+
echo \"ERROR: Expected 4 words, got $COUNT\"
2639
exit 1
2740
fi";
2841

29-
const TESTS: [&str; 5] = [
42+
const TESTS: [&str; 6] = [
3043
SIMPLE_ECHO_SCRIPT,
3144
MULTILINE_ECHO_SCRIPT,
3245
MULTILINE_ECHO_WITH_SEMICOLONS,
3346
DIRECTORY_CHECK_SCRIPT,
34-
ENV_VAR_VALIDATION_SCRIPT,
47+
QUOTE_ESCAPE_SCRIPT,
48+
COMMAND_SUBSTITUTION_SCRIPT,
3549
];
3650

51+
fn env_var_validation_script(env: &str, expected: &str) -> String {
52+
let expected: String = expected.quoted(Bash);
53+
format!(
54+
r#"
55+
if [ "${env}" != {expected} ]; then
56+
echo "FAIL: Environment variable not set correctly"
57+
echo "Got: '${env}'"
58+
exit 1
59+
fi
60+
"#
61+
)
62+
}
63+
64+
const ENV_TESTS: [(&str, &str); 8] = [
65+
(
66+
"quotes_and_escapes",
67+
r#""'He said "Hello 'world' `date`" & echo "done" with \\n\\t\\"#,
68+
),
69+
(
70+
"multiline_and_whitespace",
71+
"Line 1\nLine 2\tTabbed\n \t ",
72+
),
73+
(
74+
"shell_metacharacters",
75+
r#"*.txt | grep "test" && echo "found" || echo "error" ; ls > /tmp/out"#,
76+
),
77+
(
78+
"variables_and_commands",
79+
r#"$HOME ${PATH} $((1+1)) $(echo "embedded") VAR="value with spaces""#,
80+
),
81+
(
82+
"unicode_and_special",
83+
"🚀 café naïve\u{200b}hidden\x1b[31mRed\x1b[0m\x01\x02",
84+
),
85+
(
86+
"complex_mixed",
87+
r#"start'single'middle"double"end $VAR | cmd && echo "done" || fail"#,
88+
),
89+
("empty", ""),
90+
("space_only", " "),
91+
];
92+
93+
#[template]
94+
#[rstest::rstest]
95+
#[case(TESTS[0])]
96+
#[case(TESTS[1])]
97+
#[case(TESTS[2])]
98+
#[case(TESTS[3])]
99+
#[case(TESTS[4])]
100+
#[case(TESTS[5])]
101+
fn test_cases(#[case] cmd: &str) {}
102+
103+
#[template]
104+
#[rstest::rstest]
105+
#[case(ENV_TESTS[0])]
106+
#[case(ENV_TESTS[1])]
107+
#[case(ENV_TESTS[2])]
108+
#[case(ENV_TESTS[3])]
109+
#[case(ENV_TESTS[4])]
110+
#[case(ENV_TESTS[5])]
111+
#[case(ENV_TESTS[6])]
112+
#[case(ENV_TESTS[7])]
113+
fn env_test_cases(#[case] env_case: (&str, &str)) {}
114+
37115
async fn create_test_setup() -> (SystemInfo, RunData, TempDir) {
38116
let system_info = SystemInfo::new().unwrap();
39117

@@ -68,11 +146,7 @@ mod valgrind {
68146
}
69147
}
70148

71-
#[rstest::rstest]
72-
#[case(TESTS[0])]
73-
#[case(TESTS[1])]
74-
#[case(TESTS[2])]
75-
#[case(TESTS[3])]
149+
#[apply(test_cases)]
76150
#[tokio::test]
77151
async fn test_valgrind_executor(#[case] cmd: &str) {
78152
let (system_info, run_data, _temp_dir) = create_test_setup().await;
@@ -85,19 +159,16 @@ mod valgrind {
85159
.unwrap();
86160
}
87161

88-
#[rstest::rstest]
89-
#[case("MY_ENV_VAR", "Hello", ENV_VAR_VALIDATION_SCRIPT)]
162+
#[apply(env_test_cases)]
90163
#[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-
) {
164+
async fn test_valgrind_executor_with_env(#[case] env_case: (&str, &str)) {
96165
let (system_info, run_data, _temp_dir) = create_test_setup().await;
97166
let executor = get_valgrind_executor().await;
98167

168+
let (env_var, env_value) = env_case;
99169
temp_env::async_with_vars(&[(env_var, Some(env_value))], async {
100-
let config = valgrind_config(cmd);
170+
let cmd = env_var_validation_script(env_var, env_value);
171+
let config = valgrind_config(&cmd);
101172
executor
102173
.run(&config, &system_info, &run_data, &None)
103174
.await
@@ -141,17 +212,10 @@ mod walltime {
141212
}
142213
}
143214

215+
#[apply(test_cases)]
144216
#[rstest::rstest]
145-
#[case(TESTS[0], false)]
146-
#[case(TESTS[0], true)]
147-
#[case(TESTS[1], false)]
148-
#[case(TESTS[1], true)]
149-
#[case(TESTS[2], false)]
150-
#[case(TESTS[2], true)]
151-
#[case(TESTS[3], false)]
152-
#[case(TESTS[3], true)]
153217
#[tokio::test]
154-
async fn test_walltime_executor(#[case] cmd: &str, #[case] enable_perf: bool) {
218+
async fn test_walltime_executor(#[case] cmd: &str, #[values(false, true)] enable_perf: bool) {
155219
let (system_info, run_data, _temp_dir) = create_test_setup().await;
156220
let (_permit, executor) = get_walltime_executor().await;
157221

@@ -162,21 +226,20 @@ mod walltime {
162226
.unwrap();
163227
}
164228

229+
#[apply(env_test_cases)]
165230
#[rstest::rstest]
166-
#[case("MY_ENV_VAR", "Hello", ENV_VAR_VALIDATION_SCRIPT, false)]
167-
#[case("MY_ENV_VAR", "Hello", ENV_VAR_VALIDATION_SCRIPT, true)]
168231
#[tokio::test]
169232
async fn test_walltime_executor_with_env(
170-
#[case] env_var: &str,
171-
#[case] env_value: &str,
172-
#[case] cmd: &str,
173-
#[case] enable_perf: bool,
233+
#[case] env_case: (&str, &str),
234+
#[values(false, true)] enable_perf: bool,
174235
) {
175236
let (system_info, run_data, _temp_dir) = create_test_setup().await;
176237
let (_permit, executor) = get_walltime_executor().await;
177238

239+
let (env_var, env_value) = env_case;
178240
temp_env::async_with_vars(&[(env_var, Some(env_value))], async {
179-
let config = walltime_config(cmd, enable_perf);
241+
let cmd = env_var_validation_script(env_var, env_value);
242+
let config = walltime_config(&cmd, enable_perf);
180243
executor
181244
.run(&config, &system_info, &run_data, &None)
182245
.await

0 commit comments

Comments
 (0)