2022-10-26 19:31:39 +00:00
|
|
|
use expect_test::{expect, Expect};
|
|
|
|
use oyster_parser::ast;
|
2022-10-21 17:29:42 +00:00
|
|
|
use oyster_runtime::Shell;
|
2022-09-15 20:16:37 +00:00
|
|
|
|
2022-11-02 15:33:29 +00:00
|
|
|
use crate::collect_output;
|
2022-09-15 20:16:37 +00:00
|
|
|
|
2022-11-02 15:33:29 +00:00
|
|
|
// TODO: test signal return codes
|
2022-10-26 19:31:39 +00:00
|
|
|
|
2022-11-02 15:33:29 +00:00
|
|
|
fn check(ast: &ast::Code, expect: Expect) {
|
2022-10-26 19:31:39 +00:00
|
|
|
let actual = collect_output(|| {
|
|
|
|
let mut shell = Shell::new().unwrap();
|
|
|
|
shell.run(ast).unwrap();
|
|
|
|
});
|
|
|
|
expect.assert_debug_eq(&actual);
|
|
|
|
}
|
|
|
|
|
2022-09-15 20:16:37 +00:00
|
|
|
#[test]
|
|
|
|
fn simple_command() {
|
|
|
|
let ast = {
|
|
|
|
use oyster_parser::ast::*;
|
|
|
|
|
|
|
|
Code(vec![Statement::Pipeline(Pipeline(vec![Command(
|
|
|
|
vec![
|
|
|
|
Word(vec![WordPart::Text("echo")]),
|
|
|
|
Word(vec![WordPart::Text("hi")]),
|
|
|
|
],
|
|
|
|
Redirect::None,
|
|
|
|
)]))])
|
|
|
|
};
|
|
|
|
|
2022-11-02 15:33:29 +00:00
|
|
|
check(
|
2022-10-26 19:31:39 +00:00
|
|
|
&ast,
|
|
|
|
expect![[r#"
|
2022-11-05 13:32:38 +00:00
|
|
|
"hi\r\n"
|
|
|
|
"#]],
|
2022-10-26 19:31:39 +00:00
|
|
|
);
|
2022-09-15 20:16:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn pipeline() {
|
|
|
|
let ast = {
|
|
|
|
use oyster_parser::ast::*;
|
|
|
|
|
|
|
|
Code(vec![Statement::Pipeline(Pipeline(vec![
|
|
|
|
Command(
|
|
|
|
vec![
|
|
|
|
Word(vec![WordPart::Text("echo")]),
|
|
|
|
Word(vec![WordPart::Text("hi")]),
|
|
|
|
],
|
|
|
|
Redirect::Stdout,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
vec![
|
|
|
|
Word(vec![WordPart::Text("wc")]),
|
|
|
|
Word(vec![WordPart::Text("-c")]),
|
|
|
|
],
|
|
|
|
Redirect::None,
|
|
|
|
),
|
|
|
|
]))])
|
|
|
|
};
|
|
|
|
|
2022-11-02 15:33:29 +00:00
|
|
|
check(
|
2022-10-26 19:31:39 +00:00
|
|
|
&ast,
|
|
|
|
expect![[r#"
|
|
|
|
"3\r\n"
|
|
|
|
"#]],
|
|
|
|
);
|
2022-09-15 20:16:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn command_not_found() {
|
|
|
|
let ast = {
|
|
|
|
use oyster_parser::ast::*;
|
|
|
|
|
|
|
|
Code(vec![Statement::Pipeline(Pipeline(vec![Command(
|
|
|
|
vec![Word(vec![WordPart::Text("this_command_doesnt_exist")])],
|
|
|
|
Redirect::None,
|
|
|
|
)]))])
|
|
|
|
};
|
|
|
|
|
|
|
|
// XXX: this relies on the command actually not existing, as unsetting PATH is rather complex
|
2022-09-23 21:07:57 +00:00
|
|
|
let mut shell = Shell::new().unwrap();
|
2022-09-15 20:16:37 +00:00
|
|
|
let actual = shell.run(&ast);
|
|
|
|
|
2022-10-26 19:31:39 +00:00
|
|
|
let expect = expect![[r#"
|
|
|
|
Err(
|
|
|
|
CommandNotFound(
|
|
|
|
"this_command_doesnt_exist",
|
|
|
|
),
|
|
|
|
)
|
|
|
|
"#]];
|
|
|
|
expect.assert_debug_eq(&actual);
|
2022-09-15 20:16:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn permission_denied() {
|
|
|
|
let ast = {
|
|
|
|
use oyster_parser::ast::*;
|
|
|
|
|
|
|
|
Code(vec![Statement::Pipeline(Pipeline(vec![Command(
|
|
|
|
vec![Word(vec![WordPart::Text("/")])],
|
|
|
|
Redirect::None,
|
|
|
|
)]))])
|
|
|
|
};
|
|
|
|
|
2022-09-23 21:07:57 +00:00
|
|
|
let mut shell = Shell::new().unwrap();
|
2022-09-15 20:16:37 +00:00
|
|
|
let actual = shell.run(&ast);
|
|
|
|
|
2022-10-26 19:31:39 +00:00
|
|
|
let expect = expect![[r#"
|
|
|
|
Err(
|
|
|
|
PermissionDenied(
|
|
|
|
"/",
|
|
|
|
),
|
|
|
|
)
|
|
|
|
"#]];
|
|
|
|
expect.assert_debug_eq(&actual);
|
2022-09-15 20:16:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn multipart_word() {
|
|
|
|
let ast = {
|
|
|
|
use oyster_parser::ast::*;
|
|
|
|
|
|
|
|
Code(vec![Statement::Pipeline(Pipeline(vec![Command(
|
|
|
|
vec![
|
|
|
|
Word(vec![WordPart::Text("ec"), WordPart::Text("ho")]),
|
|
|
|
Word(vec![WordPart::Text("hel"), WordPart::Text("lo")]),
|
|
|
|
],
|
|
|
|
Redirect::None,
|
|
|
|
)]))])
|
|
|
|
};
|
|
|
|
|
2022-11-02 15:33:29 +00:00
|
|
|
check(
|
2022-10-26 19:31:39 +00:00
|
|
|
&ast,
|
|
|
|
expect![[r#"
|
|
|
|
"hello\r\n"
|
|
|
|
"#]],
|
|
|
|
);
|
2022-09-15 20:16:37 +00:00
|
|
|
}
|
2022-10-20 13:06:53 +00:00
|
|
|
|
2022-10-24 19:27:04 +00:00
|
|
|
#[test]
|
|
|
|
fn command_substitution() {
|
|
|
|
let ast = {
|
|
|
|
use oyster_parser::ast::*;
|
|
|
|
|
|
|
|
Code(vec![Statement::Pipeline(Pipeline(vec![Command(
|
|
|
|
vec![
|
|
|
|
Word(vec![WordPart::Text("echo")]),
|
|
|
|
Word(vec![WordPart::CommandSubstitution(Code(vec![
|
|
|
|
Statement::Pipeline(Pipeline(vec![Command(
|
|
|
|
vec![
|
|
|
|
Word(vec![WordPart::Text("echo")]),
|
|
|
|
Word(vec![WordPart::Text("hello")]),
|
|
|
|
],
|
|
|
|
Redirect::None,
|
|
|
|
)])),
|
|
|
|
]))]),
|
|
|
|
],
|
|
|
|
Redirect::None,
|
|
|
|
)]))])
|
|
|
|
};
|
|
|
|
|
2022-11-02 15:33:29 +00:00
|
|
|
check(
|
2022-10-26 19:31:39 +00:00
|
|
|
&ast,
|
|
|
|
expect![[r#"
|
2022-11-05 13:32:38 +00:00
|
|
|
"hello\r\n"
|
|
|
|
"#]],
|
2022-10-26 19:31:39 +00:00
|
|
|
);
|
2022-10-24 19:27:04 +00:00
|
|
|
}
|