Refactor more tests into macro invocations (#259)

This commit is contained in:
Casey Rodarmor 2017-11-18 01:44:59 -08:00 committed by GitHub
parent 28a57d9828
commit afe2c0f94e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 175 additions and 209 deletions

7
Cargo.lock generated
View File

@ -11,6 +11,11 @@ name = "ansi_term"
version = "0.9.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "assert_matches"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.3" version = "0.2.3"
@ -99,6 +104,7 @@ name = "just"
version = "0.3.3" version = "0.3.3"
dependencies = [ dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"brev 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "brev 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -263,6 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e772942dccdf11b368c31e044e4fca9189f80a773d2f0808379de65894cbf57"
"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860" "checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"

View File

@ -8,17 +8,18 @@ homepage = "https://github.com/casey/just"
readme = "crates-io-readme.md" readme = "crates-io-readme.md"
[dependencies] [dependencies]
ansi_term = "0.9.0" ansi_term = "0.9.0"
atty = "0.2.1" assert_matches = "1.1.0"
brev = "0.1.6" atty = "0.2.1"
clap = "2.0.0" brev = "0.1.6"
edit-distance = "2.0.0" clap = "2.0.0"
itertools = "0.6.2" edit-distance = "2.0.0"
lazy_static = "0.2.1" itertools = "0.6.2"
libc = "0.2.21" lazy_static = "0.2.1"
regex = "0.2.2" libc = "0.2.21"
tempdir = "0.3.5" regex = "0.2.2"
unicode-width = "0.1.3" tempdir = "0.3.5"
unicode-width = "0.1.3"
[dev-dependencies.utilities] [dev-dependencies.utilities]
path = "utilities" path = "utilities"

View File

@ -87,49 +87,46 @@ impl<'a: 'b, 'b> AssignmentResolver<'a, 'b> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use testing::parse_error;
use super::*; use super::*;
use TokenKind::*;
#[test] compilation_error_test! {
fn circular_variable_dependency() { name: unclosed_interpolation_delimiter,
let text = "a = b\nb = a"; input: "a:\n echo {{ foo",
let variable = "a"; index: 15,
let circle = vec!["a", "b", "a"]; line: 1,
parse_error(text, CompilationError { column: 12,
text: text, width: Some(0),
index: 0, kind: UnexpectedToken{expected: vec![Plus, Eol, InterpolationEnd], found: Dedent},
line: 0,
column: 0,
width: Some(1),
kind: CircularVariableDependency{variable, circle}
});
} }
#[test] compilation_error_test! {
fn self_variable_dependency() { name: circular_variable_dependency,
let text = "a = a"; input: "a = b\nb = a",
let variable = "a"; index: 0,
let circle = vec!["a", "a"]; line: 0,
parse_error(text, CompilationError { column: 0,
text: text, width: Some(1),
index: 0, kind: CircularVariableDependency{variable: "a", circle: vec!["a", "b", "a"]},
line: 0,
column: 0,
width: Some(1),
kind: CircularVariableDependency{variable, circle}
});
} }
#[test] compilation_error_test! {
fn unknown_expression_variable() { name: self_variable_dependency,
let text = "x = yy"; input: "a = a",
parse_error(text, CompilationError { index: 0,
text: text, line: 0,
index: 4, column: 0,
line: 0, width: Some(1),
column: 4, kind: CircularVariableDependency{variable: "a", circle: vec!["a", "a"]},
width: Some(2), }
kind: UndefinedVariable{variable: "yy"},
}); compilation_error_test! {
name: unknown_expression_variable,
input: "x = yy",
index: 4,
line: 0,
column: 4,
width: Some(2),
kind: UndefinedVariable{variable: "yy"},
} }
} }

View File

@ -44,5 +44,3 @@ impl<'a> CookedString<'a> {
} }
} }
} }

View File

@ -14,4 +14,3 @@ impl<'a> Fragment<'a> {
} }
} }
} }

View File

@ -165,11 +165,12 @@ impl<'a> Display for Justfile<'a> {
mod test { mod test {
use super::*; use super::*;
use testing::parse_success; use testing::parse_success;
use RuntimeError::*;
#[test] #[test]
fn unknown_recipes() { fn unknown_recipes() {
match parse_success("a:\nb:\nc:").run(&["a", "x", "y", "z"], &Default::default()).unwrap_err() { match parse_success("a:\nb:\nc:").run(&["a", "x", "y", "z"], &Default::default()).unwrap_err() {
RuntimeError::UnknownRecipes{recipes, suggestion} => { UnknownRecipes{recipes, suggestion} => {
assert_eq!(recipes, &["x", "y", "z"]); assert_eq!(recipes, &["x", "y", "z"]);
assert_eq!(suggestion, None); assert_eq!(suggestion, None);
} }
@ -197,7 +198,7 @@ a:
"; ";
match parse_success(text).run(&["a"], &Default::default()).unwrap_err() { match parse_success(text).run(&["a"], &Default::default()).unwrap_err() {
RuntimeError::Code{recipe, line_number, code} => { Code{recipe, line_number, code} => {
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(code, 200); assert_eq!(code, 200);
assert_eq!(line_number, None); assert_eq!(line_number, None);
@ -206,18 +207,18 @@ a:
} }
} }
#[test] #[test]
fn code_error() { fn code_error() {
match parse_success("fail:\n @exit 100") match parse_success("fail:\n @exit 100")
.run(&["fail"], &Default::default()).unwrap_err() { .run(&["fail"], &Default::default()).unwrap_err() {
RuntimeError::Code{recipe, line_number, code} => { Code{recipe, line_number, code} => {
assert_eq!(recipe, "fail"); assert_eq!(recipe, "fail");
assert_eq!(code, 100); assert_eq!(code, 100);
assert_eq!(line_number, Some(2)); assert_eq!(line_number, Some(2));
}, },
other => panic!("expected a code run error, but got: {}", other), other => panic!("expected a code run error, but got: {}", other),
}
} }
}
#[test] #[test]
fn run_args() { fn run_args() {
@ -226,7 +227,7 @@ a return code:
@x() { {{return}} {{code + "0"}}; }; x"#; @x() { {{return}} {{code + "0"}}; }; x"#;
match parse_success(text).run(&["a", "return", "15"], &Default::default()).unwrap_err() { match parse_success(text).run(&["a", "return", "15"], &Default::default()).unwrap_err() {
RuntimeError::Code{recipe, line_number, code} => { Code{recipe, line_number, code} => {
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(code, 150); assert_eq!(code, 150);
assert_eq!(line_number, Some(3)); assert_eq!(line_number, Some(3));
@ -238,7 +239,7 @@ a return code:
#[test] #[test]
fn missing_some_arguments() { fn missing_some_arguments() {
match parse_success("a b c d:").run(&["a", "b", "c"], &Default::default()).unwrap_err() { match parse_success("a b c d:").run(&["a", "b", "c"], &Default::default()).unwrap_err() {
RuntimeError::ArgumentCountMismatch{recipe, found, min, max} => { ArgumentCountMismatch{recipe, found, min, max} => {
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(found, 2); assert_eq!(found, 2);
assert_eq!(min, 3); assert_eq!(min, 3);
@ -251,7 +252,7 @@ a return code:
#[test] #[test]
fn missing_some_arguments_variadic() { fn missing_some_arguments_variadic() {
match parse_success("a b c +d:").run(&["a", "B", "C"], &Default::default()).unwrap_err() { match parse_success("a b c +d:").run(&["a", "B", "C"], &Default::default()).unwrap_err() {
RuntimeError::ArgumentCountMismatch{recipe, found, min, max} => { ArgumentCountMismatch{recipe, found, min, max} => {
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(found, 2); assert_eq!(found, 2);
assert_eq!(min, 3); assert_eq!(min, 3);
@ -265,7 +266,7 @@ a return code:
fn missing_all_arguments() { fn missing_all_arguments() {
match parse_success("a b c d:\n echo {{b}}{{c}}{{d}}") match parse_success("a b c d:\n echo {{b}}{{c}}{{d}}")
.run(&["a"], &Default::default()).unwrap_err() { .run(&["a"], &Default::default()).unwrap_err() {
RuntimeError::ArgumentCountMismatch{recipe, found, min, max} => { ArgumentCountMismatch{recipe, found, min, max} => {
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(found, 0); assert_eq!(found, 0);
assert_eq!(min, 3); assert_eq!(min, 3);
@ -278,7 +279,7 @@ a return code:
#[test] #[test]
fn missing_some_defaults() { fn missing_some_defaults() {
match parse_success("a b c d='hello':").run(&["a", "b"], &Default::default()).unwrap_err() { match parse_success("a b c d='hello':").run(&["a", "b"], &Default::default()).unwrap_err() {
RuntimeError::ArgumentCountMismatch{recipe, found, min, max} => { ArgumentCountMismatch{recipe, found, min, max} => {
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(found, 1); assert_eq!(found, 1);
assert_eq!(min, 2); assert_eq!(min, 2);
@ -291,7 +292,7 @@ a return code:
#[test] #[test]
fn missing_all_defaults() { fn missing_all_defaults() {
match parse_success("a b c='r' d='h':").run(&["a"], &Default::default()).unwrap_err() { match parse_success("a b c='r' d='h':").run(&["a"], &Default::default()).unwrap_err() {
RuntimeError::ArgumentCountMismatch{recipe, found, min, max} => { ArgumentCountMismatch{recipe, found, min, max} => {
assert_eq!(recipe, "a"); assert_eq!(recipe, "a");
assert_eq!(found, 0); assert_eq!(found, 0);
assert_eq!(min, 1); assert_eq!(min, 1);
@ -308,7 +309,7 @@ a return code:
configuration.overrides.insert("baz", "bob"); configuration.overrides.insert("baz", "bob");
match parse_success("a:\n echo {{`f() { return 100; }; f`}}") match parse_success("a:\n echo {{`f() { return 100; }; f`}}")
.run(&["a"], &configuration).unwrap_err() { .run(&["a"], &configuration).unwrap_err() {
RuntimeError::UnknownOverrides{overrides} => { UnknownOverrides{overrides} => {
assert_eq!(overrides, &["baz", "foo"]); assert_eq!(overrides, &["baz", "foo"]);
}, },
other => panic!("expected a code run error, but got: {}", other), other => panic!("expected a code run error, but got: {}", other),
@ -333,7 +334,7 @@ wut:
}; };
match parse_success(text).run(&["wut"], &configuration).unwrap_err() { match parse_success(text).run(&["wut"], &configuration).unwrap_err() {
RuntimeError::Code{code: _, line_number, recipe} => { Code{code: _, line_number, recipe} => {
assert_eq!(recipe, "wut"); assert_eq!(recipe, "wut");
assert_eq!(line_number, Some(8)); assert_eq!(line_number, Some(8));
}, },

View File

@ -10,6 +10,10 @@ extern crate regex;
extern crate tempdir; extern crate tempdir;
extern crate unicode_width; extern crate unicode_width;
#[cfg(test)]
#[macro_use]
mod testing;
mod assignment_evaluator; mod assignment_evaluator;
mod assignment_resolver; mod assignment_resolver;
mod color; mod color;
@ -33,8 +37,6 @@ mod shebang;
mod token; mod token;
mod tokenizer; mod tokenizer;
#[cfg(test)] mod testing;
use tokenizer::tokenize; use tokenizer::tokenize;
mod common { mod common {

View File

@ -22,4 +22,3 @@ impl<'a> Display for Parameter<'a> {
Ok(()) Ok(())
} }
} }

View File

@ -384,7 +384,6 @@ mod test {
use super::*; use super::*;
use brev; use brev;
use testing::parse_success; use testing::parse_success;
use tokenize;
macro_rules! summary_test { macro_rules! summary_test {
($name:ident, $input:expr, $expected:expr $(,)*) => { ($name:ident, $input:expr, $expected:expr $(,)*) => {
@ -403,47 +402,6 @@ mod test {
} }
} }
macro_rules! error_test {
(
name: $name:ident,
input: $input:expr,
index: $index:expr,
line: $line:expr,
column: $column:expr,
width: $width:expr,
kind: $kind:expr,
) => {
#[test]
fn $name() {
let input = $input;
let expected = CompilationError {
text: input,
index: $index,
line: $line,
column: $column,
width: $width,
kind: $kind,
};
let tokens = tokenize(input).unwrap();
let parser = Parser::new(input, tokens);
if let Err(error) = parser.justfile() {
assert_eq!(error.text, expected.text);
assert_eq!(error.index, expected.index);
assert_eq!(error.line, expected.line);
assert_eq!(error.column, expected.column);
assert_eq!(error.width, expected.width);
assert_eq!(error.kind, expected.kind);
assert_eq!(error, expected);
} else {
panic!("parse succeeded but expected: {}\n{}", expected, input);
}
}
}
}
summary_test! { summary_test! {
parse_empty, parse_empty,
" "
@ -630,7 +588,7 @@ c = a + b + a + b",
{{b}} {{c}}", {{b}} {{c}}",
} }
error_test! { compilation_error_test! {
name: missing_colon, name: missing_colon,
input: "a b c\nd e f", input: "a b c\nd e f",
index: 5, index: 5,
@ -640,7 +598,7 @@ c = a + b + a + b",
kind: UnexpectedToken{expected: vec![Name, Plus, Colon], found: Eol}, kind: UnexpectedToken{expected: vec![Name, Plus, Colon], found: Eol},
} }
error_test! { compilation_error_test! {
name: missing_default_eol, name: missing_default_eol,
input: "hello arg=\n", input: "hello arg=\n",
index: 10, index: 10,
@ -650,7 +608,7 @@ c = a + b + a + b",
kind: UnexpectedToken{expected: vec![StringToken, RawString], found: Eol}, kind: UnexpectedToken{expected: vec![StringToken, RawString], found: Eol},
} }
error_test! { compilation_error_test! {
name: missing_default_eof, name: missing_default_eof,
input: "hello arg=", input: "hello arg=",
index: 10, index: 10,
@ -660,7 +618,7 @@ c = a + b + a + b",
kind: UnexpectedToken{expected: vec![StringToken, RawString], found: Eof}, kind: UnexpectedToken{expected: vec![StringToken, RawString], found: Eof},
} }
error_test! { compilation_error_test! {
name: missing_default_colon, name: missing_default_colon,
input: "hello arg=:", input: "hello arg=:",
index: 10, index: 10,
@ -670,7 +628,7 @@ c = a + b + a + b",
kind: UnexpectedToken{expected: vec![StringToken, RawString], found: Colon}, kind: UnexpectedToken{expected: vec![StringToken, RawString], found: Colon},
} }
error_test! { compilation_error_test! {
name: missing_default_backtick, name: missing_default_backtick,
input: "hello arg=`hello`", input: "hello arg=`hello`",
index: 10, index: 10,
@ -680,7 +638,7 @@ c = a + b + a + b",
kind: UnexpectedToken{expected: vec![StringToken, RawString], found: Backtick}, kind: UnexpectedToken{expected: vec![StringToken, RawString], found: Backtick},
} }
error_test! { compilation_error_test! {
name: parameter_after_variadic, name: parameter_after_variadic,
input: "foo +a bbb:", input: "foo +a bbb:",
index: 7, index: 7,
@ -690,7 +648,7 @@ c = a + b + a + b",
kind: ParameterFollowsVariadicParameter{parameter: "bbb"}, kind: ParameterFollowsVariadicParameter{parameter: "bbb"},
} }
error_test! { compilation_error_test! {
name: required_after_default, name: required_after_default,
input: "hello arg='foo' bar:", input: "hello arg='foo' bar:",
index: 16, index: 16,
@ -700,7 +658,7 @@ c = a + b + a + b",
kind: RequiredParameterFollowsDefaultParameter{parameter: "bar"}, kind: RequiredParameterFollowsDefaultParameter{parameter: "bar"},
} }
error_test! { compilation_error_test! {
name: missing_eol, name: missing_eol,
input: "a b c: z =", input: "a b c: z =",
index: 9, index: 9,
@ -710,7 +668,7 @@ c = a + b + a + b",
kind: UnexpectedToken{expected: vec![Name, Eol, Eof], found: Equals}, kind: UnexpectedToken{expected: vec![Name, Eol, Eof], found: Equals},
} }
error_test! { compilation_error_test! {
name: duplicate_parameter, name: duplicate_parameter,
input: "a b b:", input: "a b b:",
index: 4, index: 4,
@ -720,7 +678,7 @@ c = a + b + a + b",
kind: DuplicateParameter{recipe: "a", parameter: "b"}, kind: DuplicateParameter{recipe: "a", parameter: "b"},
} }
error_test! { compilation_error_test! {
name: parameter_shadows_varible, name: parameter_shadows_varible,
input: "foo = \"h\"\na foo:", input: "foo = \"h\"\na foo:",
index: 12, index: 12,
@ -730,7 +688,7 @@ c = a + b + a + b",
kind: ParameterShadowsVariable{parameter: "foo"}, kind: ParameterShadowsVariable{parameter: "foo"},
} }
error_test! { compilation_error_test! {
name: dependency_has_parameters, name: dependency_has_parameters,
input: "foo arg:\nb: foo", input: "foo arg:\nb: foo",
index: 12, index: 12,
@ -740,7 +698,7 @@ c = a + b + a + b",
kind: DependencyHasParameters{recipe: "b", dependency: "foo"}, kind: DependencyHasParameters{recipe: "b", dependency: "foo"},
} }
error_test! { compilation_error_test! {
name: duplicate_dependency, name: duplicate_dependency,
input: "a b c: b c z z", input: "a b c: b c z z",
index: 13, index: 13,
@ -750,7 +708,7 @@ c = a + b + a + b",
kind: DuplicateDependency{recipe: "a", dependency: "z"}, kind: DuplicateDependency{recipe: "a", dependency: "z"},
} }
error_test! { compilation_error_test! {
name: duplicate_recipe, name: duplicate_recipe,
input: "a:\nb:\na:", input: "a:\nb:\na:",
index: 6, index: 6,
@ -760,7 +718,7 @@ c = a + b + a + b",
kind: DuplicateRecipe{recipe: "a", first: 0}, kind: DuplicateRecipe{recipe: "a", first: 0},
} }
error_test! { compilation_error_test! {
name: duplicate_variable, name: duplicate_variable,
input: "a = \"0\"\na = \"0\"", input: "a = \"0\"\na = \"0\"",
index: 8, index: 8,
@ -770,7 +728,7 @@ c = a + b + a + b",
kind: DuplicateVariable{variable: "a"}, kind: DuplicateVariable{variable: "a"},
} }
error_test! { compilation_error_test! {
name: extra_whitespace, name: extra_whitespace,
input: "a:\n blah\n blarg", input: "a:\n blah\n blarg",
index: 10, index: 10,
@ -780,7 +738,7 @@ c = a + b + a + b",
kind: ExtraLeadingWhitespace, kind: ExtraLeadingWhitespace,
} }
error_test! { compilation_error_test! {
name: interpolation_outside_of_recipe, name: interpolation_outside_of_recipe,
input: "{{", input: "{{",
index: 0, index: 0,
@ -790,7 +748,7 @@ c = a + b + a + b",
kind: UnexpectedToken{expected: vec![Name, At], found: InterpolationStart}, kind: UnexpectedToken{expected: vec![Name, At], found: InterpolationStart},
} }
error_test! { compilation_error_test! {
name: unclosed_interpolation_delimiter, name: unclosed_interpolation_delimiter,
input: "a:\n echo {{ foo", input: "a:\n echo {{ foo",
index: 15, index: 15,
@ -800,7 +758,7 @@ c = a + b + a + b",
kind: UnexpectedToken{expected: vec![Plus, Eol, InterpolationEnd], found: Dedent}, kind: UnexpectedToken{expected: vec![Plus, Eol, InterpolationEnd], found: Dedent},
} }
error_test! { compilation_error_test! {
name: plus_following_parameter, name: plus_following_parameter,
input: "a b c+:", input: "a b c+:",
index: 5, index: 5,

View File

@ -102,72 +102,54 @@ impl<'a, 'b> RecipeResolver<'a, 'b> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use testing::parse_error;
#[test] compilation_error_test! {
fn circular_recipe_dependency() { name: circular_recipe_dependency,
let text = "a: b\nb: a"; input: "a: b\nb: a",
let recipe = "b"; index: 8,
let circle = vec!["a", "b", "a"]; line: 1,
parse_error(text, CompilationError { column: 3,
text: text, width: Some(1),
index: 8, kind: CircularRecipeDependency{recipe: "b", circle: vec!["a", "b", "a"]},
line: 1,
column: 3,
width: Some(1),
kind: CircularRecipeDependency{recipe, circle}
});
} }
#[test] compilation_error_test! {
fn self_recipe_dependency() { name: self_recipe_dependency,
let text = "a: a"; input: "a: a",
parse_error(text, CompilationError { index: 3,
text: text, line: 0,
index: 3, column: 3,
line: 0, width: Some(1),
column: 3, kind: CircularRecipeDependency{recipe: "a", circle: vec!["a", "a"]},
width: Some(1),
kind: CircularRecipeDependency{recipe: "a", circle: vec!["a", "a"]}
});
} }
#[test] compilation_error_test! {
fn unknown_dependency() { name: unknown_dependency,
let text = "a: b"; input: "a: b",
parse_error(text, CompilationError { index: 3,
text: text, line: 0,
index: 3, column: 3,
line: 0, width: Some(1),
column: 3, kind: UnknownDependency{recipe: "a", unknown: "b"},
width: Some(1),
kind: UnknownDependency{recipe: "a", unknown: "b"}
});
} }
#[test] compilation_error_test! {
fn unknown_interpolation_variable() { name: unknown_interpolation_variable,
let text = "x:\n {{ hello}}"; input: "x:\n {{ hello}}",
parse_error(text, CompilationError { index: 9,
text: text, line: 1,
index: 9, column: 6,
line: 1, width: Some(5),
column: 6, kind: UndefinedVariable{variable: "hello"},
width: Some(5),
kind: UndefinedVariable{variable: "hello"},
});
} }
#[test] compilation_error_test! {
fn unknown_second_interpolation_variable() { name: unknown_second_interpolation_variable,
let text = "wtf=\"x\"\nx:\n echo\n foo {{wtf}} {{ lol }}"; input: "wtf=\"x\"\nx:\n echo\n foo {{wtf}} {{ lol }}",
parse_error(text, CompilationError { index: 33,
text: text, line: 3,
index: 33, column: 16,
line: 3, width: Some(3),
column: 16, kind: UndefinedVariable{variable: "lol"},
width: Some(3),
kind: UndefinedVariable{variable: "lol"},
});
} }
} }

View File

@ -1,7 +1,6 @@
use common::*; use common::*;
use compile; use compile;
use tokenizer::tokenize;
pub fn parse_success(text: &str) -> Justfile { pub fn parse_success(text: &str) -> Justfile {
match compile(text) { match compile(text) {
@ -10,20 +9,43 @@ pub fn parse_success(text: &str) -> Justfile {
} }
} }
pub fn parse_error(text: &str, expected: CompilationError) { macro_rules! compilation_error_test {
let tokens = tokenize(text).unwrap(); (
let parser = Parser::new(text, tokens); name: $name:ident,
input: $input:expr,
index: $index:expr,
line: $line:expr,
column: $column:expr,
width: $width:expr,
kind: $kind:expr,
) => {
#[test]
fn $name() {
let input = $input;
if let Err(error) = parser.justfile() { let expected = ::CompilationError {
assert_eq!(error.text, expected.text); text: input,
assert_eq!(error.index, expected.index); index: $index,
assert_eq!(error.line, expected.line); line: $line,
assert_eq!(error.column, expected.column); column: $column,
assert_eq!(error.kind, expected.kind); width: $width,
assert_eq!(error.width, expected.width); kind: $kind,
assert_eq!(error, expected); };
} else {
panic!("Expected {:?} but parse succeeded", expected.kind); let tokens = ::tokenizer::tokenize(input).unwrap();
let parser = ::Parser::new(input, tokens);
if let Err(error) = parser.justfile() {
assert_eq!(error.text, expected.text);
assert_eq!(error.index, expected.index);
assert_eq!(error.line, expected.line);
assert_eq!(error.column, expected.column);
assert_eq!(error.width, expected.width);
assert_eq!(error.kind, expected.kind);
assert_eq!(error, expected);
} else {
panic!("parse succeeded but expected: {}\n{}", expected, input);
}
}
} }
} }