use expect_test::{expect, Expect}; use oyster_parser::ast; fn check(s: &str, expect: Expect) { let actual = ast::Code::try_from(s); expect.assert_debug_eq(&actual); } #[test] fn empty() { check( "", expect![[r#" Ok( Code( [], ), ) "#]], ); } #[test] fn word() { check( "word", expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "word", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn word_with_escape() { check( r"hello\#world", expect![[r##" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "hello", ), Text( "#", ), Text( "world", ), ], ), ], None, ), ], ), ), ], ), ) "##]], ); } #[test] fn unicode() { check( "谚语", expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "谚语", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn simple_command() { check( "echo hi", expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "echo", ), ], ), Word( [ Text( "hi", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn semicolon() { check( "hello; hi", expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "hello", ), ], ), ], None, ), ], ), ), Pipeline( Pipeline( [ Command( [ Word( [ Text( "hi", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn comment() { let source = r"# a # b"; check( source, expect![[r#" Ok( Code( [], ), ) "#]], ); } #[test] fn inline_comment() { check( "whoami # hello", expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "whoami", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn pipeline() { check( "whoami | cat", expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "whoami", ), ], ), ], Stdout, ), Command( [ Word( [ Text( "cat", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn multiline_pipeline() { let source = r"whoami | wc -l"; check( source, expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "whoami", ), ], ), ], Stdout, ), Command( [ Word( [ Text( "wc", ), ], ), Word( [ Text( "-l", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn comment_in_pipeline() { let source = r"whoami | # comment wc -l"; check( source, expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "whoami", ), ], ), ], Stdout, ), Command( [ Word( [ Text( "wc", ), ], ), Word( [ Text( "-l", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn reject_leading_pipe() { let source = r"whoami | cat"; check( source, expect![[r#" Err( UnexpectedPipe, ) "#]], ); } #[test] fn reject_trailing_pipe() { check( "whoami |", expect![[r#" Err( UnexpectedEof, ) "#]], ); } #[test] fn reject_pipe_semicolon() { let source = "whoami | ; cat"; check( source, expect![[r#" Err( UnexpectedSemicolon, ) "#]], ); } #[test] fn reject_double_pipe() { check( "whoami | | cat", expect![[r#" Err( UnexpectedPipe, ) "#]], ); } #[test] fn double_quote_string() { check( r#""hello world""#, expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "hello world", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn escaped_char_in_double_quotes() { check( r#""hello \" world""#, expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "hello ", ), Text( "\"", ), Text( " world", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn unterminated_double_quotes() { check( r#""hello world"#, expect![[r#" Err( UnexpectedEof, ) "#]], ); } #[test] fn command_substitution() { check( r#"echo (whoami)"#, expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "echo", ), ], ), Word( [ CommandSubstitution( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "whoami", ), ], ), ], None, ), ], ), ), ], ), ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn quoted_command_substitution() { let source = r#"echo "(whoami) ""#; check( source, expect![[r#" Ok( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "echo", ), ], ), Word( [ CommandSubstitution( Code( [ Pipeline( Pipeline( [ Command( [ Word( [ Text( "whoami", ), ], ), ], None, ), ], ), ), ], ), ), Text( "\n ", ), ], ), ], None, ), ], ), ), ], ), ) "#]], ); } #[test] fn empty_pipeline() { check( ";", expect![[r#" Ok( Code( [], ), ) "#]], ); }