use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn test_RULE_SYNTAX_001_prop_basic_rules_always_parse(
target in "[a-z][a-z0-9_-]{0,20}",
prereq in "[a-z][a-z0-9_-]{0,20}",
recipe in "[a-z][a-z0-9 _-]{1,50}"
) {
let makefile = format!("{}:{}\n\t{}", target, prereq, recipe);
let result = parse_makefile(&makefile);
prop_assert!(result.is_ok(), "Failed to parse: {}", makefile);
let ast = result.unwrap();
prop_assert_eq!(ast.items.len(), 1);
if let MakeItem::Target { name, prerequisites, recipe: rec, .. } = &ast.items[0] {
prop_assert_eq!(name, &target);
prop_assert_eq!(prerequisites.len(), 1);
prop_assert_eq!(&prerequisites[0], &prereq);
prop_assert_eq!(rec.len(), 1);
prop_assert_eq!(&rec[0], recipe.trim());
} else {
return Err(TestCaseError::fail("Expected Target item"));
}
}
#[test]
fn test_RULE_SYNTAX_001_prop_parsing_is_deterministic(
target in "[a-z]{1,10}",
recipe in "[a-z ]{1,30}"
) {
let makefile = format!("{}:\n\t{}", target, recipe);
let result1 = parse_makefile(&makefile);
let result2 = parse_makefile(&makefile);
prop_assert!(result1.is_ok());
prop_assert!(result2.is_ok());
let ast1 = result1.unwrap();
let ast2 = result2.unwrap();
prop_assert_eq!(ast1.items.len(), ast2.items.len());
prop_assert_eq!(ast1.items, ast2.items);
}
#[test]
fn test_RULE_SYNTAX_001_prop_multiple_prerequisites(
target in "[a-z]{1,10}",
prereqs in prop::collection::vec("[a-z]{1,10}", 1..5)
) {
let prereq_str = prereqs.join(" ");
let makefile = format!("{}: {}", target, prereq_str);
let result = parse_makefile(&makefile);
prop_assert!(result.is_ok());
let ast = result.unwrap();
if let MakeItem::Target { prerequisites, .. } = &ast.items[0] {
prop_assert_eq!(prerequisites.len(), prereqs.len());
for (i, prereq) in prereqs.iter().enumerate() {
prop_assert_eq!(&prerequisites[i], prereq);
}
} else {
return Err(TestCaseError::fail("Expected Target item"));
}
}
#[test]
fn test_RULE_SYNTAX_001_prop_multiline_recipes(
target in "[a-z]{1,10}",
recipe_lines in prop::collection::vec("[a-z ]{1,20}", 1..5)
) {
let recipe_str = recipe_lines.iter()
.map(|line| format!("\t{}", line))
.collect::<Vec<_>>()
.join("\n");
let makefile = format!("{}:\n{}", target, recipe_str);
let result = parse_makefile(&makefile);
prop_assert!(result.is_ok());
let ast = result.unwrap();
if let MakeItem::Target { recipe, .. } = &ast.items[0] {
prop_assert_eq!(recipe.len(), recipe_lines.len());
for (i, line) in recipe_lines.iter().enumerate() {
prop_assert_eq!(&recipe[i], &line.trim());
}
} else {
return Err(TestCaseError::fail("Expected Target item"));
}
}
}