Backtick tests done!

This commit is contained in:
Casey Rodarmor 2016-10-30 01:27:05 -07:00
parent 21320d36ee
commit 25c6432fa3
5 changed files with 127 additions and 18 deletions

9
notes
View file

@ -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

View file

@ -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),
}
}
}

View file

@ -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`
| ^^^^^^^^^^
",
);
}

View file

@ -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,

View file

@ -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),
}
}