use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn test_SYNTAX_002_prop_continuation_always_parses(
var_name in "[A-Z][A-Z0-9_]{0,10}",
value1 in "[a-z0-9_]{1,10}",
value2 in "[a-z0-9_]{1,10}"
) {
let makefile = format!("{} = {} \\\n {}", var_name, value1, value2);
let result = parse_makefile(&makefile);
prop_assert!(result.is_ok(), "Line continuation must always parse: {:?}", result);
}
}
proptest! {
#[test]
fn test_SYNTAX_002_prop_continuation_equivalent_to_sameline(
var_name in "[A-Z][A-Z0-9_]{0,10}",
value1 in "[a-z0-9_]{1,10}",
value2 in "[a-z0-9_]{1,10}"
) {
let with_continuation = format!("{} = {} \\\n {}", var_name, value1, value2);
let without_continuation = format!("{} = {} {}", var_name, value1, value2);
let result1 = parse_makefile(&with_continuation);
let result2 = parse_makefile(&without_continuation);
prop_assert!(result1.is_ok());
prop_assert!(result2.is_ok());
let ast1 = result1.unwrap();
let ast2 = result2.unwrap();
match (&ast1.items[0], &ast2.items[0]) {
(
MakeItem::Variable { value: v1, .. },
MakeItem::Variable { value: v2, .. }
) => {
prop_assert_eq!(v1, v2, "Continuation must be equivalent to same-line");
}
_ => return Err(TestCaseError::fail("Expected Variables")),
}
}
}
proptest! {
#[test]
fn test_SYNTAX_002_prop_multiple_continuations(
var_name in "[A-Z][A-Z0-9_]{0,10}",
values in prop::collection::vec("[a-z0-9_]{1,10}", 2..5)
) {
let mut makefile = format!("{} = {}", var_name, values[0]);
for value in values.iter().skip(1) {
makefile.push_str(" \\\n ");
makefile.push_str(value);
}
let result = parse_makefile(&makefile);
prop_assert!(result.is_ok(), "Multiple continuations must parse: {:?}", result);
let ast = result.unwrap();
prop_assert_eq!(ast.items.len(), 1);
match &ast.items[0] {
MakeItem::Variable { value, .. } => {
for v in &values {
prop_assert!(value.contains(v), "Value {:?} should contain {:?}", value, v);
}
}
_ => return Err(TestCaseError::fail("Expected Variable")),
}
}
}
proptest! {
#[test]
fn test_SYNTAX_002_prop_preserves_order(
var_name in "[A-Z][A-Z0-9_]{0,10}",
value1 in "[a-z]{3,5}",
value2 in "[a-z]{3,5}",
value3 in "[a-z]{3,5}"
) {
if value1 == value2 || value2 == value3 || value1 == value3 {
return Ok(());
}
if value1.contains(&value2) || value2.contains(&value1) ||
value2.contains(&value3) || value3.contains(&value2) ||
value1.contains(&value3) || value3.contains(&value1) {
return Ok(());
}
let makefile = format!("{} = {} \\\n {} \\\n {}", var_name, value1, value2, value3);
let result = parse_makefile(&makefile);
prop_assert!(result.is_ok());
let ast = result.unwrap();
match &ast.items[0] {
MakeItem::Variable { value, .. } => {
let pos1 = value.find(&value1);
let pos2 = value.find(&value2);
let pos3 = value.find(&value3);
prop_assert!(pos1.is_some());
prop_assert!(pos2.is_some());
prop_assert!(pos3.is_some());
prop_assert!(pos1.unwrap() < pos2.unwrap(), "Order: {} < {}", value1, value2);
prop_assert!(pos2.unwrap() < pos3.unwrap(), "Order: {} < {}", value2, value3);
}
_ => return Err(TestCaseError::fail("Expected Variable")),
}
}
}
proptest! {
#[test]
fn test_SYNTAX_002_prop_works_with_all_flavors(
var_name in "[A-Z][A-Z0-9_]{0,10}",
value1 in "[a-z0-9_]{1,10}",
value2 in "[a-z0-9_]{1,10}",
flavor in prop::sample::select(vec!["=", ":=", "?=", "+=", "!="])
) {
let makefile = format!("{} {} {} \\\n {}", var_name, flavor, value1, value2);
let result = parse_makefile(&makefile);
prop_assert!(result.is_ok(), "Continuation with flavor {} must parse", flavor);
let ast = result.unwrap();
prop_assert_eq!(ast.items.len(), 1);
match &ast.items[0] {
MakeItem::Variable { .. } => {
}
_ => return Err(TestCaseError::fail("Expected Variable")),
}
}
}