use json_eval_rs::*;
use serde_json::json;
#[cfg(test)]
mod table_tests {
use super::*;
#[test]
fn test_valueat_basic() {
let mut engine = RLogic::new();
let data = json!({
"table": [
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25},
{"name": "Charlie", "age": 35}
]
});
let logic_id = engine
.compile(&json!({"VALUEAT": [{"var": "table"}, 1]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!({"name": "Bob", "age": 25}));
let logic_id = engine
.compile(&json!({"VALUEAT": [{"var": "table"}, 1, "name"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!("Bob"));
let logic_id = engine
.compile(&json!({"VALUEAT": [{"var": "table"}, 2, "age"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(35));
}
#[test]
fn test_valueat_edge_cases() {
let mut engine = RLogic::new();
let data = json!({
"table": [
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25}
]
});
let logic_id = engine
.compile(&json!({"VALUEAT": [{"var": "table"}, -1]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(null));
let logic_id = engine
.compile(&json!({"VALUEAT": [{"var": "table"}, 5]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(null));
let data = json!({"table": []});
let logic_id = engine
.compile(&json!({"VALUEAT": [{"var": "table"}, 0]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(null));
let data = json!({"table": [{"name": "Alice"}]});
let logic_id = engine
.compile(&json!({"VALUEAT": [{"var": "table"}, 0, "missing"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(null));
}
#[test]
fn test_maxat() {
let mut engine = RLogic::new();
let data = json!({
"table": [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 92},
{"name": "Charlie", "score": 78}
]
});
let logic_id = engine
.compile(&json!({"MAXAT": [{"var": "table"}, "score"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(78)); }
#[test]
fn test_indexat() {
let mut engine = RLogic::new();
let data = json!({
"table": [
{"id": 100, "name": "Alice"},
{"id": 200, "name": "Bob"},
{"id": 300, "name": "Charlie"}
]
});
let logic_id = engine
.compile(&json!({"INDEXAT": [200, {"var": "table"}, "id"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(1));
let logic_id = engine
.compile(&json!({"INDEXAT": [250, {"var": "table"}, "id", true]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(0));
let logic_id = engine
.compile(&json!({"INDEXAT": [50, {"var": "table"}, "id", true]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(-1));
let logic_id = engine
.compile(&json!({"INDEXAT": [999, {"var": "table"}, "id"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(-1));
}
#[test]
fn test_match() {
let mut engine = RLogic::new();
let data = json!({
"table": [
{"name": "Alice", "age": 30, "city": "NYC"},
{"name": "Bob", "age": 25, "city": "LA"},
{"name": "Charlie", "age": 35, "city": "NYC"}
]
});
let logic_id = engine
.compile(&json!({"MATCH": [{"var": "table"}, "Alice", "name"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(0));
let logic_id = engine
.compile(&json!({"MATCH": [{"var": "table"}, "Alice", "name", "NYC", "city"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(0));
let logic_id = engine
.compile(&json!({"MATCH": [{"var": "table"}, "David", "name"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(-1));
}
#[test]
fn test_match_range() {
let mut engine = RLogic::new();
let data = json!({
"rates": [
{"min_age": 0, "max_age": 25, "rate": 0.05},
{"min_age": 26, "max_age": 40, "rate": 0.07},
{"min_age": 41, "max_age": 60, "rate": 0.09}
]
});
let logic_id = engine
.compile(&json!({"MATCHRANGE": [{"var": "rates"}, "min_age", "max_age", 30]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(1));
let logic_id = engine
.compile(&json!({"MATCHRANGE": [{"var": "rates"}, "min_age", "max_age", 50]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(2));
}
#[test]
fn test_choose() {
let mut engine = RLogic::new();
let data = json!({
"products": [
{"name": "Widget", "category": "A", "price": 10},
{"name": "Gadget", "category": "B", "price": 20},
{"name": "Tool", "category": "A", "price": 15}
]
});
let logic_id = engine
.compile(&json!({"CHOOSE": [{"var": "products"}, "A", "category"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
let index = result.as_f64().unwrap();
assert!(index == 0.0 || index == 2.0);
let products = data["products"].as_array().unwrap();
let product = &products[index as usize];
assert_eq!(product["category"], "A");
}
#[test]
fn test_find_index() {
let mut engine = RLogic::new();
let data = json!({
"items": [
{"value": 10, "active": true},
{"value": 20, "active": false},
{"value": 30, "active": true}
]
});
let logic_id = engine
.compile(&json!({"FINDINDEX": [{"var": "items"},
"active", [">", 15, "value"]
]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
println!("Result with active AND value>15: {}", result);
println!("Expected: 2 (item 2 has active=true AND value=30 > 15)");
println!(
"Item 0: active={}, value={}",
data["items"][0]["active"], data["items"][0]["value"]
);
println!(
"Item 1: active={}, value={}",
data["items"][1]["active"], data["items"][1]["value"]
);
println!(
"Item 2: active={}, value={}",
data["items"][2]["active"], data["items"][2]["value"]
);
assert_eq!(result, json!(2));
let logic_id = engine
.compile(&json!({"FINDINDEX": [{"var": "items"},
{">": [{"var": "value"}, 50]}
]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(-1));
}
#[test]
fn test_table_operations_with_references() {
let mut engine = RLogic::new();
let data = json!({
"$params": {
"mortality_table": [
{"age": 30, "qx": 0.001},
{"age": 35, "qx": 0.002},
{"age": 40, "qx": 0.003}
]
},
"current_age": 35
});
let logic_id = engine
.compile(&json!({"VALUEAT": [
{"$ref": "$params.mortality_table"},
{"INDEXAT": [{"var": "current_age"}, {"$ref": "$params.mortality_table"}, "age"]},
"qx"
]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(0.002));
}
#[test]
fn test_table_operations_performance() {
let mut engine = RLogic::new();
let mut table = Vec::new();
for i in 0..100 {
table.push(json!({"id": i, "value": i * 2, "active": i % 2 == 0}));
}
let data = json!({"table": table});
let logic_id = engine
.compile(&json!({"VALUEAT": [{"var": "table"}, 50, "value"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(100));
let logic_id = engine
.compile(&json!({"INDEXAT": [75, {"var": "table"}, "id"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(75));
let logic_id = engine
.compile(&json!({"MATCH": [{"var": "table"}, true, "active"]}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(0)); }
#[test]
fn test_table_operations_errors() {
let mut engine = RLogic::new();
let data = json!({"not_array": "string"});
let logic_id = engine
.compile(&json!({"VALUEAT": [{"var": "not_array"}, 0]}))
.unwrap();
let result = engine.run(&logic_id, &data);
assert!(result.is_err() || result.unwrap().is_null());
let logic_id = engine
.compile(&json!({"INDEXAT": [1, {"var": "not_array"}, "field"]}))
.unwrap();
let result = engine.run(&logic_id, &data);
assert!(result.is_err() || result.unwrap() == json!(-1.0));
let logic_id = engine
.compile(&json!({"MATCH": [{"var": "not_array"}, "value", "field"]}))
.unwrap();
let result = engine.run(&logic_id, &data);
assert!(result.is_err() || result.unwrap() == json!(-1.0));
}
#[test]
fn test_findindex_preprocessing() {
let mut engine = RLogic::new();
let data = json!({"items": [{"x": 10}, {"x": 20}]});
let logic_id = engine
.compile(&json!({
"FINDINDEX": [{"var": "items"}, ["==", 20, "x"]]
}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
println!("Test 1 (number) result: {}", result);
assert_eq!(result, json!(1));
let data2 = json!({"items": [{"name": "Alice"}, {"name": "Bob"}]});
let logic_id = engine
.compile(&json!({
"FINDINDEX": [{"var": "items"}, ["==", "Bob", "name"]]
}))
.unwrap();
let result = engine.run(&logic_id, &data2).unwrap();
println!("Test 2 (string) result: {}", result);
assert_eq!(result, json!(1)); }
#[test]
fn test_findindex_with_and() {
let mut engine = RLogic::new();
let data = json!({
"employees": [
{"id": 1, "name": "Alice", "salary": 50000, "department": "Engineering"},
{"id": 2, "name": "Bob", "salary": 55000, "department": "Sales"},
{"id": 3, "name": "Charlie", "salary": 60000, "department": "Engineering"},
{"id": 4, "name": "Diana", "salary": 52000, "department": "Sales"}
]
});
let logic_id = engine
.compile(&json!({
"FINDINDEX": [
{"var": "employees"},
["==", "Engineering", "department"]
]
}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(0));
let logic_id = engine
.compile(&json!({
"FINDINDEX": [
{"var": "employees"},
["&&",
["==", "Engineering", "department"],
[">", 55000, "salary"]
]
]
}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(2)); }
#[test]
fn test_combined_table_operations() {
let mut engine = RLogic::new();
let data = json!({
"employees": [
{"id": 1, "name": "Alice", "salary": 50000, "department": "Engineering"},
{"id": 2, "name": "Bob", "salary": 55000, "department": "Sales"},
{"id": 3, "name": "Charlie", "salary": 60000, "department": "Engineering"},
{"id": 4, "name": "Diana", "salary": 52000, "department": "Sales"}
]
});
let logic_id = engine
.compile(&json!({
"VALUEAT": [
{"var": "employees"},
{"FINDINDEX": [
{"var": "employees"},
["&&",
["==", "Engineering", "department"],
[">", 55000, "salary"]
]
]},
"name"
]
}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!("Charlie"));
let logic_id = engine
.compile(&json!({
"sum": [{"map": [
{"filter": [
{"var": "employees"},
{"==": [{"var": "department"}, "Engineering"]}
]},
{"var": "salary"}
]}]
}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!(110000)); }
#[test]
fn test_mapoptions() {
let mut engine = RLogic::new();
let data = json!({
"options": [
{"id": 1, "name": "Option 1", "active": true},
{"id": 2, "name": "Option 2", "active": false},
{"id": 3, "name": "Option 3", "active": true}
]
});
let logic_id = engine
.compile(&json!({
"MAPOPTIONS": [{"var": "options"}, "name", "id"]
}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(
result,
json!([
{"label": "Option 1", "value": 1},
{"label": "Option 2", "value": 2},
{"label": "Option 3", "value": 3}
])
);
}
#[test]
fn test_mapoptionsif() {
let mut engine = RLogic::new();
let data = json!({
"options": [
{"id": 1, "name": "Option 1", "visible": true},
{"id": 2, "name": "Option 2", "visible": false},
{"id": 3, "name": "Option 3", "visible": true}
]
});
let logic_id = engine
.compile(&json!({
"MAPOPTIONSIF": [
{"var": "options"},
"name",
"id",
true, "==", "visible"
]
}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(
result,
json!([
{"label": "Option 1", "value": 1},
{"label": "Option 3", "value": 3}
])
);
let logic_id2 = engine
.compile(&json!({
"MAPOPTIONSIF": [
{"var": "options"},
"name",
"id",
false, "==", "visible",
2, "==", "id"
]
}))
.unwrap();
let result2 = engine.run(&logic_id2, &data).unwrap();
assert_eq!(
result2,
json!([
{"label": "Option 2", "value": 2}
])
);
let logic_id3 = engine
.compile(&json!({
"MAPOPTIONSIF": [
{"var": "options"},
"name",
"id",
[true, "==", "visible"]
]
}))
.unwrap();
let result3 = engine.run(&logic_id3, &data).unwrap();
assert_eq!(
result3,
json!([
{"label": "Option 1", "value": 1},
{"label": "Option 3", "value": 3}
])
);
}
#[test]
fn test_mapoptions_with_ref() {
let mut engine = RLogic::new();
let data = json!({
"$params": {
"system_options": [
{"code": "A", "desc": "Alpha", "active": true},
{"code": "B", "desc": "Beta", "active": false},
{"code": "C", "desc": "Gamma", "active": true}
]
}
});
let logic_id = engine
.compile(&json!({
"MAPOPTIONS": [{"$ref": "$params/system_options"}, "desc", "code"]
}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(
result,
json!([
{"label": "Alpha", "value": "A"},
{"label": "Beta", "value": "B"},
{"label": "Gamma", "value": "C"}
])
);
}
#[test]
fn test_mapoptionsif_with_ref() {
let mut engine = RLogic::new();
let data = json!({
"$params": {
"system_options": [
{"code": "A", "desc": "Alpha", "visible": true},
{"code": "B", "desc": "Beta", "visible": false},
{"code": "C", "desc": "Gamma", "visible": true}
]
}
});
let logic_id = engine
.compile(&json!({
"MAPOPTIONSIF": [
{"$ref": "$params/system_options"},
"desc",
"code",
true, "==", "visible"
]
}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(
result,
json!([
{"label": "Alpha", "value": "A"},
{"label": "Gamma", "value": "C"}
])
);
}
#[test]
fn test_mapoptionsif_with_evaluation_blocks() {
let mut engine = RLogic::new();
let data = json!({
"options": [
{
"id": 1,
"name": "Option 1",
"visible": { "$evaluation": { "==": [1, 1] } }
},
{
"id": 2,
"name": "Option 2",
"visible": { "$evaluation": { "==": [1, 2] } }
}
]
});
let logic_id = engine
.compile(&json!({
"MAPOPTIONSIF": [
{"var": "options"},
"name",
"id",
true, "==", "visible"
]
}))
.unwrap();
let result = engine.run(&logic_id, &data).unwrap();
assert_eq!(result, json!([])); }
}