Test all errors and error messages (#145)
This commit is contained in:
parent
64e4905e49
commit
1befc8674e
@ -344,7 +344,7 @@ recipe:
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error() {
|
||||
fn unknown_dependency() {
|
||||
integration_test(
|
||||
&[],
|
||||
"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]
|
||||
fn export_shebang() {
|
||||
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]
|
||||
fn required_after_default() {
|
||||
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]
|
||||
fn use_string_default() {
|
||||
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]
|
||||
fn long_circular_recipe_dependency() {
|
||||
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]
|
||||
fn multiline_raw_string() {
|
||||
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 {
|
||||
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 {
|
||||
@ -1052,7 +1052,7 @@ impl<'a> Display for CompileError<'a> {
|
||||
match self.kind {
|
||||
CircularRecipeDependency{recipe, ref circle} => {
|
||||
if circle.len() == 2 {
|
||||
write!(f, "Recipe `{}` depends on itself", recipe)?;
|
||||
writeln!(f, "Recipe `{}` depends on itself", recipe)?;
|
||||
} else {
|
||||
writeln!(f, "Recipe `{}` has circular dependency `{}`",
|
||||
recipe, circle.join(" -> "))?;
|
||||
@ -1060,8 +1060,7 @@ impl<'a> Display for CompileError<'a> {
|
||||
}
|
||||
CircularVariableDependency{variable, ref circle} => {
|
||||
if circle.len() == 2 {
|
||||
writeln!(f, "Variable `{}` depends on its own value: `{}`",
|
||||
variable, circle.join(" -> "))?;
|
||||
writeln!(f, "Variable `{}` is defined in terms of itself", variable)?;
|
||||
} else {
|
||||
writeln!(f, "Variable `{}` depends on its own value: `{}`",
|
||||
variable, circle.join(" -> "))?;
|
||||
@ -1075,21 +1074,21 @@ impl<'a> Display for CompileError<'a> {
|
||||
writeln!(f, "Recipe `{}` has duplicate parameter `{}`", recipe, parameter)?;
|
||||
}
|
||||
DuplicateVariable{variable} => {
|
||||
writeln!(f, "Variable `{}` is has multiple definitions", variable)?;
|
||||
writeln!(f, "Variable `{}` has multiple definitions", variable)?;
|
||||
}
|
||||
UnexpectedToken{ref expected, found} => {
|
||||
writeln!(f, "Expected {} but found {}", Or(expected), found)?;
|
||||
writeln!(f, "Expected {}, but found {}", Or(expected), found)?;
|
||||
}
|
||||
DuplicateDependency{recipe, dependency} => {
|
||||
writeln!(f, "Recipe `{}` has duplicate dependency `{}`", recipe, dependency)?;
|
||||
}
|
||||
DuplicateRecipe{recipe, first} => {
|
||||
writeln!(f, "Recipe `{}` first defined on line {} is redefined on line {}",
|
||||
recipe, first, self.line)?;
|
||||
recipe, first + 1, self.line + 1)?;
|
||||
}
|
||||
DependencyHasParameters{recipe, dependency} => {
|
||||
writeln!(f, "Recipe `{}` depends on `{}` which requires arguments. \
|
||||
dependencies may not require arguments", recipe, dependency)?;
|
||||
Dependencies may not require arguments", recipe, dependency)?;
|
||||
}
|
||||
ParameterShadowsVariable{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)?;
|
||||
}
|
||||
ParameterFollowsVariadicParameter{parameter} => {
|
||||
writeln!(f, "Parameter `{}` follows a varidic parameter", parameter)?;
|
||||
writeln!(f, "Parameter `{}` follows variadic parameter", parameter)?;
|
||||
}
|
||||
MixedLeadingWhitespace{whitespace} => {
|
||||
writeln!(f,
|
||||
"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)
|
||||
)?;
|
||||
}
|
||||
@ -1112,12 +1111,12 @@ impl<'a> Display for CompileError<'a> {
|
||||
}
|
||||
InconsistentLeadingWhitespace{expected, found} => {
|
||||
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)
|
||||
)?;
|
||||
}
|
||||
OuterShebang => {
|
||||
writeln!(f, "Shebang `#!` is reserved syntax outside of recipes")?;
|
||||
writeln!(f, "`#!` is reserved syntax outside of recipes")?;
|
||||
}
|
||||
UnknownDependency{recipe, unknown} => {
|
||||
writeln!(f, "Recipe `{}` has unknown dependency `{}`", recipe, unknown)?;
|
||||
@ -1405,7 +1404,7 @@ impl<'a> Display for RunError<'a> {
|
||||
error_token = Some(token);
|
||||
}
|
||||
BacktickUnknownFailure{ref token} => {
|
||||
write!(f, "Backtick failed for an uknown reason")?;
|
||||
write!(f, "Backtick failed for an unknown reason")?;
|
||||
error_token = Some(token);
|
||||
}
|
||||
BacktickIoError{ref token, ref io_error} => {
|
||||
|
Loading…
Reference in New Issue
Block a user