#[cfg(test)]
mod tests {
use super::super::common::vm_query;
use serde_json::json;
#[test]
fn read_after_pipe_write_sees_new_value() {
let doc = json!({"a": 1});
let r = vm_query(r#"$.a.set(99) | @.a"#, &doc).unwrap();
assert_eq!(r, json!(99));
}
#[test]
fn read_after_object_write_field_sees_post_write_doc() {
let doc = json!({"x": 10, "y": 20});
let r = vm_query(r#"$.x.set(100) | @.x + @.y"#, &doc).unwrap();
assert_eq!(r, json!(120));
}
#[test]
fn read_after_let_init_write_sees_new_value() {
let doc = json!({"a": 0});
let r = vm_query(r#"let x = $.a.set(7) in x.a"#, &doc).unwrap();
assert_eq!(r, json!(7));
}
#[test]
fn two_writes_same_path_last_wins() {
let doc = json!({"k": 0});
let r = vm_query(r#"patch $ { k: 1, k: 2 }"#, &doc).unwrap();
assert_eq!(r, json!({"k": 2}));
}
#[test]
fn modify_after_set_reads_prebatch_value() {
let doc = json!({"k": 1});
let r = vm_query(r#"patch $ { k: 10, k: @ + 5 }"#, &doc).unwrap();
assert_eq!(r, json!({"k": 6}));
}
#[test]
fn three_chained_sets_apply_in_order() {
let doc = json!({});
let r = vm_query(r#"$.a.set(1) | $.b.set(2) | $.c.set(3)"#, &doc).unwrap();
assert_eq!(r, json!({"a": 1, "b": 2, "c": 3}));
}
#[test]
fn sibling_sets_in_one_batch_share_parent() {
let doc = json!({"user": {"a": 0, "b": 0}});
let r = vm_query(r#"patch $ { user.a: 1, user.b: 2 }"#, &doc).unwrap();
assert_eq!(r, json!({"user": {"a": 1, "b": 2}}));
}
#[test]
fn lambda_writes_dont_leak_to_outer() {
let doc = json!({"list": [{"id": 1}, {"id": 2}]});
let r = vm_query(r#"$.list.map(lambda o: o.id.set(99))"#, &doc).unwrap();
assert_eq!(r, json!([99, 99]));
}
#[test]
fn comprehension_per_iter_writes_isolated() {
let doc = json!({"list": [{"n": 1}, {"n": 2}, {"n": 3}]});
let r = vm_query(r#"[x.n + 10 for x in $.list]"#, &doc).unwrap();
assert_eq!(r, json!([11, 12, 13]));
}
#[test]
fn nested_lambda_currents_distinct() {
let doc = json!({"groups": [[1, 2], [3, 4]]});
let r = vm_query(
r#"$.groups.map(lambda g: g.map(lambda x: x + 10))"#,
&doc,
)
.unwrap();
assert_eq!(r, json!([[11, 12], [13, 14]]));
}
#[test]
fn read_between_writes_breaks_fusion_pin() {
let doc = json!({"a": 5});
let r = vm_query(r#"$.a.set(10) | $.a + 100 | $.b.set(@)"#, &doc).unwrap();
assert!(r.get("b").is_some());
}
#[test]
fn read_then_write_then_read_sees_intermediate() {
let doc = json!({"a": 1, "b": 0});
let r = vm_query(r#"$.b.set($.a + 100) | @.b"#, &doc).unwrap();
assert_eq!(r, json!(101));
}
#[test]
fn conditional_op_only_fires_when_truthy() {
let doc = json!({"role": "admin", "active": false});
let r = vm_query(
r#"patch $ { active: true when $.role == "admin" }"#,
&doc,
)
.unwrap();
assert_eq!(r, json!({"role": "admin", "active": true}));
}
#[test]
fn conditional_skipped_when_falsy_keeps_field() {
let doc = json!({"role": "user", "active": false});
let r = vm_query(
r#"patch $ { active: true when $.role == "admin" }"#,
&doc,
)
.unwrap();
assert_eq!(r, json!({"role": "user", "active": false}));
}
#[test]
fn conditional_reads_prebatch_state() {
let doc = json!({"id": 0, "flag": false});
let r = vm_query(
r#"patch $ { id: 7, flag: true when $.id > 5 }"#,
&doc,
)
.unwrap();
assert_eq!(r, json!({"id": 7, "flag": false}));
}
#[test]
fn let_aliases_root_and_fuses() {
let doc = json!({});
let r = vm_query(r#"let x = $.a.set(1) in x.b.set(2)"#, &doc).unwrap();
assert_eq!(r, json!({"a": 1, "b": 2}));
}
#[test]
fn nested_let_aliases_chain_resolve_to_root_for_reads() {
let doc = json!({"a": 99});
let r = vm_query(
r#"let x = $ in let y = x in y.a"#,
&doc,
)
.unwrap();
assert_eq!(r, json!(99));
}
#[test]
fn let_alias_to_root_then_chain_write_via_root_fuses() {
let doc = json!({});
let r = vm_query(
r#"let x = $.a.set(1) in $.b.set(2)"#,
&doc,
)
.unwrap();
assert_eq!(r, json!({"a": 1, "b": 2}));
}
#[test]
fn let_alias_to_local_chain_write_method_call_semantics() {
let doc = json!({"sub": {"k": 0}});
let r = vm_query(
r#"let x = $.sub in x.k.set(42)"#,
&doc,
)
.unwrap();
assert_eq!(r, json!(42));
}
#[test]
fn modify_with_at_sees_pre_write_value() {
let doc = json!({"a": 5});
let r = vm_query(r#"$.a.modify(@ + 1)"#, &doc).unwrap();
assert_eq!(r, json!({"a": 6}));
}
#[test]
fn modify_referencing_root_field_reads_current_state() {
let doc = json!({"a": 5});
let r = vm_query(r#"$.a.modify(@ + $.a)"#, &doc).unwrap();
assert_eq!(r, json!({"a": 10}));
}
#[test]
fn many_disjoint_writes_correctness() {
let mut ops = Vec::new();
for i in 0..50 {
ops.push(format!("k{}: {}", i, i * 2));
}
let expr = format!("patch $ {{ {} }}", ops.join(", "));
let doc = json!({});
let r = vm_query(&expr, &doc).unwrap();
for i in 0..50 {
assert_eq!(
r[format!("k{}", i)],
json!(i * 2),
"field k{} mismatch",
i
);
}
}
#[test]
fn deep_nested_path_writes() {
let doc = json!({});
let r = vm_query(
r#"$.a.b.c.d.e.f.g.set(1) | $.a.b.c.d.e.f.h.set(2)"#,
&doc,
)
.unwrap();
assert_eq!(
r,
json!({"a": {"b": {"c": {"d": {"e": {"f": {"g": 1, "h": 2}}}}}}})
);
}
#[test]
fn array_index_overlap_last_wins() {
let doc = json!({"items": [0, 0, 0]});
let r = vm_query(
r#"patch $ { items[0]: 10, items[0]: 20, items[0]: 30 }"#,
&doc,
)
.unwrap();
assert_eq!(r, json!({"items": [30, 0, 0]}));
}
#[test]
fn untouched_subtree_intact_after_batch() {
let doc = json!({
"touched": {"x": 0},
"untouched": {"deep": {"list": [1, 2, 3]}}
});
let r = vm_query(r#"patch $ { touched.x: 99 }"#, &doc).unwrap();
assert_eq!(r["untouched"], json!({"deep": {"list": [1, 2, 3]}}));
assert_eq!(r["touched"]["x"], json!(99));
}
#[test]
fn mixed_write_kinds_in_one_patch() {
let doc = json!({"keep": 1, "drop": 2, "bump": 10});
let r = vm_query(
r#"patch $ { keep: 100, drop: DELETE, bump: @ + 5 }"#,
&doc,
)
.unwrap();
assert_eq!(r, json!({"keep": 100, "bump": 15}));
}
}