Skip to content

Commit

Permalink
more unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rfuzzo committed Dec 13, 2023
1 parent 9e627dc commit 64004d6
Show file tree
Hide file tree
Showing 4 changed files with 359 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ where
pub fn tokenize(line: String) -> Vec<String> {
let mut tokens: Vec<String> = vec![];

// TODO do we want .archive matching?
let mut is_quoted = false;
let mut current_token: String = "".to_owned();
for c in line.chars() {
Expand Down
7 changes: 7 additions & 0 deletions tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ mod integration_tests {
assert!(topo_sort(&mods, &order).is_ok(), "rules contain a cycle")
}

#[test]
fn test_parse_rules() {
let rules =
parse_rules_from_path("./tests/cmop/rules_note.txt").expect("rule parse failed");
assert_eq!(14, rules.len());
}

#[test]
fn test_gather_mods() {
let root_path = "./tests";
Expand Down
319 changes: 305 additions & 14 deletions tests/unit_parser_tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[cfg(test)]
mod unit_tests {
use core::panic;
use std::io::Cursor;

use cmop::{expressions::*, parser::*, rules::*};
Expand All @@ -19,6 +20,51 @@ mod unit_tests {
}
}

////////////////////////////////////////////////////////////////////////
// ORDER

#[test]
fn test_multiline_order() {
let input = "[Order]\na.archive\nb.archive\nc.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(2, rules.len());

let mut rule = rules.first().expect("No rules found");
if let Rule::Order(n) = rule {
assert_eq!("a.archive", n.name_a.as_str());
assert_eq!("b.archive", n.name_b.as_str());
}

rule = rules.get(1).expect("No rules found");
if let Rule::Order(n) = rule {
assert_eq!("b.archive", n.name_a.as_str());
assert_eq!("c.archive", n.name_b.as_str());
}
}

#[test]
fn test_inline_order() {
let input = "[Order]a.archive \"b name.archive\" c.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(2, rules.len());

let mut rule = rules.first().expect("No rules found");
if let Rule::Order(n) = rule {
assert_eq!("a.archive", n.name_a.as_str());
assert_eq!("b name.archive", n.name_b.as_str());
}

rule = rules.get(1).expect("No rules found");
if let Rule::Order(n) = rule {
assert_eq!("b name.archive", n.name_a.as_str());
assert_eq!("c.archive", n.name_b.as_str());
}
}

////////////////////////////////////////////////////////////////////////
// NOTE

Expand All @@ -43,6 +89,27 @@ mod unit_tests {
}
}

#[test]
fn test_inline_note2() {
let input = "[Note message] a.archive b name.archive c.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(1, rules.len());
let rule = rules.first().expect("No rules found");
assert_eq!("message", rule.get_comment());

let names = ["a.archive", "b name.archive", "c.archive"];
if let Rule::Note(n) = rule {
assert_eq!(3, n.expressions.len());
for (i, e) in n.expressions.iter().enumerate() {
if let Expression::Atomic(a) = e {
assert_eq!(names[i], a.get_item().as_str());
}
}
}
}

#[test]
fn test_multiline_note() {
let input = "[Note message]\na.archive\nb.archive\nc.archive".to_owned();
Expand Down Expand Up @@ -121,39 +188,263 @@ mod unit_tests {
}

////////////////////////////////////////////////////////////////////////
// ORDER
// CONFLICT

#[test]
fn test_multiline_order() {
let input = "[Order]\na.archive\nb.archive\nc.archive".to_owned();
fn test_inline_conflict() {
let input = "[Conflict message] a.archive b.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(2, rules.len());
assert_eq!(1, rules.len());
let rule = rules.first().expect("No rules found");
assert_eq!("message", rule.get_comment());

let mut rule = rules.first().expect("No rules found");
if let Rule::Order(n) = rule {
assert_eq!("a.archive", n.name_a.as_str());
assert_eq!("b.archive", n.name_b.as_str());
let names = ["a.archive", "b.archive"];
if let Rule::Conflict(n) = rule {
assert!(n.expression_a.is_some());
assert!(n.expression_b.is_some());

assert!(is_atomic(&n.expression_a.clone().unwrap(), names[0]));
assert!(is_atomic(&n.expression_b.clone().unwrap(), names[1]));
}
}

rule = rules.get(1).expect("No rules found");
if let Rule::Order(n) = rule {
assert_eq!("b.archive", n.name_a.as_str());
assert_eq!("c.archive", n.name_b.as_str());
#[test]
fn test_inline_conflict_whitespace() {
let input = "[Conflict message] a.archive b name.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(1, rules.len());
let rule = rules.first().expect("No rules found");
assert_eq!("message", rule.get_comment());

let names = ["a.archive", "b name.archive"];
if let Rule::Conflict(n) = rule {
assert!(n.expression_a.is_some());
assert!(n.expression_b.is_some());

assert!(is_atomic(&n.expression_a.clone().unwrap(), names[0]));
assert!(is_atomic(&n.expression_b.clone().unwrap(), names[1]));
}
}

////////////////////////////////////////////////////////////////////////
// CONFLICT
#[test]
fn test_multiline_conflict() {
let input = "[Conflict message]\na.archive\nb.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(1, rules.len());
let rule = rules.first().expect("No rules found");
assert_eq!("message", rule.get_comment());

let names = ["a.archive", "b.archive"];
if let Rule::Conflict(n) = rule {
assert!(n.expression_a.is_some());
assert!(n.expression_b.is_some());

assert!(is_atomic(&n.expression_a.clone().unwrap(), names[0]));
assert!(is_atomic(&n.expression_b.clone().unwrap(), names[1]));
}
}

#[test]
fn test_multiline_conflict_overflow() {
let input = "[Conflict message]\na.archive\nb.archive\nc.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(1, rules.len());
let rule = rules.first().expect("No rules found");
assert_eq!("message", rule.get_comment());

let names = ["a.archive", "b.archive"];
if let Rule::Conflict(n) = rule {
assert!(n.expression_a.is_some());
assert!(n.expression_b.is_some());

assert!(is_atomic(&n.expression_a.clone().unwrap(), names[0]));
assert!(is_atomic(&n.expression_b.clone().unwrap(), names[1]));
}
}

#[test]
fn test_multiline_conflict_whitespace() {
let input = "[Conflict]\nname a.archive\nb.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(1, rules.len());
let rule = rules.first().expect("No rules found");
assert_eq!("", rule.get_comment());

let names = ["name a.archive", "b.archive"];
if let Rule::Conflict(n) = rule {
assert!(n.expression_a.is_some());
assert!(n.expression_b.is_some());

assert!(is_atomic(&n.expression_a.clone().unwrap(), names[0]));
assert!(is_atomic(&n.expression_b.clone().unwrap(), names[1]));
}
}

#[test]
fn test_multiline_conflict_expression() {
let input = "[Conflict]\nname a.archive\n[ALL b.archive c name.archive]".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(1, rules.len());
let rule = rules.first().expect("No rules found");
assert_eq!("", rule.get_comment());

let names = ["name a.archive"];
if let Rule::Conflict(n) = rule {
assert!(n.expression_a.is_some());
assert!(n.expression_b.is_some());

assert!(is_atomic(&n.expression_a.clone().unwrap(), names[0]));
assert!(is_all(&n.expression_b.clone().unwrap()));
}
}

////////////////////////////////////////////////////////////////////////
// REQUIRES

#[test]
fn test_inline_requires() {
let input: String = "[Requires message] a.archive b.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(1, rules.len());
let rule = rules.first().expect("No rules found");
assert_eq!("message", rule.get_comment());

let names = ["a.archive", "b.archive"];
if let Rule::Requires(n) = rule {
assert!(n.expression_a.is_some());
assert!(n.expression_b.is_some());

assert!(is_atomic(&n.expression_a.clone().unwrap(), names[0]));
assert!(is_atomic(&n.expression_b.clone().unwrap(), names[1]));
}
}

#[test]
fn test_inline_requires_whitespace() {
let input = "[Requires message] a.archive b name.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(1, rules.len());
let rule = rules.first().expect("No rules found");
assert_eq!("message", rule.get_comment());

let names = ["a.archive", "b name.archive"];
if let Rule::Requires(n) = rule {
assert!(n.expression_a.is_some());
assert!(n.expression_b.is_some());

assert!(is_atomic(&n.expression_a.clone().unwrap(), names[0]));
assert!(is_atomic(&n.expression_b.clone().unwrap(), names[1]));
}
}

#[test]
fn test_multiline_requires() {
let input = "[Requires message]\na.archive\nb.archive".to_owned();
let reader = Cursor::new(input.as_bytes());

let rules = parse_rules_from_reader(reader).expect("Failed to parse rule");
assert_eq!(1, rules.len());
let rule = rules.first().expect("No rules found");
assert_eq!("message", rule.get_comment());

let names = ["a.archive", "b.archive"];
if let Rule::Requires(n) = rule {
assert!(n.expression_a.is_some());
assert!(n.expression_b.is_some());

assert!(is_atomic(&n.expression_a.clone().unwrap(), names[0]));
assert!(is_atomic(&n.expression_b.clone().unwrap(), names[1]));
}
}

////////////////////////////////////////////////////////////////////////
// EXPRESSIONS
////////////////////////////////////////////////////////////////////////

#[test]
fn test_atomic_expr() {
test_atomic("a.archive", "a.archive");
test_atomic("a name.archive", "a name.archive");
}

fn test_atomic(input: &str, expected: &str) {
assert_eq!(
1,
parse_expressions(Cursor::new(input.as_bytes()))
.expect("No expressions parsed")
.len()
);
let e = parse_expression(input).expect("No expressions parsed");
assert!(is_atomic(&e, expected));
}

#[test]
fn test_all_expr() {
test_all(
"[ALL a.archive b.archive]",
["a.archive", "b.archive"].to_vec(),
);
test_all(
"[ALL a name.archive b.archive]",
["a name.archive", "b.archive"].to_vec(),
);
test_all(
"[ALL\na name.archive\nb.archive]",
["a name.archive", "b.archive"].to_vec(),
);
}

fn test_all(input: &str, expected: Vec<&str>) {
assert_eq!(
1,
parse_expressions(Cursor::new(input.as_bytes()))
.expect("No expressions parsed")
.len()
);
let expr = parse_expression(input).expect("No expressions parsed");
if let Expression::ALL(b) = expr {
assert_eq!(expected.len(), b.expressions.len());
for (i, e) in b.expressions.iter().enumerate() {
assert!(is_atomic(e, expected[i]));
}
} else {
panic!("wrong type");
}
}

fn is_atomic(e: &Expression, expected: &str) -> bool {
if let Expression::Atomic(b) = e {
assert_eq!(expected, b.get_item().as_str());
true
} else {
panic!("wrong type");
}
}

fn is_all(e: &Expression) -> bool {
if let Expression::ALL(_b) = e {
true
} else {
panic!("wrong type");
}
}

#[test]
fn test_multiline_expr() {
{
Expand Down
Loading

0 comments on commit 64004d6

Please sign in to comment.