Backtick tests done!
This commit is contained in:
parent
21320d36ee
commit
25c6432fa3
9
notes
9
notes
@ -1,15 +1,6 @@
|
|||||||
notes
|
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:
|
- --debug tests that:
|
||||||
- should consider renaming it to --evaluate if it actually evaluates stuff
|
- should consider renaming it to --evaluate if it actually evaluates stuff
|
||||||
- test values of assignments
|
- test values of assignments
|
||||||
|
@ -133,6 +133,10 @@ pub fn app() {
|
|||||||
|
|
||||||
if let Err(run_error) = justfile.run(&arguments) {
|
if let Err(run_error) = justfile.run(&arguments) {
|
||||||
warn!("{}", run_error);
|
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",
|
"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
|
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")
|
let output = process::Command::new("sh")
|
||||||
.arg("-cu")
|
.arg("-cu")
|
||||||
.arg(raw)
|
.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 let Some(code) = output.status.code() {
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
return Err(RunError::BacktickCode {
|
return Err(RunError::BacktickCode {
|
||||||
|
token: token.clone(),
|
||||||
code: code,
|
code: code,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -877,7 +878,7 @@ enum RunError<'a> {
|
|||||||
TmpdirIoError{recipe: &'a str, io_error: io::Error},
|
TmpdirIoError{recipe: &'a str, io_error: io::Error},
|
||||||
UnknownFailure{recipe: &'a str},
|
UnknownFailure{recipe: &'a str},
|
||||||
UnknownRecipes{recipes: Vec<&'a str>},
|
UnknownRecipes{recipes: Vec<&'a str>},
|
||||||
BacktickCode{code: i32},
|
BacktickCode{code: i32, token: Token<'a>},
|
||||||
BacktickIoError{io_error: io::Error},
|
BacktickIoError{io_error: io::Error},
|
||||||
BacktickSignal{signal: i32},
|
BacktickSignal{signal: i32},
|
||||||
BacktickUtf8Error{utf8_error: std::str::Utf8Error},
|
BacktickUtf8Error{utf8_error: std::str::Utf8Error},
|
||||||
@ -920,14 +921,27 @@ impl<'a> Display for RunError<'a> {
|
|||||||
},
|
},
|
||||||
RunError::TmpdirIoError{recipe, ref io_error} =>
|
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)),
|
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} => {
|
RunError::BacktickCode{code, ref token} => {
|
||||||
try!(writeln!(f, "backtick failed with exit code {}", code));
|
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} => {
|
RunError::BacktickSignal{signal} => {
|
||||||
try!(writeln!(f, "backtick was terminated by signal {}", signal));
|
try!(write!(f, "backtick was terminated by signal {}", signal));
|
||||||
}
|
}
|
||||||
RunError::BacktickUnknownFailure => {
|
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} => {
|
RunError::BacktickIoError{ref io_error} => {
|
||||||
try!(match io_error.kind() {
|
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));
|
try!(write!(f, "backtick succeeded but stdout was not utf8: {}", utf8_error));
|
||||||
}
|
}
|
||||||
RunError::InternalError{ref message} => {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
struct Token<'a> {
|
struct Token<'a> {
|
||||||
index: usize,
|
index: usize,
|
||||||
line: 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),
|
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