@@ -499,4 +499,100 @@ mod tests {
499499 let exit_code = execute_external ( "echo" , & [ "hello" . to_string ( ) ] ) . unwrap ( ) ;
500500 assert_eq ! ( exit_code, 0 , "echo should return 0" ) ;
501501 }
502+
503+ #[ test]
504+ fn test_pipeline_simple ( ) {
505+ // Test simple 2-stage pipeline: true | true
506+ use tempfile:: TempDir ;
507+ let temp = TempDir :: new ( ) . unwrap ( ) ;
508+ let mut state = crate :: state:: ShellState :: new ( temp. path ( ) . to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
509+
510+ let stages = vec ! [
511+ ( "true" . to_string( ) , vec![ ] ) ,
512+ ( "true" . to_string( ) , vec![ ] ) ,
513+ ] ;
514+ let exit_code = execute_pipeline ( & stages, & [ ] , & mut state) . unwrap ( ) ;
515+ assert_eq ! ( exit_code, 0 , "true | true should return 0" ) ;
516+ }
517+
518+ #[ test]
519+ fn test_pipeline_exit_code ( ) {
520+ // Test that pipeline returns exit code from last stage
521+ use tempfile:: TempDir ;
522+ let temp = TempDir :: new ( ) . unwrap ( ) ;
523+ let mut state = crate :: state:: ShellState :: new ( temp. path ( ) . to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
524+
525+ let stages = vec ! [
526+ ( "true" . to_string( ) , vec![ ] ) ,
527+ ( "false" . to_string( ) , vec![ ] ) ,
528+ ] ;
529+ let exit_code = execute_pipeline ( & stages, & [ ] , & mut state) . unwrap ( ) ;
530+ assert_eq ! ( exit_code, 1 , "true | false should return 1 (from false)" ) ;
531+ }
532+
533+ #[ test]
534+ fn test_pipeline_three_stages ( ) {
535+ // Test 3-stage pipeline
536+ use tempfile:: TempDir ;
537+ let temp = TempDir :: new ( ) . unwrap ( ) ;
538+ let mut state = crate :: state:: ShellState :: new ( temp. path ( ) . to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
539+
540+ let stages = vec ! [
541+ ( "echo" . to_string( ) , vec![ "hello" . to_string( ) ] ) ,
542+ ( "cat" . to_string( ) , vec![ ] ) ,
543+ ( "cat" . to_string( ) , vec![ ] ) ,
544+ ] ;
545+ let exit_code = execute_pipeline ( & stages, & [ ] , & mut state) . unwrap ( ) ;
546+ assert_eq ! ( exit_code, 0 , "echo hello | cat | cat should return 0" ) ;
547+ }
548+
549+ #[ test]
550+ fn test_pipeline_with_redirect ( ) {
551+ // Test pipeline with output redirection
552+ use tempfile:: TempDir ;
553+ use std:: fs;
554+ let temp = TempDir :: new ( ) . unwrap ( ) ;
555+ let mut state = crate :: state:: ShellState :: new ( temp. path ( ) . to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
556+
557+ let stages = vec ! [
558+ ( "echo" . to_string( ) , vec![ "test" . to_string( ) ] ) ,
559+ ( "cat" . to_string( ) , vec![ ] ) ,
560+ ] ;
561+ let redirects = vec ! [ crate :: redirection:: Redirection :: Output {
562+ file: "output.txt" . to_string( ) ,
563+ } ] ;
564+ let exit_code = execute_pipeline ( & stages, & redirects, & mut state) . unwrap ( ) ;
565+ assert_eq ! ( exit_code, 0 , "Pipeline with redirect should return 0" ) ;
566+
567+ // Verify file was created
568+ let output_file = temp. path ( ) . join ( "output.txt" ) ;
569+ assert ! ( output_file. exists( ) , "Output file should be created" ) ;
570+
571+ let content = fs:: read_to_string ( output_file) . unwrap ( ) ;
572+ assert_eq ! ( content. trim( ) , "test" , "Output should be 'test'" ) ;
573+ }
574+
575+ #[ test]
576+ fn test_pipeline_error_empty_stages ( ) {
577+ // Test that empty stages array returns error
578+ use tempfile:: TempDir ;
579+ let temp = TempDir :: new ( ) . unwrap ( ) ;
580+ let mut state = crate :: state:: ShellState :: new ( temp. path ( ) . to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
581+
582+ let stages: Vec < ( String , Vec < String > ) > = vec ! [ ] ;
583+ let result = execute_pipeline ( & stages, & [ ] , & mut state) ;
584+ assert ! ( result. is_err( ) , "Empty pipeline should return error" ) ;
585+ }
586+
587+ #[ test]
588+ fn test_pipeline_single_stage_delegates ( ) {
589+ // Test that single-stage pipeline delegates to execute_external_with_redirects
590+ use tempfile:: TempDir ;
591+ let temp = TempDir :: new ( ) . unwrap ( ) ;
592+ let mut state = crate :: state:: ShellState :: new ( temp. path ( ) . to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
593+
594+ let stages = vec ! [ ( "true" . to_string( ) , vec![ ] ) ] ;
595+ let exit_code = execute_pipeline ( & stages, & [ ] , & mut state) . unwrap ( ) ;
596+ assert_eq ! ( exit_code, 0 , "Single-stage pipeline should work" ) ;
597+ }
502598}
0 commit comments