use parsm::dsl::parse_command;
use parsm::filter::{ComparisonOp, FilterExpr, FilterValue, TemplateItem};
#[test]
fn test_critical_parsing_distinctions() {
println!("\n=== Testing Critical Parsing Distinctions ===");
println!("\nTest 1: $name as field substitution");
let result = parse_command("$name").unwrap();
assert!(result.template.is_some(), "$name should be template");
assert!(result.filter.is_none(), "$name should not be filter");
assert!(
result.field_selector.is_none(),
"$name should not be field selector"
);
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Field(field) => {
assert_eq!(field.parts, vec!["name"]);
println!(
" ✓ $name correctly parsed as field substitution: {:?}",
field.parts
);
}
TemplateItem::Literal(text) => {
panic!("$name should be field substitution, not literal: {text}");
}
TemplateItem::Conditional { .. } => {
panic!("$name should not be conditional template");
}
}
println!("\nTest 3: \"name\" as literal field selector");
let result = parse_command("\"name\"").unwrap();
assert!(
result.field_selector.is_some(),
"\"name\" should be field selector"
);
assert!(result.filter.is_none(), "\"name\" should not be filter");
assert!(result.template.is_none(), "\"name\" should not be template");
let field_selector = result.field_selector.unwrap();
assert_eq!(field_selector.parts, vec!["name"]);
println!(
" ✓ \"name\" correctly parsed as field selector: {:?}",
field_selector.parts
);
println!("\nTest 4: {{name}} as literal template");
let result = parse_command("{name}").unwrap();
assert!(result.template.is_some(), "{{name}} should be template");
assert!(result.filter.is_none(), "{{name}} should not be filter");
assert!(
result.field_selector.is_none(),
"{{name}} should not be field selector"
);
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Literal(text) => assert_eq!(text, "name"),
_ => panic!("{{name}} should be literal template, not field substitution"),
}
println!("\nTest 7: ${{0}} as field substitution");
let result = parse_command("${0}");
match result {
Ok(parsed) => {
if let Some(template) = parsed.template {
if template.items.len() == 1 {
match &template.items[0] {
TemplateItem::Field(field) => {
assert_eq!(field.parts, vec!["$0"]);
println!(" ✓ ${{0}} correctly parsed as field substitution to $0");
}
_ => panic!("${{0}} should be field substitution"),
}
}
} else {
panic!("${{0}} should parse as template");
}
}
Err(e) => {
println!(" âš ${{0}} failed to parse: {e}");
}
}
println!("\n=== All Critical Parsing Distinction Tests Completed ===");
}
#[test]
fn bare_braced_named_variable_requires_p1_3() {
let result = parse_command("${name}").unwrap();
assert!(result.template.is_some(), "${{name}} should be template");
assert!(result.filter.is_none(), "${{name}} should not be filter");
assert!(
result.field_selector.is_none(),
"${{name}} should not be field selector"
);
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Field(field) => {
assert_eq!(field.parts, vec!["name"]);
}
TemplateItem::Literal(text) => {
panic!("${{name}} should be field substitution, not literal: {text}");
}
TemplateItem::Conditional { .. } => {
panic!("${{name}} should not be conditional template");
}
}
}
#[test]
fn bare_dollar_amount_literal_requires_p1_3() {
let result = parse_command("$20").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Literal(text) => assert_eq!(text, "$20"),
_ => panic!("Expected $20 to be literal"),
}
let result = parse_command("$0").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Literal(text) => assert_eq!(text, "$0"),
_ => panic!("Expected $0 to be literal"),
}
}
#[test]
fn test_quoted_string_literals() {
println!("\n=== Testing Quoted String Literals ===");
println!("\nTest 1: \"Alice\" as quoted field selector");
let result = parse_command("\"Alice\"").unwrap();
assert!(
result.field_selector.is_some(),
"\"Alice\" should be field selector"
);
assert!(result.filter.is_none(), "\"Alice\" should not be filter");
assert!(
result.template.is_none(),
"\"Alice\" should not be template"
);
let field_selector = result.field_selector.unwrap();
assert_eq!(field_selector.parts, vec!["Alice"]);
println!(
" ✓ \"Alice\" correctly parsed as field selector: {:?}",
field_selector.parts
);
println!("\nTest 2: \"25\" as quoted field selector");
let result = parse_command("\"25\"").unwrap();
assert!(
result.field_selector.is_some(),
"\"25\" should be field selector"
);
assert!(result.filter.is_none(), "\"25\" should not be filter");
assert!(result.template.is_none(), "\"25\" should not be template");
let field_selector = result.field_selector.unwrap();
assert_eq!(field_selector.parts, vec!["25"]);
println!(
" ✓ \"25\" correctly parsed as field selector: {:?}",
field_selector.parts
);
println!("\nTest 3: 'Alice' as single-quoted field selector");
let result = parse_command("'Alice'").unwrap();
assert!(
result.field_selector.is_some(),
"'Alice' should be field selector"
);
assert!(result.filter.is_none(), "'Alice' should not be filter");
assert!(result.template.is_none(), "'Alice' should not be template");
let field_selector = result.field_selector.unwrap();
assert_eq!(field_selector.parts, vec!["Alice"]);
println!(
" ✓ 'Alice' correctly parsed as field selector: {:?}",
field_selector.parts
);
println!("\nTest 4: 'field name' as quoted field selector with spaces");
let result = parse_command("'field name'").unwrap();
assert!(
result.field_selector.is_some(),
"'field name' should be field selector"
);
let field_selector = result.field_selector.unwrap();
assert_eq!(field_selector.parts, vec!["field name"]);
println!(
" ✓ 'field name' correctly parsed as field selector: {:?}",
field_selector.parts
);
println!("\nTest 5: \"field.with.dots\" as dotted field selector");
let result = parse_command("\"field.with.dots\"").unwrap();
assert!(
result.field_selector.is_some(),
"\"field.with.dots\" should be field selector"
);
let field_selector = result.field_selector.unwrap();
assert_eq!(field_selector.parts, vec!["field", "with", "dots"]);
println!(
" ✓ \"field.with.dots\" correctly parsed as field selector: {:?}",
field_selector.parts
);
println!("\n=== Quoted String Literal Tests Completed ===");
}
#[test]
fn test_template_variable_edge_cases() {
let result = parse_command("${0}").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Field(field) => {
assert_eq!(field.parts, vec!["$0"]);
}
_ => panic!("Expected ${{0}} to be field substitution"),
}
let result = parse_command("$0").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Literal(text) => assert_eq!(text, "$0"),
_ => panic!("Expected $0 to be literal"),
}
let result = parse_command("$20").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Literal(text) => assert_eq!(text, "$20"),
_ => panic!("Expected $20 to be literal"),
}
let result = parse_command("$1").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Literal(text) => assert_eq!(text, "$1"),
_ => panic!("Expected $1 to be literal"),
}
let result = parse_command("${1}").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Field(field) => assert_eq!(field.parts, vec!["1"]),
_ => panic!("Expected ${{1}} to be field substitution"),
}
let result = parse_command("${2}").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Field(field) => assert_eq!(field.parts, vec!["2"]),
_ => panic!("Expected ${{2}} to be field substitution"),
}
let result = parse_command("${20}").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Field(field) => assert_eq!(field.parts, vec!["20"]),
_ => panic!("Expected ${{20}} to be field substitution"),
}
}
#[test]
fn test_mixed_numeric_template_patterns() {
let result = parse_command("{I have $20 and ${name} has $100}").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert!(template.items.len() >= 2);
let mut found_literal_with_dollar = false;
let mut found_field = false;
for item in &template.items {
match item {
TemplateItem::Literal(text) => {
if text.contains("$20") || text.contains("$100") {
found_literal_with_dollar = true;
}
}
TemplateItem::Field(field) if field.parts == vec!["name"] => {
found_field = true;
}
_ => {}
}
}
assert!(
found_literal_with_dollar,
"Should contain literal dollar amounts"
);
assert!(found_field, "Should contain field substitution");
}
#[test]
fn test_parsing_edge_cases() {
println!("\n=== Testing Edge Cases ===");
let test_cases = vec![
("$1", "literal dollar amount"),
("$999", "literal dollar amount"),
("$00", "literal dollar amount"),
("$01", "literal dollar amount"),
("${1}", "field substitution"),
("${999}", "field substitution"),
("${00}", "field substitution"),
("${01}", "field substitution"),
("$a", "field substitution - single letter"),
("$_", "field substitution - underscore"),
("$name_123", "field substitution - alphanumeric"),
("{$20}", "literal template with dollar amount"),
("{${name}}", "template with field substitution"),
("\"$20\"", "quoted literal"),
("$", "bare dollar sign"),
("${}", "empty braced expression"),
("{}", "empty braces"),
];
for (input, description) in test_cases {
println!("\nTesting edge case: {input} ({description})");
match parse_command(input) {
Ok(result) => {
println!(" ✓ Parsed successfully:");
println!(" Filter: {:?}", result.filter.is_some());
println!(" Template: {:?}", result.template.is_some());
println!(" Field selector: {:?}", result.field_selector.is_some());
match input {
"$1" | "$999" | "$00" | "$01" => {
assert!(result.template.is_some(), "{input} should be template");
if let Some(template) = result.template
&& !template.items.is_empty()
{
match &template.items[0] {
TemplateItem::Literal(text) => assert_eq!(text, input),
_ => panic!("{input} should be literal"),
}
}
}
"${1}" | "${999}" | "${00}" | "${01}" => {
assert!(result.template.is_some(), "{input} should be template");
if let Some(template) = result.template
&& !template.items.is_empty()
{
match &template.items[0] {
TemplateItem::Field(_) => {} _ => panic!("{input} should be field substitution"),
}
}
}
"\"$20\"" => {
assert!(
result.field_selector.is_some(),
"{input} should be field selector"
);
}
_ => {} }
}
Err(e) => {
println!(" âš Failed to parse: {e}");
}
}
}
println!("\n=== Edge Case Tests Completed ===");
}
#[test]
fn test_comprehensive_disambiguation() {
let test_cases = vec![
("{${name}}", "template"),
("{State of ${name}}", "template"),
("$name", "template"),
("{name}", "literal_template"),
("name", "field_selector"),
("user.email", "field_selector"),
("\"field name\"", "field_selector"),
("name == \"Alice\"", "filter"),
("age > 25", "filter"),
("user.active == true", "filter"),
];
for (input, expected_type) in test_cases {
let result = parse_command(input);
match expected_type {
"template" => {
assert!(result.is_ok(), "Template '{input}' should parse");
let parsed = result.unwrap();
assert!(
parsed.template.is_some(),
"Input '{input}' should be template"
);
assert!(
parsed.filter.is_none(),
"Input '{input}' should not be filter"
);
assert!(
parsed.field_selector.is_none(),
"Input '{input}' should not be field selector"
);
}
"field_selector" => {
assert!(result.is_ok(), "Field selector '{input}' should parse");
let parsed = result.unwrap();
assert!(
parsed.field_selector.is_some(),
"Input '{input}' should be field selector"
);
assert!(
parsed.filter.is_none(),
"Input '{input}' should not be filter"
);
assert!(
parsed.template.is_none(),
"Input '{input}' should not be template"
);
}
"filter" => {
assert!(result.is_ok(), "Filter '{input}' should parse");
let parsed = result.unwrap();
assert!(parsed.filter.is_some(), "Input '{input}' should be filter");
assert!(
parsed.template.is_some(),
"Input '{input}' should have a template (default templates are now added to filters)"
);
assert!(
parsed.field_selector.is_none(),
"Input '{input}' should not be field selector"
);
}
"literal_template" => {
assert!(result.is_ok(), "Literal template '{input}' should parse");
let parsed = result.unwrap();
assert!(
parsed.template.is_some(),
"Input '{input}' should be template"
);
assert!(
parsed.filter.is_none(),
"Input '{input}' should not be filter"
);
assert!(
parsed.field_selector.is_none(),
"Input '{input}' should not be field selector"
);
let template = parsed.template.unwrap();
if template.items.len() == 1 {
if let TemplateItem::Literal(_) = &template.items[0] {
} else {
panic!("Input '{input}' should be literal template, not field");
}
}
}
_ => panic!("Unknown expected type: {expected_type}"),
}
}
}
#[test]
fn test_filter_expressions() {
let result = parse_command(r#"name == "Alice""#).unwrap();
assert!(result.filter.is_some());
assert!(result.template.is_some());
assert!(result.field_selector.is_none());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["name"]);
assert_eq!(op, ComparisonOp::Equal);
assert_eq!(value, FilterValue::String("Alice".to_string()));
} else {
panic!("Expected simple comparison");
}
let result = parse_command("age > 25").unwrap();
assert!(result.filter.is_some());
assert!(result.template.is_some());
assert!(result.field_selector.is_none());
}
#[test]
fn test_complex_boolean_expressions() {
let result = parse_command("active?").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::FieldTruthy(field)) = result.filter {
assert_eq!(field.parts, vec!["active"]);
} else {
panic!("Expected field truthy");
}
let result = parse_command("!active?").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Not(inner)) = result.filter {
if let FilterExpr::FieldTruthy(field) = inner.as_ref() {
assert_eq!(field.parts, vec!["active"]);
} else {
panic!("Expected NOT of field truthy");
}
} else {
panic!("Expected NOT expression");
}
}
#[test]
fn test_nested_field_access() {
let result = parse_command("user.email == \"alice@example.com\"").unwrap();
if let Some(FilterExpr::Comparison { field, .. }) = result.filter {
assert_eq!(field.parts, vec!["user", "email"]);
} else {
panic!("Expected comparison with nested field");
}
let result = parse_command("{${user.name}}").unwrap();
let template = result.template.unwrap();
match &template.items[0] {
TemplateItem::Field(field) => assert_eq!(field.parts, vec!["user", "name"]),
_ => panic!("Expected nested field"),
}
let result = parse_command("user.profile.name").unwrap();
let field = result.field_selector.unwrap();
assert_eq!(field.parts, vec!["user", "profile", "name"]);
}
#[test]
fn test_bracketed_template_syntax() {
let result = parse_command("[${name}]").unwrap();
assert!(result.template.is_some());
assert!(result.filter.is_none());
assert!(result.field_selector.is_none());
let template = result.template.unwrap();
assert_eq!(template.items.len(), 1);
match &template.items[0] {
TemplateItem::Field(field) => assert_eq!(field.parts, vec!["name"]),
_ => panic!("Expected field"),
}
let result = parse_command("[Name: ${name}, Age: ${age}]").unwrap();
assert!(result.template.is_some());
let template = result.template.unwrap();
assert!(template.items.len() >= 3);
let mut found_name_field = false;
let mut found_age_field = false;
let mut found_literal_content = false;
for item in &template.items {
match item {
TemplateItem::Field(field) => {
if field.parts == vec!["name"] {
found_name_field = true;
} else if field.parts == vec!["age"] {
found_age_field = true;
}
}
TemplateItem::Literal(text) if (text.contains("Name:") || text.contains("Age:")) => {
found_literal_content = true;
}
_ => {}
}
}
assert!(found_name_field, "Should contain name field");
assert!(found_age_field, "Should contain age field");
assert!(found_literal_content, "Should contain literal content");
}
#[test]
fn test_array_element_selection() {
use parsm::filter::FieldPath;
use serde_json::json;
let data = json!({
"users": [
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25}
],
"items": ["apple", "banana", "cherry"]
});
let field_path = FieldPath::new(vec![
"users".to_string(),
"0".to_string(),
"name".to_string(),
]);
let result = field_path.get_value(&data);
assert_eq!(result, Some(&json!("Alice")));
let field_path = FieldPath::new(vec![
"users".to_string(),
"1".to_string(),
"name".to_string(),
]);
let result = field_path.get_value(&data);
assert_eq!(result, Some(&json!("Bob")));
let field_path = FieldPath::new(vec!["items".to_string(), "0".to_string()]);
let result = field_path.get_value(&data);
assert_eq!(result, Some(&json!("apple")));
let result = parse_command("users.0.name").unwrap();
assert!(result.field_selector.is_some());
assert!(result.filter.is_none());
assert!(result.template.is_none());
if let Some(field_selector) = result.field_selector {
assert_eq!(field_selector.parts, vec!["users", "0", "name"]);
}
}
#[test]
fn test_regex_matching() {
let result = parse_command("name ~= /^[A-Z]/");
match result {
Ok(parsed) => {
assert!(parsed.filter.is_some(), "Regex pattern should be filter");
if let Some(FilterExpr::Comparison { field, op, value }) = parsed.filter {
assert_eq!(field.parts, vec!["name"]);
assert!(
matches!(op, ComparisonOp::Regex),
"Should be regex operator"
);
if let FilterValue::Regex { pattern, .. } = value {
assert!(pattern.contains("^[A-Z]"), "Should contain regex pattern");
} else {
panic!("Expected regex value for regex pattern");
}
} else {
panic!("Expected comparison expression with regex operator");
}
}
Err(e) => {
println!("Note: Regex parsing may not be fully implemented: {e}");
}
}
}
#[test]
fn test_all_comparison_operators() {
let result = parse_command(r#"name == "Alice""#).unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["name"]);
assert_eq!(op, ComparisonOp::Equal);
assert_eq!(value, FilterValue::String("Alice".to_string()));
} else {
panic!("Expected equality comparison");
}
let result = parse_command(r#"name != "Bob""#).unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["name"]);
assert_eq!(op, ComparisonOp::NotEqual);
assert_eq!(value, FilterValue::String("Bob".to_string()));
} else {
panic!("Expected not equal comparison");
}
let result = parse_command("age < 30").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["age"]);
assert_eq!(op, ComparisonOp::LessThan);
assert_eq!(value, FilterValue::Number(30.0));
} else {
panic!("Expected less than comparison");
}
let result = parse_command("age <= 30").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["age"]);
assert_eq!(op, ComparisonOp::LessThanOrEqual);
assert_eq!(value, FilterValue::Number(30.0));
} else {
panic!("Expected less than or equal comparison");
}
let result = parse_command("age > 25").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["age"]);
assert_eq!(op, ComparisonOp::GreaterThan);
assert_eq!(value, FilterValue::Number(25.0));
} else {
panic!("Expected greater than comparison");
}
let result = parse_command("age >= 25").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["age"]);
assert_eq!(op, ComparisonOp::GreaterThanOrEqual);
assert_eq!(value, FilterValue::Number(25.0));
} else {
panic!("Expected greater than or equal comparison");
}
let result = parse_command(r#"name *= "lic""#).unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["name"]);
assert_eq!(op, ComparisonOp::Contains);
assert_eq!(value, FilterValue::String("lic".to_string()));
} else {
panic!("Expected contains comparison");
}
let result = parse_command(r#"name ^= "Al""#).unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["name"]);
assert_eq!(op, ComparisonOp::StartsWith);
assert_eq!(value, FilterValue::String("Al".to_string()));
} else {
panic!("Expected starts with comparison");
}
let result = parse_command(r#"name $= "ice""#).unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["name"]);
assert_eq!(op, ComparisonOp::EndsWith);
assert_eq!(value, FilterValue::String("ice".to_string()));
} else {
panic!("Expected ends with comparison");
}
let result = parse_command(r#"email ~= "@.*\.com$""#).unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["email"]);
assert_eq!(op, ComparisonOp::Regex);
assert_eq!(value, FilterValue::String("@.*\\.com$".to_string()));
} else {
panic!("Expected regex comparison");
}
}
#[test]
fn test_operators_with_different_value_types() {
let result = parse_command(r#"name == "Alice""#).unwrap();
assert!(result.filter.is_some());
let result = parse_command("age >= 18").unwrap();
assert!(result.filter.is_some());
let result = parse_command("active == true").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["active"]);
assert_eq!(op, ComparisonOp::Equal);
assert_eq!(value, FilterValue::Boolean(true));
} else {
panic!("Expected boolean comparison");
}
let result = parse_command("active != false").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["active"]);
assert_eq!(op, ComparisonOp::NotEqual);
assert_eq!(value, FilterValue::Boolean(false));
} else {
panic!("Expected boolean not equal comparison");
}
let result = parse_command("score <= 98.5").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison { field, op, value }) = result.filter {
assert_eq!(field.parts, vec!["score"]);
assert_eq!(op, ComparisonOp::LessThanOrEqual);
assert_eq!(value, FilterValue::Number(98.5));
} else {
panic!("Expected decimal number comparison");
}
}
#[test]
fn test_operator_precedence_and_spacing() {
let result = parse_command("age>=25").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison {
field: _,
op,
value: _,
}) = result.filter
{
assert_eq!(op, ComparisonOp::GreaterThanOrEqual);
} else {
panic!("Expected >= operator parsing without spaces");
}
let result = parse_command("age<=30").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison {
field: _,
op,
value: _,
}) = result.filter
{
assert_eq!(op, ComparisonOp::LessThanOrEqual);
} else {
panic!("Expected <= operator parsing without spaces");
}
let result = parse_command(r#"name!="Bob""#).unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison {
field: _,
op,
value: _,
}) = result.filter
{
assert_eq!(op, ComparisonOp::NotEqual);
} else {
panic!("Expected != operator parsing without spaces");
}
let result = parse_command("age < 30").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison {
field: _,
op,
value: _,
}) = result.filter
{
assert_eq!(op, ComparisonOp::LessThan);
} else {
panic!("Expected < operator with spaces");
}
let result = parse_command("age > 25").unwrap();
assert!(result.filter.is_some());
if let Some(FilterExpr::Comparison {
field: _,
op,
value: _,
}) = result.filter
{
assert_eq!(op, ComparisonOp::GreaterThan);
} else {
panic!("Expected > operator with spaces");
}
}