@@ -4,6 +4,8 @@ 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 rstest_reuse:: { self , * } ;
8+ use shell_quote:: { Bash , QuoteRefExt } ;
79use tempfile:: TempDir ;
810use tokio:: sync:: { OnceCell , Semaphore , SemaphorePermit } ;
911
@@ -19,21 +21,97 @@ const DIRECTORY_CHECK_SCRIPT: &str = "cd /tmp
1921if [ $(basename $(pwd)) != \" tmp\" ]; then
2022 exit 1
2123fi" ;
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
2740fi" ;
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\n Line 2\t Tabbed\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+
37115async 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