Backtick tests done!
This commit is contained in:
parent
21320d36ee
commit
25c6432fa3
9
notes
9
notes
@ -1,15 +1,6 @@
|
||||
notes
|
||||
-----
|
||||
|
||||
- unit tests for as many backtick error types as possible
|
||||
- integration tests for as many error types as possible, errors should underline backtick token
|
||||
- test shebang recipe `` evaluation order
|
||||
make sure that nothing happens if a `` fails on a later line
|
||||
- test command recipe `` evaluation order
|
||||
do some stuff, then have a line with a `` that fails
|
||||
make sure that stuff before that actually happened
|
||||
make sure that result error code is correct
|
||||
|
||||
- --debug tests that:
|
||||
- should consider renaming it to --evaluate if it actually evaluates stuff
|
||||
- test values of assignments
|
||||
|
@ -133,6 +133,10 @@ pub fn app() {
|
||||
|
||||
if let Err(run_error) = justfile.run(&arguments) {
|
||||
warn!("{}", run_error);
|
||||
process::exit(if let super::RunError::Code{code, ..} = run_error { code } else { -1 });
|
||||
match run_error {
|
||||
super::RunError::Code{code, .. } => process::exit(code),
|
||||
super::RunError::BacktickCode{code, ..} => process::exit(code),
|
||||
_ => process::exit(-1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -261,3 +261,91 @@ fn backtick_trimming() {
|
||||
"echo 'Hello, world!'\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn backtick_code_assignment() {
|
||||
integration_test(
|
||||
"backtick_code_assignment",
|
||||
&[],
|
||||
"b = a\na = `function f { return 100; }; f`\nbar:\n echo '{{`function f { return 200; }; f`}}'",
|
||||
100,
|
||||
"",
|
||||
"backtick failed with exit code 100
|
||||
|
|
||||
2 | a = `function f { return 100; }; f`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn backtick_code_interpolation() {
|
||||
integration_test(
|
||||
"backtick_code_interpolation",
|
||||
&[],
|
||||
"b = a\na = `echo hello`\nbar:\n echo '{{`function f { return 200; }; f`}}'",
|
||||
200,
|
||||
"",
|
||||
"backtick failed with exit code 200
|
||||
|
|
||||
4 | echo '{{`function f { return 200; }; f`}}'
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shebang_backtick_failure() {
|
||||
integration_test(
|
||||
"shebang_backtick_failure",
|
||||
&[],
|
||||
"foo:
|
||||
#!/bin/sh
|
||||
echo hello
|
||||
echo {{`exit 123`}}",
|
||||
123,
|
||||
"",
|
||||
"backtick failed with exit code 123
|
||||
|
|
||||
4 | echo {{`exit 123`}}
|
||||
| ^^^^^^^^^^
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn command_backtick_failure() {
|
||||
integration_test(
|
||||
"command_backtick_failure",
|
||||
&[],
|
||||
"foo:
|
||||
echo hello
|
||||
echo {{`exit 123`}}",
|
||||
123,
|
||||
"hello\n",
|
||||
"echo hello\nbacktick failed with exit code 123
|
||||
|
|
||||
3 | echo {{`exit 123`}}
|
||||
| ^^^^^^^^^^
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assignment_backtick_failure() {
|
||||
integration_test(
|
||||
"assignment_backtick_failure",
|
||||
&[],
|
||||
"foo:
|
||||
echo hello
|
||||
echo {{`exit 111`}}
|
||||
a = `exit 222`",
|
||||
222,
|
||||
"",
|
||||
"backtick failed with exit code 222
|
||||
|
|
||||
4 | a = `exit 222`
|
||||
| ^^^^^^^^^^
|
||||
",
|
||||
);
|
||||
}
|
||||
|
31
src/lib.rs
31
src/lib.rs
@ -148,7 +148,7 @@ fn backtick_error_from_signal(exit_status: process::ExitStatus) -> RunError<'sta
|
||||
RunError::BacktickUnknownFailure
|
||||
}
|
||||
|
||||
fn run_backtick<'a>(raw: &str, _token: &Token<'a>) -> Result<String, RunError<'a>> {
|
||||
fn run_backtick<'a>(raw: &str, token: &Token<'a>) -> Result<String, RunError<'a>> {
|
||||
let output = process::Command::new("sh")
|
||||
.arg("-cu")
|
||||
.arg(raw)
|
||||
@ -160,6 +160,7 @@ fn run_backtick<'a>(raw: &str, _token: &Token<'a>) -> Result<String, RunError<'a
|
||||
if let Some(code) = output.status.code() {
|
||||
if code != 0 {
|
||||
return Err(RunError::BacktickCode {
|
||||
token: token.clone(),
|
||||
code: code,
|
||||
});
|
||||
}
|
||||
@ -877,7 +878,7 @@ enum RunError<'a> {
|
||||
TmpdirIoError{recipe: &'a str, io_error: io::Error},
|
||||
UnknownFailure{recipe: &'a str},
|
||||
UnknownRecipes{recipes: Vec<&'a str>},
|
||||
BacktickCode{code: i32},
|
||||
BacktickCode{code: i32, token: Token<'a>},
|
||||
BacktickIoError{io_error: io::Error},
|
||||
BacktickSignal{signal: i32},
|
||||
BacktickUtf8Error{utf8_error: std::str::Utf8Error},
|
||||
@ -920,14 +921,27 @@ impl<'a> Display for RunError<'a> {
|
||||
},
|
||||
RunError::TmpdirIoError{recipe, ref io_error} =>
|
||||
try!(write!(f, "Recipe \"{}\" could not be run because of an IO error while trying to create a temporary directory or write a file to that directory`:\n{}", recipe, io_error)),
|
||||
RunError::BacktickCode{code} => {
|
||||
try!(writeln!(f, "backtick failed with exit code {}", code));
|
||||
RunError::BacktickCode{code, ref token} => {
|
||||
try!(write!(f, "backtick failed with exit code {}\n", code));
|
||||
match token.text.lines().nth(token.line) {
|
||||
Some(line) => {
|
||||
let line_number_width = token.line.to_string().len();
|
||||
try!(write!(f, "{0:1$} |\n", "", line_number_width));
|
||||
try!(write!(f, "{} | {}\n", token.line + 1, line));
|
||||
try!(write!(f, "{0:1$} |", "", line_number_width));
|
||||
try!(write!(f, " {0:1$}{2:^<3$}", "",
|
||||
token.column + token.prefix.len(), "", token.lexeme.len()));
|
||||
},
|
||||
None => if token.index != token.text.len() {
|
||||
try!(write!(f, "internal error: Error has invalid line number: {}", token.line + 1))
|
||||
},
|
||||
}
|
||||
}
|
||||
RunError::BacktickSignal{signal} => {
|
||||
try!(writeln!(f, "backtick was terminated by signal {}", signal));
|
||||
try!(write!(f, "backtick was terminated by signal {}", signal));
|
||||
}
|
||||
RunError::BacktickUnknownFailure => {
|
||||
try!(writeln!(f, "backtick failed for an uknown reason"));
|
||||
try!(write!(f, "backtick failed for an uknown reason"));
|
||||
}
|
||||
RunError::BacktickIoError{ref io_error} => {
|
||||
try!(match io_error.kind() {
|
||||
@ -940,14 +954,15 @@ impl<'a> Display for RunError<'a> {
|
||||
try!(write!(f, "backtick succeeded but stdout was not utf8: {}", utf8_error));
|
||||
}
|
||||
RunError::InternalError{ref message} => {
|
||||
try!(writeln!(f, "internal error, this may indicate a bug in j: {}\n consider filing an issue: https://github.com/casey/j/issues/new", message));
|
||||
try!(write!(f, "internal error, this may indicate a bug in j: {}\n consider filing an issue: https://github.com/casey/j/issues/new", message));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
struct Token<'a> {
|
||||
index: usize,
|
||||
line: usize,
|
||||
|
11
src/unit.rs
11
src/unit.rs
@ -797,3 +797,14 @@ fn missing_default() {
|
||||
other => panic!("expected an code run error, but got: {}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn backtick_code() {
|
||||
match parse_success("a:\n echo {{`function f { return 100; }; f`}}").run(&["a"]).unwrap_err() {
|
||||
super::RunError::BacktickCode{code, token} => {
|
||||
assert_eq!(code, 100);
|
||||
assert_eq!(token.lexeme, "`function f { return 100; }; f`");
|
||||
},
|
||||
other => panic!("expected an code run error, but got: {}", other),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user