Test all errors and error messages (#145)
This commit is contained in:
parent
64e4905e49
commit
1befc8674e
@ -344,7 +344,7 @@ recipe:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error() {
|
fn unknown_dependency() {
|
||||||
integration_test(
|
integration_test(
|
||||||
&[],
|
&[],
|
||||||
"bar:\nhello:\nfoo: bar baaaaaaaz hello",
|
"bar:\nhello:\nfoo: bar baaaaaaaz hello",
|
||||||
@ -740,6 +740,31 @@ wut:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn outer_shebang() {
|
||||||
|
integration_test(
|
||||||
|
&[],
|
||||||
|
r#"#!/lol/wut
|
||||||
|
export foo = "a"
|
||||||
|
baz = "c"
|
||||||
|
export bar = "b"
|
||||||
|
export abc = foo + bar + baz
|
||||||
|
|
||||||
|
wut:
|
||||||
|
#!/bin/sh
|
||||||
|
echo $foo $bar $abc
|
||||||
|
"#,
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: `#!` is reserved syntax outside of recipes
|
||||||
|
|
|
||||||
|
1 | #!/lol/wut
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn export_shebang() {
|
fn export_shebang() {
|
||||||
integration_test(
|
integration_test(
|
||||||
@ -1100,6 +1125,53 @@ recipe a b +d:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mixed_whitespace() {
|
||||||
|
integration_test(
|
||||||
|
&[],
|
||||||
|
"bar:\n\t echo hello",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Found a mix of tabs and spaces in leading whitespace: `␉␠`
|
||||||
|
Leading whitespace may consist of tabs or spaces, but not both
|
||||||
|
|
|
||||||
|
2 | echo hello
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extra_leading_whitespace() {
|
||||||
|
integration_test(
|
||||||
|
&[],
|
||||||
|
"bar:\n\t\techo hello\n\t\t\techo goodbye",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Recipe line has extra leading whitespace
|
||||||
|
|
|
||||||
|
3 | echo goodbye
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inconsistent_leading_whitespace() {
|
||||||
|
integration_test(
|
||||||
|
&[],
|
||||||
|
"bar:\n\t\techo hello\n\t echo goodbye",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Recipe line has inconsistent leading whitespace. Recipe started with `␉␉` but found line with `␉␠`
|
||||||
|
|
|
||||||
|
3 | echo goodbye
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn required_after_default() {
|
fn required_after_default() {
|
||||||
integration_test(
|
integration_test(
|
||||||
@ -1115,6 +1187,21 @@ fn required_after_default() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn required_after_variadic() {
|
||||||
|
integration_test(
|
||||||
|
&[],
|
||||||
|
"bar:\nhello baz +arg bar:",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Parameter `bar` follows variadic parameter
|
||||||
|
|
|
||||||
|
2 | hello baz +arg bar:
|
||||||
|
| ^^^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn use_string_default() {
|
fn use_string_default() {
|
||||||
integration_test(
|
integration_test(
|
||||||
@ -1374,6 +1461,128 @@ c: b a
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parameter_shadows_variable() {
|
||||||
|
integration_test(
|
||||||
|
&["a"],
|
||||||
|
"FOO = 'hello'\na FOO:",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Parameter `FOO` shadows variable of the same name
|
||||||
|
|
|
||||||
|
2 | a FOO:
|
||||||
|
| ^^^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dependency_takes_arguments() {
|
||||||
|
integration_test(
|
||||||
|
&["b"],
|
||||||
|
"b: a\na FOO:",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Recipe `b` depends on `a` which requires arguments. Dependencies may not require arguments
|
||||||
|
|
|
||||||
|
1 | b: a
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn duplicate_parameter() {
|
||||||
|
integration_test(
|
||||||
|
&["a"],
|
||||||
|
"a foo foo:",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Recipe `a` has duplicate parameter `foo`
|
||||||
|
|
|
||||||
|
1 | a foo foo:
|
||||||
|
| ^^^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn duplicate_dependency() {
|
||||||
|
integration_test(
|
||||||
|
&["a"],
|
||||||
|
"b:\na: b b",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Recipe `a` has duplicate dependency `b`
|
||||||
|
|
|
||||||
|
2 | a: b b
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn duplicate_recipe() {
|
||||||
|
integration_test(
|
||||||
|
&["b"],
|
||||||
|
"b:\nb:",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Recipe `b` first defined on line 1 is redefined on line 2
|
||||||
|
|
|
||||||
|
2 | b:
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn duplicate_variable() {
|
||||||
|
integration_test(
|
||||||
|
&["foo"],
|
||||||
|
"a = 'hello'\na = 'hello'\nfoo:",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Variable `a` has multiple definitions
|
||||||
|
|
|
||||||
|
2 | a = 'hello'
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unexpected_token() {
|
||||||
|
integration_test(
|
||||||
|
&["foo"],
|
||||||
|
"foo: 'bar'",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Expected name, end of line, or end of file, but found raw string
|
||||||
|
|
|
||||||
|
1 | foo: 'bar'
|
||||||
|
| ^^^^^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn self_dependency() {
|
||||||
|
integration_test(
|
||||||
|
&["a"],
|
||||||
|
"a: a",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Recipe `a` depends on itself
|
||||||
|
|
|
||||||
|
1 | a: a
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn long_circular_recipe_dependency() {
|
fn long_circular_recipe_dependency() {
|
||||||
integration_test(
|
integration_test(
|
||||||
@ -1389,6 +1598,53 @@ fn long_circular_recipe_dependency() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn variable_self_dependency() {
|
||||||
|
integration_test(
|
||||||
|
&["a"],
|
||||||
|
"z = z\na:",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Variable `z` is defined in terms of itself
|
||||||
|
|
|
||||||
|
1 | z = z
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn variable_circular_dependency() {
|
||||||
|
integration_test(
|
||||||
|
&["a"],
|
||||||
|
"x = y\ny = z\nz = x\na:",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: Variable `x` depends on its own value: `x -> y -> z -> x`
|
||||||
|
|
|
||||||
|
1 | x = y
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_escape_sequence() {
|
||||||
|
integration_test(
|
||||||
|
&["a"],
|
||||||
|
r#"x = "\q"
|
||||||
|
a:"#,
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"error: `\\q` is not a valid escape sequence
|
||||||
|
|
|
||||||
|
1 | x = \"\\q\"
|
||||||
|
| ^^^^
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multiline_raw_string() {
|
fn multiline_raw_string() {
|
||||||
integration_test(
|
integration_test(
|
||||||
|
25
src/lib.rs
25
src/lib.rs
@ -828,7 +828,7 @@ fn internal_error(message: String) -> CompileError<'static> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn show_whitespace(text: &str) -> String {
|
fn show_whitespace(text: &str) -> String {
|
||||||
text.chars().map(|c| match c { '\t' => 't', ' ' => 's', _ => c }).collect()
|
text.chars().map(|c| match c { '\t' => '␉', ' ' => '␠', _ => c }).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mixed_whitespace(text: &str) -> bool {
|
fn mixed_whitespace(text: &str) -> bool {
|
||||||
@ -1052,7 +1052,7 @@ impl<'a> Display for CompileError<'a> {
|
|||||||
match self.kind {
|
match self.kind {
|
||||||
CircularRecipeDependency{recipe, ref circle} => {
|
CircularRecipeDependency{recipe, ref circle} => {
|
||||||
if circle.len() == 2 {
|
if circle.len() == 2 {
|
||||||
write!(f, "Recipe `{}` depends on itself", recipe)?;
|
writeln!(f, "Recipe `{}` depends on itself", recipe)?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(f, "Recipe `{}` has circular dependency `{}`",
|
writeln!(f, "Recipe `{}` has circular dependency `{}`",
|
||||||
recipe, circle.join(" -> "))?;
|
recipe, circle.join(" -> "))?;
|
||||||
@ -1060,8 +1060,7 @@ impl<'a> Display for CompileError<'a> {
|
|||||||
}
|
}
|
||||||
CircularVariableDependency{variable, ref circle} => {
|
CircularVariableDependency{variable, ref circle} => {
|
||||||
if circle.len() == 2 {
|
if circle.len() == 2 {
|
||||||
writeln!(f, "Variable `{}` depends on its own value: `{}`",
|
writeln!(f, "Variable `{}` is defined in terms of itself", variable)?;
|
||||||
variable, circle.join(" -> "))?;
|
|
||||||
} else {
|
} else {
|
||||||
writeln!(f, "Variable `{}` depends on its own value: `{}`",
|
writeln!(f, "Variable `{}` depends on its own value: `{}`",
|
||||||
variable, circle.join(" -> "))?;
|
variable, circle.join(" -> "))?;
|
||||||
@ -1075,21 +1074,21 @@ impl<'a> Display for CompileError<'a> {
|
|||||||
writeln!(f, "Recipe `{}` has duplicate parameter `{}`", recipe, parameter)?;
|
writeln!(f, "Recipe `{}` has duplicate parameter `{}`", recipe, parameter)?;
|
||||||
}
|
}
|
||||||
DuplicateVariable{variable} => {
|
DuplicateVariable{variable} => {
|
||||||
writeln!(f, "Variable `{}` is has multiple definitions", variable)?;
|
writeln!(f, "Variable `{}` has multiple definitions", variable)?;
|
||||||
}
|
}
|
||||||
UnexpectedToken{ref expected, found} => {
|
UnexpectedToken{ref expected, found} => {
|
||||||
writeln!(f, "Expected {} but found {}", Or(expected), found)?;
|
writeln!(f, "Expected {}, but found {}", Or(expected), found)?;
|
||||||
}
|
}
|
||||||
DuplicateDependency{recipe, dependency} => {
|
DuplicateDependency{recipe, dependency} => {
|
||||||
writeln!(f, "Recipe `{}` has duplicate dependency `{}`", recipe, dependency)?;
|
writeln!(f, "Recipe `{}` has duplicate dependency `{}`", recipe, dependency)?;
|
||||||
}
|
}
|
||||||
DuplicateRecipe{recipe, first} => {
|
DuplicateRecipe{recipe, first} => {
|
||||||
writeln!(f, "Recipe `{}` first defined on line {} is redefined on line {}",
|
writeln!(f, "Recipe `{}` first defined on line {} is redefined on line {}",
|
||||||
recipe, first, self.line)?;
|
recipe, first + 1, self.line + 1)?;
|
||||||
}
|
}
|
||||||
DependencyHasParameters{recipe, dependency} => {
|
DependencyHasParameters{recipe, dependency} => {
|
||||||
writeln!(f, "Recipe `{}` depends on `{}` which requires arguments. \
|
writeln!(f, "Recipe `{}` depends on `{}` which requires arguments. \
|
||||||
dependencies may not require arguments", recipe, dependency)?;
|
Dependencies may not require arguments", recipe, dependency)?;
|
||||||
}
|
}
|
||||||
ParameterShadowsVariable{parameter} => {
|
ParameterShadowsVariable{parameter} => {
|
||||||
writeln!(f, "Parameter `{}` shadows variable of the same name", parameter)?;
|
writeln!(f, "Parameter `{}` shadows variable of the same name", parameter)?;
|
||||||
@ -1098,12 +1097,12 @@ impl<'a> Display for CompileError<'a> {
|
|||||||
writeln!(f, "Non-default parameter `{}` follows default parameter", parameter)?;
|
writeln!(f, "Non-default parameter `{}` follows default parameter", parameter)?;
|
||||||
}
|
}
|
||||||
ParameterFollowsVariadicParameter{parameter} => {
|
ParameterFollowsVariadicParameter{parameter} => {
|
||||||
writeln!(f, "Parameter `{}` follows a varidic parameter", parameter)?;
|
writeln!(f, "Parameter `{}` follows variadic parameter", parameter)?;
|
||||||
}
|
}
|
||||||
MixedLeadingWhitespace{whitespace} => {
|
MixedLeadingWhitespace{whitespace} => {
|
||||||
writeln!(f,
|
writeln!(f,
|
||||||
"Found a mix of tabs and spaces in leading whitespace: `{}`\n\
|
"Found a mix of tabs and spaces in leading whitespace: `{}`\n\
|
||||||
leading whitespace may consist of tabs or spaces, but not both",
|
Leading whitespace may consist of tabs or spaces, but not both",
|
||||||
show_whitespace(whitespace)
|
show_whitespace(whitespace)
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
@ -1112,12 +1111,12 @@ impl<'a> Display for CompileError<'a> {
|
|||||||
}
|
}
|
||||||
InconsistentLeadingWhitespace{expected, found} => {
|
InconsistentLeadingWhitespace{expected, found} => {
|
||||||
writeln!(f,
|
writeln!(f,
|
||||||
"Inconsistant leading whitespace: recipe started with `{}` but found line with `{}`:",
|
"Recipe line has inconsistent leading whitespace. Recipe started with `{}` but found line with `{}`",
|
||||||
show_whitespace(expected), show_whitespace(found)
|
show_whitespace(expected), show_whitespace(found)
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
OuterShebang => {
|
OuterShebang => {
|
||||||
writeln!(f, "Shebang `#!` is reserved syntax outside of recipes")?;
|
writeln!(f, "`#!` is reserved syntax outside of recipes")?;
|
||||||
}
|
}
|
||||||
UnknownDependency{recipe, unknown} => {
|
UnknownDependency{recipe, unknown} => {
|
||||||
writeln!(f, "Recipe `{}` has unknown dependency `{}`", recipe, unknown)?;
|
writeln!(f, "Recipe `{}` has unknown dependency `{}`", recipe, unknown)?;
|
||||||
@ -1405,7 +1404,7 @@ impl<'a> Display for RunError<'a> {
|
|||||||
error_token = Some(token);
|
error_token = Some(token);
|
||||||
}
|
}
|
||||||
BacktickUnknownFailure{ref token} => {
|
BacktickUnknownFailure{ref token} => {
|
||||||
write!(f, "Backtick failed for an uknown reason")?;
|
write!(f, "Backtick failed for an unknown reason")?;
|
||||||
error_token = Some(token);
|
error_token = Some(token);
|
||||||
}
|
}
|
||||||
BacktickIoError{ref token, ref io_error} => {
|
BacktickIoError{ref token, ref io_error} => {
|
||||||
|
Loading…
Reference in New Issue
Block a user