use anyhow::Result;
use assert_matches::assert_matches;
use motogarage_parser::Command;
use motogarage_parser::{
Condition, MotogarageParser, Motorcycle, Query, Rule, Value, parse_moto_file,
};
use pest::Parser;
#[test]
fn test_parse_comment() -> Result<()> {
let input = r#"
// This is a comment
DEFINE bike "Test Bike" { year: 2000 }
// Another comment
"#;
let ast = parse_moto_file(input)?;
assert_eq!(ast.len(), 1);
assert_matches!(ast[0], Command::Definition(_));
Ok(())
}
#[test]
fn test_parse_atoms() -> Result<()> {
let pairs = MotogarageParser::parse(Rule::ident, "my_field")?;
assert_eq!(pairs.as_str(), "my_field");
let pairs = MotogarageParser::parse(Rule::number, "12345")?;
assert_eq!(pairs.as_str(), "12345");
let pairs = MotogarageParser::parse(Rule::number_with_unit, "600cc")?;
assert_eq!(pairs.as_str(), "600cc");
let pairs = MotogarageParser::parse(Rule::string_literal, r#""Hello World""#)?;
assert_eq!(pairs.as_str(), r#""Hello World""#);
Ok(())
}
#[test]
fn test_parse_property() -> Result<()> {
let mut pairs = MotogarageParser::parse(Rule::property, "year: 2020")?;
let property_pair = pairs.next().unwrap();
let mut inner = property_pair.into_inner();
assert_eq!(inner.next().unwrap().as_str(), "year");
assert_eq!(inner.next().unwrap().as_str(), "2020");
Ok(())
}
#[test]
fn test_parse_definition() -> Result<()> {
let input = r#"
DEFINE bike "Honda CBR600RR" {
year: 2021,
engine: 599cc,
type: sport
}
"#;
let ast = parse_moto_file(input)?;
assert_eq!(ast.len(), 1);
assert_matches!(&ast[0], Command::Definition(bike) if
bike == &Motorcycle {
name: "Honda CBR600RR".to_string(),
year: Some(2021),
engine_cc: Some(599),
bike_type: Some("sport".to_string()),
}
);
Ok(())
}
#[test]
fn test_parse_query_get() -> Result<()> {
let input = "GET BIKES WHERE type = sport";
let ast = parse_moto_file(input)?;
assert_eq!(ast.len(), 1);
assert_matches!(&ast[0], Command::Get(query) if
query == &Query {
condition: Some(Condition {
field: "type".to_string(),
operator: "=".to_string(),
value: Value::StringType("sport".to_string()),
})
}
);
Ok(())
}
#[test]
fn test_parse_query_count() -> Result<()> {
let input = "COUNT BIKES WHERE year > 2020";
let ast = parse_moto_file(input)?;
assert_eq!(ast.len(), 1);
assert_matches!(&ast[0], Command::Count(query) if
query == &Query {
condition: Some(Condition {
field: "year".to_string(),
operator: ">".to_string(),
value: Value::Number(2020),
})
}
);
Ok(())
}
#[test]
fn test_parse_full_file() -> Result<()> {
let input = r#"
DEFINE bike "Bike 1" { year: 2010 }
// Comment
GET BIKES WHERE year > 2000
DEFINE bike "Bike 2" { type: cruiser }
COUNT BIKES
"#;
let ast = parse_moto_file(input)?;
assert_eq!(ast.len(), 4);
assert_matches!(&ast[0], Command::Definition(_));
assert_matches!(&ast[1], Command::Get(_));
assert_matches!(&ast[2], Command::Definition(_));
assert_matches!(&ast[3], Command::Count(_));
Ok(())
}
#[test]
fn test_parse_error() {
let input = "DEFINE bike { year: 2000 }"; let result = parse_moto_file(input);
assert!(result.is_err());
assert_matches!(
result.unwrap_err(),
motogarage_parser::MotoError::ParseError(_)
);
}