@@ -4,6 +4,7 @@ use crate::run::runner::executor::Executor;
44use crate :: run:: runner:: interfaces:: RunData ;
55use crate :: run:: runner:: valgrind:: executor:: ValgrindExecutor ;
66use crate :: run:: { RunnerMode , runner:: wall_time:: executor:: WallTimeExecutor } ;
7+ use shell_quote:: { Bash , QuoteRefExt } ;
78use tempfile:: TempDir ;
89use tokio:: sync:: { OnceCell , Semaphore , SemaphorePermit } ;
910
@@ -19,19 +20,66 @@ const DIRECTORY_CHECK_SCRIPT: &str = "cd /tmp
1920if [ $(basename $(pwd)) != \" tmp\" ]; then
2021 exit 1
2122fi" ;
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
2739fi" ;
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\n Line 2\t Tabbed\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
3785async 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