use logical_expressions::{LogicalExpression, ParseError};
mod condition;
use condition::{Condition, InvalidCharacter};
fn test(expression: &str, expected: LogicalExpression<Condition>) {
let result = LogicalExpression::parse(expression);
assert_eq!(result, Ok(expected));
}
fn test_err(expression: &str, expected: ParseError<InvalidCharacter>) {
let result: Result<LogicalExpression<Condition>, ParseError<InvalidCharacter>> =
LogicalExpression::parse(expression);
assert_eq!(result, Err(expected));
}
#[test]
fn test_condition() {
test("a", LogicalExpression::Condition(Condition::new("a")));
test(" a ", LogicalExpression::Condition(Condition::new("a")));
}
#[test]
fn test_simple() {
test(
"a & b",
LogicalExpression::And(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::Condition(Condition::new("b")),
]),
);
test(
"a | b",
LogicalExpression::Or(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::Condition(Condition::new("b")),
]),
);
}
#[test]
fn test_empty_condition() {
test_err("", ParseError::EmptyCondition);
test_err(" ", ParseError::EmptyCondition);
}
#[test]
fn test_invalid_characters() {
test_err("a*", ParseError::ConditionParsing(InvalidCharacter('*')));
test_err("*a", ParseError::ConditionParsing(InvalidCharacter('*')));
test_err("*a-", ParseError::ConditionParsing(InvalidCharacter('*')));
test_err("-a*", ParseError::ConditionParsing(InvalidCharacter('-')));
}
#[test]
fn test_one_sided_operators() {
test_err("a&", ParseError::TrailingOperator);
test_err("&a", ParseError::LeadingOperator);
test_err("a|", ParseError::TrailingOperator);
test_err("|a", ParseError::LeadingOperator);
test_err("(a&)", ParseError::TrailingOperator);
test_err("(&a)", ParseError::LeadingOperator);
test_err("(a|)", ParseError::TrailingOperator);
test_err("(|a)", ParseError::LeadingOperator);
test_err("&a&b", ParseError::LeadingOperator);
test_err("|a|b", ParseError::LeadingOperator);
test_err("a&b&", ParseError::TrailingOperator);
test_err("a|b|", ParseError::TrailingOperator);
}
#[test]
fn test_and_or_combinations() {
test(
"a & b | c",
LogicalExpression::Or(vec![
LogicalExpression::And(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::Condition(Condition::new("b")),
]),
LogicalExpression::Condition(Condition::new("c")),
]),
);
test(
"a | b & c",
LogicalExpression::Or(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::And(vec![
LogicalExpression::Condition(Condition::new("b")),
LogicalExpression::Condition(Condition::new("c")),
]),
]),
);
}
#[test]
fn test_missing_operators_around_brackets() {
test_err("a (b)", ParseError::ConditionBeforeOpeningBracket);
test_err("(a) b", ParseError::ConditionAfterClosingBracket);
test_err("a & b (c)", ParseError::ConditionBeforeOpeningBracket);
test_err("(a) b | c", ParseError::ConditionAfterClosingBracket);
test_err("(a (b & c))", ParseError::ConditionBeforeOpeningBracket);
test_err("((a & b) c)", ParseError::ConditionAfterClosingBracket);
test_err("a (b) c", ParseError::ConditionBeforeOpeningBracket);
}
#[test]
fn test_parentheses() {
test("(a)", LogicalExpression::Condition(Condition::new("a")));
test(
"(a & b)",
LogicalExpression::And(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::Condition(Condition::new("b")),
]),
);
test_err("(", ParseError::NoMatchingClosingBracket);
test_err(")", ParseError::NoMatchingOpeningBracket);
test_err("(a", ParseError::NoMatchingClosingBracket);
test_err("a)", ParseError::NoMatchingOpeningBracket);
test_err(")a(", ParseError::NoMatchingOpeningBracket);
test_err("()a", ParseError::EmptyCondition);
}
#[test]
fn test_nested_parentheses() {
test(
"((a) & (b))",
LogicalExpression::And(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::Condition(Condition::new("b")),
]),
);
test(
"(a & (b | c))",
LogicalExpression::And(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::Or(vec![
LogicalExpression::Condition(Condition::new("b")),
LogicalExpression::Condition(Condition::new("c")),
]),
]),
);
}
#[test]
fn test_multiple_operators() {
test_err("a && b", ParseError::MultipleOperators);
test_err("a || b", ParseError::MultipleOperators);
test_err("a &&& b", ParseError::MultipleOperators);
test_err("a ||| b", ParseError::MultipleOperators);
test_err("a &| b", ParseError::MultipleOperators);
test_err("a |& b", ParseError::MultipleOperators);
test_err("a &|& b", ParseError::MultipleOperators);
test_err("a |&| b", ParseError::MultipleOperators);
test_err("(a && b)", ParseError::MultipleOperators);
test_err("(a || b)", ParseError::MultipleOperators);
test_err("a && (b)", ParseError::MultipleOperators);
test_err("a || (b)", ParseError::MultipleOperators);
test_err("(a) && b", ParseError::MultipleOperators);
test_err("(a) || b", ParseError::MultipleOperators);
}
#[test]
fn test_whitespace() {
test(
"a&b",
LogicalExpression::And(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::Condition(Condition::new("b")),
]),
);
test(
"a & b",
LogicalExpression::And(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::Condition(Condition::new("b")),
]),
);
test(
"a & b | c",
LogicalExpression::Or(vec![
LogicalExpression::And(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::Condition(Condition::new("b")),
]),
LogicalExpression::Condition(Condition::new("c")),
]),
);
test(
"a & b | c",
LogicalExpression::Or(vec![
LogicalExpression::And(vec![
LogicalExpression::Condition(Condition::new("a")),
LogicalExpression::Condition(Condition::new("b")),
]),
LogicalExpression::Condition(Condition::new("c")),
]),
);
test_err("a & & b", ParseError::MultipleOperators);
test_err("a | | b", ParseError::MultipleOperators);
test_err("a & | b", ParseError::MultipleOperators);
test_err("a | & b", ParseError::MultipleOperators);
}