@@ -321,3 +321,126 @@ fn test_single_long_execution() -> Result<()> {
321321
322322 Ok ( ( ) )
323323}
324+
325+ /// Test that a command with shell operators (&&) works correctly when passed as a single argument
326+ #[ test]
327+ fn test_command_with_shell_operators ( ) -> Result < ( ) > {
328+ let exec_opts = exec_harness:: walltime:: ExecutionOptions :: try_from (
329+ exec_harness:: walltime:: WalltimeExecutionArgs {
330+ warmup_time : Some ( "0s" . to_string ( ) ) ,
331+ max_time : None ,
332+ min_time : None ,
333+ max_rounds : Some ( 1 ) ,
334+ min_rounds : None ,
335+ } ,
336+ ) ?;
337+
338+ let tmpdir = TempDir :: new ( ) ?;
339+ let marker_file = tmpdir. path ( ) . join ( "marker.txt" ) ;
340+
341+ // This simulates: bash -c "echo first && echo second > marker.txt"
342+ // The entire "echo first && echo second > marker.txt" should be passed as one argument to -c
343+ let cmd = format ! ( "echo first && echo second > {}" , marker_file. display( ) ) ;
344+
345+ let times = exec_harness:: walltime:: perform (
346+ "test::shell_operators" . to_string ( ) ,
347+ vec ! [ "bash" . to_string( ) , "-c" . to_string( ) , cmd] ,
348+ & exec_opts,
349+ ) ?;
350+
351+ assert_eq ! ( times. len( ) , 1 , "Expected exactly 1 iteration" ) ;
352+
353+ // Verify that the second command (after &&) was executed
354+ assert ! (
355+ marker_file. exists( ) ,
356+ "Marker file should exist - the second part of && was not executed"
357+ ) ;
358+
359+ let content = std:: fs:: read_to_string ( & marker_file) ?;
360+ assert_eq ! (
361+ content. trim( ) ,
362+ "second" ,
363+ "Marker file should contain 'second'"
364+ ) ;
365+
366+ Ok ( ( ) )
367+ }
368+
369+ /// Test that a command with pipes works correctly
370+ #[ test]
371+ fn test_command_with_pipes ( ) -> Result < ( ) > {
372+ let exec_opts = exec_harness:: walltime:: ExecutionOptions :: try_from (
373+ exec_harness:: walltime:: WalltimeExecutionArgs {
374+ warmup_time : Some ( "0s" . to_string ( ) ) ,
375+ max_time : None ,
376+ min_time : None ,
377+ max_rounds : Some ( 1 ) ,
378+ min_rounds : None ,
379+ } ,
380+ ) ?;
381+
382+ let tmpdir = TempDir :: new ( ) ?;
383+ let output_file = tmpdir. path ( ) . join ( "output.txt" ) ;
384+
385+ // This simulates: bash -c "echo 'hello world' | tr 'a-z' 'A-Z' > output.txt"
386+ let cmd = format ! (
387+ "echo 'hello world' | tr 'a-z' 'A-Z' > {}" ,
388+ output_file. display( )
389+ ) ;
390+
391+ let times = exec_harness:: walltime:: perform (
392+ "test::pipes" . to_string ( ) ,
393+ vec ! [ "bash" . to_string( ) , "-c" . to_string( ) , cmd] ,
394+ & exec_opts,
395+ ) ?;
396+
397+ assert_eq ! ( times. len( ) , 1 , "Expected exactly 1 iteration" ) ;
398+
399+ // Verify that the pipe worked correctly
400+ let content = std:: fs:: read_to_string ( & output_file) ?;
401+ assert_eq ! (
402+ content. trim( ) ,
403+ "HELLO WORLD" ,
404+ "Pipe should have transformed text to uppercase"
405+ ) ;
406+
407+ Ok ( ( ) )
408+ }
409+
410+ /// Test that a command with quotes in the argument works correctly
411+ #[ test]
412+ fn test_command_with_embedded_quotes ( ) -> Result < ( ) > {
413+ let exec_opts = exec_harness:: walltime:: ExecutionOptions :: try_from (
414+ exec_harness:: walltime:: WalltimeExecutionArgs {
415+ warmup_time : Some ( "0s" . to_string ( ) ) ,
416+ max_time : None ,
417+ min_time : None ,
418+ max_rounds : Some ( 1 ) ,
419+ min_rounds : None ,
420+ } ,
421+ ) ?;
422+
423+ let tmpdir = TempDir :: new ( ) ?;
424+ let output_file = tmpdir. path ( ) . join ( "output.txt" ) ;
425+
426+ // This simulates: bash -c "echo 'hello world' > output.txt"
427+ let cmd = format ! ( "echo 'hello world' > {}" , output_file. display( ) ) ;
428+
429+ let times = exec_harness:: walltime:: perform (
430+ "test::embedded_quotes" . to_string ( ) ,
431+ vec ! [ "bash" . to_string( ) , "-c" . to_string( ) , cmd] ,
432+ & exec_opts,
433+ ) ?;
434+
435+ assert_eq ! ( times. len( ) , 1 , "Expected exactly 1 iteration" ) ;
436+
437+ // Verify that the quoted string was preserved
438+ let content = std:: fs:: read_to_string ( & output_file) ?;
439+ assert_eq ! (
440+ content. trim( ) ,
441+ "hello world" ,
442+ "Quoted string should be preserved"
443+ ) ;
444+
445+ Ok ( ( ) )
446+ }
0 commit comments