Skip to main content

suture_driver_json/
lib.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2use serde_json::Value;
3use suture_driver::{DriverError, SemanticChange, SutureDriver};
4use suture_driver::impl_structured_driver;
5
6pub struct JsonDriver;
7
8impl JsonDriver {
9    fn json_pointer_escape(s: &str) -> String {
10        s.replace('~', "~0").replace('/', "~1")
11    }
12}
13
14impl_structured_driver! {
15    driver = JsonDriver,
16    name = "JSON",
17    extensions = [".json"],
18    value_ty = Value,
19
20    obj_pat = |_m| Value::Object(_m),
21    arr_pat = |_v| Value::Array(_v),
22
23    new_map = serde_json::Map::new(),
24    wrap_map = |m| Value::Object(m),
25    wrap_arr = |v| Value::Array(v),
26
27    key_set = |map| map.keys().map(|s| s.as_str()).collect::<std::collections::HashSet<&str>>(),
28    map_get = |map, key| Some(&map[*key]),
29    map_insert = |map, key, val| { map.insert(key.to_string(), val); },
30
31    val_str = |v| v.to_string(),
32    child_path = |parent, key| {
33        let escaped = JsonDriver::json_pointer_escape(key);
34        if parent == "/" { format!("/{escaped}") } else { format!("{parent}/{escaped}") }
35    },
36
37    parse_val = |s| serde_json::from_str(s).map_err(|e| DriverError::ParseError(e.to_string())),
38    serialize_val = |v| serde_json::to_string_pretty(v).map_err(|e| DriverError::SerializationError(e.to_string())),
39
40    arrow = "→",
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn test_json_driver_name() {
49        let driver = JsonDriver::new();
50        assert_eq!(driver.name(), "JSON");
51    }
52
53    #[test]
54    fn test_json_driver_extensions() {
55        let driver = JsonDriver::new();
56        assert_eq!(driver.supported_extensions(), &[".json"]);
57    }
58
59    #[test]
60    fn test_diff_added_key() {
61        let driver = JsonDriver::new();
62        let old = r#"{"name": "Alice"}"#;
63        let new = r#"{"name": "Alice", "email": "alice@example.com"}"#;
64
65        let changes = driver.diff(Some(old), new).unwrap();
66        assert!(changes.contains(&SemanticChange::Added {
67            path: "/email".to_string(),
68            value: "\"alice@example.com\"".to_string(),
69        }));
70    }
71
72    #[test]
73    fn test_diff_removed_key() {
74        let driver = JsonDriver::new();
75        let old = r#"{"name": "Alice", "phone": "+1234567890"}"#;
76        let new = r#"{"name": "Alice"}"#;
77
78        let changes = driver.diff(Some(old), new).unwrap();
79        assert!(changes.contains(&SemanticChange::Removed {
80            path: "/phone".to_string(),
81            old_value: "\"+1234567890\"".to_string(),
82        }));
83    }
84
85    #[test]
86    fn test_diff_modified_key() {
87        let driver = JsonDriver::new();
88        let old = r#"{"name": "Alice"}"#;
89        let new = r#"{"name": "Bob"}"#;
90
91        let changes = driver.diff(Some(old), new).unwrap();
92        assert_eq!(changes.len(), 1);
93        assert_eq!(
94            changes[0],
95            SemanticChange::Modified {
96                path: "/name".to_string(),
97                old_value: "\"Alice\"".to_string(),
98                new_value: "\"Bob\"".to_string(),
99            }
100        );
101    }
102
103    #[test]
104    fn test_diff_nested() {
105        let driver = JsonDriver::new();
106        let old = r#"{"address": {"city": "NYC", "zip": "10001"}}"#;
107        let new = r#"{"address": {"city": "San Francisco", "zip": "10001"}}"#;
108
109        let changes = driver.diff(Some(old), new).unwrap();
110        assert!(changes.contains(&SemanticChange::Modified {
111            path: "/address/city".to_string(),
112            old_value: "\"NYC\"".to_string(),
113            new_value: "\"San Francisco\"".to_string(),
114        }));
115    }
116
117    #[test]
118    fn test_diff_new_file() {
119        let driver = JsonDriver::new();
120        let new = r#"{"name": "Alice", "age": 30}"#;
121
122        let changes = driver.diff(None, new).unwrap();
123        assert!(!changes.is_empty());
124        for change in &changes {
125            assert!(matches!(change, SemanticChange::Added { .. }));
126        }
127    }
128
129    #[test]
130    fn test_format_diff() {
131        let driver = JsonDriver::new();
132        let old = r#"{"name": "Alice"}"#;
133        let new = r#"{"name": "Bob", "email": "bob@example.com"}"#;
134
135        let output = driver.format_diff(Some(old), new).unwrap();
136        assert!(output.contains("MODIFIED"));
137        assert!(output.contains("ADDED"));
138        assert!(output.contains("/name"));
139        assert!(output.contains("/email"));
140    }
141
142    #[test]
143    fn test_format_diff_empty() {
144        let driver = JsonDriver::new();
145        let content = r#"{"name": "Alice"}"#;
146
147        let output = driver.format_diff(Some(content), content).unwrap();
148        assert_eq!(output, "no changes");
149    }
150
151    #[test]
152    fn test_array_changes() {
153        let driver = JsonDriver::new();
154        let old = r#"{"items": ["a", "b"]}"#;
155        let new = r#"{"items": ["a", "c", "d"]}"#;
156
157        let changes = driver.diff(Some(old), new).unwrap();
158        assert!(changes.contains(&SemanticChange::Modified {
159            path: "/items/1".to_string(),
160            old_value: "\"b\"".to_string(),
161            new_value: "\"c\"".to_string(),
162        }));
163        assert!(changes.contains(&SemanticChange::Added {
164            path: "/items/2".to_string(),
165            value: "\"d\"".to_string(),
166        }));
167    }
168
169    #[test]
170    fn test_merge_no_conflict() {
171        let driver = JsonDriver::new();
172        let base = r#"{"a": 1, "b": 2, "c": 3}"#;
173        let ours = r#"{"a": 10, "b": 2, "c": 3}"#;
174        let theirs = r#"{"a": 1, "b": 2, "c": 30}"#;
175
176        let result = driver.merge(base, ours, theirs).unwrap();
177        assert!(result.is_some());
178        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
179        assert_eq!(merged["a"], 10);
180        assert_eq!(merged["b"], 2);
181        assert_eq!(merged["c"], 30);
182    }
183
184    #[test]
185    fn test_merge_conflict() {
186        let driver = JsonDriver::new();
187        let base = r#"{"key": "original"}"#;
188        let ours = r#"{"key": "ours"}"#;
189        let theirs = r#"{"key": "theirs"}"#;
190
191        let result = driver.merge(base, ours, theirs).unwrap();
192        assert!(result.is_none());
193    }
194
195    #[test]
196    fn test_merge_both_add_different_keys() {
197        let driver = JsonDriver::new();
198        let base = r#"{"a": 1}"#;
199        let ours = r#"{"a": 1, "x": 100}"#;
200        let theirs = r#"{"a": 1, "y": 200}"#;
201
202        let result = driver.merge(base, ours, theirs).unwrap();
203        assert!(result.is_some());
204        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
205        assert_eq!(merged["a"], 1);
206        assert_eq!(merged["x"], 100);
207        assert_eq!(merged["y"], 200);
208    }
209
210    #[test]
211    fn test_merge_both_add_same_key() {
212        let driver = JsonDriver::new();
213        let base = r#"{"a": 1}"#;
214        let ours = r#"{"a": 1, "x": 100}"#;
215        let theirs = r#"{"a": 1, "x": 999}"#;
216
217        let result = driver.merge(base, ours, theirs).unwrap();
218        assert!(result.is_none());
219    }
220
221    #[test]
222    fn test_merge_nested() {
223        let driver = JsonDriver::new();
224        let base = r#"{"outer": {"inner": "base", "other": "keep"}}"#;
225        let ours = r#"{"outer": {"inner": "ours", "other": "keep"}}"#;
226        let theirs = r#"{"outer": {"inner": "base", "other": "changed"}}"#;
227
228        let result = driver.merge(base, ours, theirs).unwrap();
229        assert!(result.is_some());
230        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
231        assert_eq!(merged["outer"]["inner"], "ours");
232        assert_eq!(merged["outer"]["other"], "changed");
233    }
234
235    #[test]
236    fn test_merge_identical() {
237        let driver = JsonDriver::new();
238        let content = r#"{"a": 1, "b": 2}"#;
239
240        let result = driver.merge(content, content, content).unwrap();
241        assert!(result.is_some());
242        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
243        assert_eq!(merged["a"], 1);
244        assert_eq!(merged["b"], 2);
245    }
246
247    #[test]
248    fn test_correctness_merge_determinism() {
249        let driver = JsonDriver::new();
250        let base = r#"{"a": 1, "b": 2, "c": 3}"#;
251        let ours = r#"{"a": 10, "b": 2, "d": 4}"#;
252        let theirs = r#"{"a": 1, "b": 20, "e": 5}"#;
253
254        let r1 = driver.merge(base, ours, theirs).unwrap();
255        let r2 = driver.merge(base, theirs, ours).unwrap();
256        assert_eq!(r1.is_some(), r2.is_some());
257        if let (Some(m1), Some(m2)) = (r1, r2) {
258            let v1: Value = serde_json::from_str(&m1).unwrap();
259            let v2: Value = serde_json::from_str(&m2).unwrap();
260            assert_eq!(
261                v1, v2,
262                "merge(base, ours, theirs) must equal merge(base, theirs, ours)"
263            );
264        }
265    }
266
267    #[test]
268    fn test_correctness_merge_idempotency() {
269        let driver = JsonDriver::new();
270        let base = r#"{"a": 1, "b": 2}"#;
271        let ours = r#"{"a": 10, "b": 2, "c": 3}"#;
272
273        let result = driver.merge(base, ours, ours).unwrap();
274        assert!(result.is_some());
275        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
276        let expected: Value = serde_json::from_str(ours).unwrap();
277        assert_eq!(
278            merged, expected,
279            "merge(base, ours, ours) should equal ours"
280        );
281    }
282
283    #[test]
284    fn test_correctness_base_equals_ours() {
285        let driver = JsonDriver::new();
286        let base = r#"{"a": 1, "b": 2}"#;
287        let theirs = r#"{"a": 10, "b": 2, "c": 3}"#;
288
289        let result = driver.merge(base, base, theirs).unwrap();
290        assert!(result.is_some());
291        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
292        let expected: Value = serde_json::from_str(theirs).unwrap();
293        assert_eq!(
294            merged, expected,
295            "merge(base, base, theirs) should equal theirs"
296        );
297    }
298
299    #[test]
300    fn test_correctness_base_equals_theirs() {
301        let driver = JsonDriver::new();
302        let base = r#"{"a": 1, "b": 2}"#;
303        let ours = r#"{"a": 10, "b": 2, "c": 3}"#;
304
305        let result = driver.merge(base, ours, base).unwrap();
306        assert!(result.is_some());
307        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
308        let expected: Value = serde_json::from_str(ours).unwrap();
309        assert_eq!(
310            merged, expected,
311            "merge(base, ours, base) should equal ours"
312        );
313    }
314
315    #[test]
316    fn test_correctness_all_equal() {
317        let driver = JsonDriver::new();
318        let content = r#"{"x": 42, "y": "hello"}"#;
319
320        let result = driver.merge(content, content, content).unwrap();
321        assert!(result.is_some());
322        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
323        let expected: Value = serde_json::from_str(content).unwrap();
324        assert_eq!(merged, expected);
325    }
326
327    #[test]
328    fn test_correctness_both_add_different_keys() {
329        let driver = JsonDriver::new();
330        let base = r#"{"shared": true}"#;
331        let ours = r#"{"shared": true, "from_ours": 100}"#;
332        let theirs = r#"{"shared": true, "from_theirs": 200}"#;
333
334        let result = driver.merge(base, ours, theirs).unwrap();
335        assert!(result.is_some());
336        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
337        assert_eq!(merged["shared"], true);
338        assert_eq!(merged["from_ours"], 100);
339        assert_eq!(merged["from_theirs"], 200);
340        assert_eq!(merged.as_object().unwrap().len(), 3);
341    }
342
343    #[test]
344    fn test_correctness_both_modify_different_keys() {
345        let driver = JsonDriver::new();
346        let base = r#"{"a": 1, "b": 2, "c": 3}"#;
347        let ours = r#"{"a": 10, "b": 2, "c": 3}"#;
348        let theirs = r#"{"a": 1, "b": 2, "c": 30}"#;
349
350        let result = driver.merge(base, ours, theirs).unwrap();
351        assert!(result.is_some());
352        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
353        assert_eq!(merged["a"], 10, "ours change to 'a' should be kept");
354        assert_eq!(merged["c"], 30, "theirs change to 'c' should be kept");
355        assert_eq!(merged["b"], 2, "unchanged key should remain");
356    }
357
358    #[test]
359    fn test_correctness_both_modify_same_key_same_value() {
360        let driver = JsonDriver::new();
361        let base = r#"{"key": "original"}"#;
362        let ours = r#"{"key": "changed"}"#;
363        let theirs = r#"{"key": "changed"}"#;
364
365        let result = driver.merge(base, ours, theirs).unwrap();
366        assert!(result.is_some(), "identical changes should not conflict");
367        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
368        assert_eq!(merged["key"], "changed");
369    }
370
371    #[test]
372    fn test_correctness_both_modify_same_key_different_value() {
373        let driver = JsonDriver::new();
374        let base = r#"{"key": "original"}"#;
375        let ours = r#"{"key": "ours"}"#;
376        let theirs = r#"{"key": "theirs"}"#;
377
378        let result = driver.merge(base, ours, theirs).unwrap();
379        assert!(result.is_none(), "conflicting changes should return None");
380    }
381
382    #[test]
383    fn test_correctness_deeply_nested_merge() {
384        let driver = JsonDriver::new();
385        let base = r#"{"level1": {"level2": {"level3": {"a": 1, "b": 2, "c": 3}}}}"#;
386        let ours = r#"{"level1": {"level2": {"level3": {"a": 10, "b": 2, "c": 3}}}}"#;
387        let theirs = r#"{"level1": {"level2": {"level3": {"a": 1, "b": 2, "c": 30}}}}"#;
388
389        let result = driver.merge(base, ours, theirs).unwrap();
390        assert!(result.is_some());
391        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
392        assert_eq!(merged["level1"]["level2"]["level3"]["a"], 10);
393        assert_eq!(merged["level1"]["level2"]["level3"]["c"], 30);
394        assert_eq!(merged["level1"]["level2"]["level3"]["b"], 2);
395    }
396
397    #[test]
398    fn test_correctness_deeply_nested_merge_different_levels() {
399        let driver = JsonDriver::new();
400        let base = r#"{"outer": {"inner": "base", "other": "keep"}}"#;
401        let ours = r#"{"outer": {"inner": "ours", "other": "keep", "extra": 1}}"#;
402        let theirs = r#"{"outer": {"inner": "base", "other": "changed"}}"#;
403
404        let result = driver.merge(base, ours, theirs).unwrap();
405        assert!(result.is_some());
406        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
407        assert_eq!(merged["outer"]["inner"], "ours");
408        assert_eq!(merged["outer"]["other"], "changed");
409        assert_eq!(merged["outer"]["extra"], 1);
410    }
411
412    #[test]
413    fn test_correctness_unicode_keys_and_values() {
414        let driver = JsonDriver::new();
415        let base = r#"{"名前": "太郎", "age": 30}"#;
416        let ours = r#"{"名前": "太郎", "age": 31}"#;
417        let theirs = r#"{"名前": "次郎", "age": 30}"#;
418
419        let result = driver.merge(base, ours, theirs).unwrap();
420        assert!(result.is_some());
421        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
422        assert_eq!(merged["名前"], "次郎");
423        assert_eq!(merged["age"], 31);
424    }
425
426    #[test]
427    fn test_correctness_unicode_emoji_keys() {
428        let driver = JsonDriver::new();
429        let base = r#"{"🌍": "earth", "🚀": "rocket"}"#;
430        let ours = r#"{"🌍": "earth", "🚀": "falcon"}"#;
431        let theirs = r#"{"🌍": "terra", "🚀": "rocket"}"#;
432
433        let result = driver.merge(base, ours, theirs).unwrap();
434        assert!(result.is_some());
435        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
436        assert_eq!(merged["🌍"], "terra");
437        assert_eq!(merged["🚀"], "falcon");
438    }
439
440    #[test]
441    fn test_correctness_large_file() {
442        let driver = JsonDriver::new();
443        let mut base_obj = serde_json::Map::new();
444        let mut ours_obj = serde_json::Map::new();
445        let mut theirs_obj = serde_json::Map::new();
446
447        for i in 0..500 {
448            let key = format!("key_{i}");
449            base_obj.insert(key.clone(), Value::String(format!("value_{i}")));
450            ours_obj.insert(
451                key.clone(),
452                if i == 100 {
453                    Value::String("modified_by_ours".to_string())
454                } else {
455                    Value::String(format!("value_{i}"))
456                },
457            );
458            theirs_obj.insert(
459                key.clone(),
460                if i == 400 {
461                    Value::String("modified_by_theirs".to_string())
462                } else {
463                    Value::String(format!("value_{i}"))
464                },
465            );
466        }
467
468        let base = serde_json::to_string(&Value::Object(base_obj)).unwrap();
469        let ours = serde_json::to_string(&Value::Object(ours_obj)).unwrap();
470        let theirs = serde_json::to_string(&Value::Object(theirs_obj)).unwrap();
471
472        let result = driver.merge(&base, &ours, &theirs).unwrap();
473        assert!(result.is_some());
474        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
475        assert_eq!(merged["key_100"], "modified_by_ours");
476        assert_eq!(merged["key_400"], "modified_by_theirs");
477        assert_eq!(merged["key_0"], "value_0");
478        assert_eq!(merged["key_499"], "value_499");
479        assert_eq!(merged.as_object().unwrap().len(), 500);
480    }
481
482    #[test]
483    fn test_correctness_null_values() {
484        let driver = JsonDriver::new();
485        let base = r#"{"a": 1, "b": null, "c": "hello"}"#;
486        let ours = r#"{"a": 1, "b": "not_null", "c": "hello"}"#;
487        let theirs = r#"{"a": 10, "b": null, "c": "hello"}"#;
488
489        let result = driver.merge(base, ours, theirs).unwrap();
490        assert!(result.is_some());
491        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
492        assert_eq!(merged["a"], 10, "theirs change should apply");
493        assert_eq!(merged["b"], "not_null", "ours change should apply");
494        assert_eq!(merged["c"], "hello");
495    }
496
497    #[test]
498    fn test_correctness_null_to_value() {
499        let driver = JsonDriver::new();
500        let base = r#"{"key": null}"#;
501        let ours = r#"{"key": null}"#;
502        let theirs = r#"{"key": "now_set"}"#;
503
504        let result = driver.merge(base, ours, theirs).unwrap();
505        assert!(result.is_some());
506        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
507        assert_eq!(merged["key"], "now_set");
508    }
509
510    #[test]
511    fn test_correctness_output_validity() {
512        let driver = JsonDriver::new();
513        let base = r#"{"a": 1, "b": {"c": [1, 2, 3]}}"#;
514        let ours = r#"{"a": 10, "b": {"c": [1, 2, 3]}}"#;
515        let theirs = r#"{"a": 1, "b": {"c": [1, 2, 3], "d": "new"}}"#;
516
517        let result = driver.merge(base, ours, theirs).unwrap();
518        assert!(result.is_some());
519        let merged_str = result.unwrap();
520        let merged: Value = serde_json::from_str(&merged_str)
521            .unwrap_or_else(|e| panic!("merged output should be valid JSON: {e}"));
522        assert_eq!(merged["a"], 10);
523        assert_eq!(merged["b"]["d"], "new");
524    }
525
526    #[test]
527    fn test_correctness_array_merge_positional() {
528        let driver = JsonDriver::new();
529        let base = r#"{"items": [1, 2, 3, 4, 5]}"#;
530        let ours = r#"{"items": [10, 2, 3, 4, 5]}"#;
531        let theirs = r#"{"items": [1, 2, 3, 4, 50]}"#;
532
533        let result = driver.merge(base, ours, theirs).unwrap();
534        assert!(result.is_some());
535        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
536        assert_eq!(merged["items"][0], 10);
537        assert_eq!(merged["items"][1], 2);
538        assert_eq!(merged["items"][4], 50);
539        assert_eq!(merged["items"].as_array().unwrap().len(), 5);
540    }
541
542    #[test]
543    fn test_correctness_array_both_append() {
544        let driver = JsonDriver::new();
545        let base = r#"{"items": [1, 2]}"#;
546        let ours = r#"{"items": [1, 2, 3]}"#;
547        let theirs = r#"{"items": [1, 2, 3, 4]}"#;
548
549        let result = driver.merge(base, ours, theirs).unwrap();
550        assert!(result.is_some());
551        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
552        let arr = merged["items"].as_array().unwrap();
553        assert_eq!(arr.len(), 4);
554        assert_eq!(arr[2], 3);
555        assert_eq!(arr[3], 4);
556    }
557
558    #[test]
559    fn test_correctness_array_both_append_different() {
560        let driver = JsonDriver::new();
561        let base = r#"{"items": [1]}"#;
562        let ours = r#"{"items": [1, 2]}"#;
563        let theirs = r#"{"items": [1, 3]}"#;
564
565        let result = driver.merge(base, ours, theirs).unwrap();
566        assert!(
567            result.is_none(),
568            "both appending different values at same index should conflict"
569        );
570    }
571
572    #[test]
573    fn test_correctness_array_nested_objects() {
574        let driver = JsonDriver::new();
575        let base = r#"{"items": [{"a": 1}, {"a": 2}]}"#;
576        let ours = r#"{"items": [{"a": 10}, {"a": 2}]}"#;
577        let theirs = r#"{"items": [{"a": 1}, {"a": 20}]}"#;
578
579        let result = driver.merge(base, ours, theirs).unwrap();
580        assert!(result.is_some());
581        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
582        assert_eq!(merged["items"][0]["a"], 10);
583        assert_eq!(merged["items"][1]["a"], 20);
584    }
585
586    #[test]
587    fn test_correctness_number_precision() {
588        let driver = JsonDriver::new();
589        let base = r#"{"value": 1}"#;
590        let ours = r#"{"value": 1.0}"#;
591        let theirs = r#"{"value": 1}"#;
592
593        let result = driver.merge(base, ours, theirs).unwrap();
594        assert!(result.is_some());
595        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
596        assert_eq!(merged["value"], 1.0);
597    }
598
599    #[test]
600    fn test_correctness_boolean_merge() {
601        let driver = JsonDriver::new();
602        let base = r#"{"a": true, "b": false}"#;
603        let ours = r#"{"a": false, "b": false}"#;
604        let theirs = r#"{"a": true, "b": true}"#;
605
606        let result = driver.merge(base, ours, theirs).unwrap();
607        assert!(result.is_some());
608        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
609        assert_eq!(merged["a"], false, "ours change to false should apply");
610        assert_eq!(merged["b"], true, "theirs change to true should apply");
611    }
612
613    #[test]
614    fn test_correctness_nested_object_3_levels_deep() {
615        let driver = JsonDriver::new();
616        let base = r#"{"l1": {"l2": {"l3": {"x": 0, "y": 0, "z": 0}}}}"#;
617        let ours = r#"{"l1": {"l2": {"l3": {"x": 1, "y": 0, "z": 0}}}}"#;
618        let theirs = r#"{"l1": {"l2": {"l3": {"x": 0, "y": 0, "z": 1}}}}"#;
619
620        let result = driver.merge(base, ours, theirs).unwrap();
621        assert!(result.is_some());
622        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
623        assert_eq!(merged["l1"]["l2"]["l3"]["x"], 1);
624        assert_eq!(merged["l1"]["l2"]["l3"]["y"], 0);
625        assert_eq!(merged["l1"]["l2"]["l3"]["z"], 1);
626    }
627
628    #[test]
629    fn test_correctness_key_deletion_by_ours() {
630        let driver = JsonDriver::new();
631        let base = r#"{"a": 1, "b": 2, "c": 3}"#;
632        let ours = r#"{"a": 1, "c": 3}"#;
633        let theirs = r#"{"a": 1, "b": 2, "c": 3}"#;
634
635        let result = driver.merge(base, ours, theirs).unwrap();
636        assert!(result.is_some());
637        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
638        assert!(
639            merged.as_object().unwrap().contains_key("b"),
640            "theirs kept 'b' since ours deleted it but theirs didn't"
641        );
642    }
643
644    #[test]
645    fn test_correctness_key_deletion_by_both() {
646        let driver = JsonDriver::new();
647        let base = r#"{"a": 1, "b": 2, "c": 3}"#;
648        let ours = r#"{"a": 1, "c": 3}"#;
649        let theirs = r#"{"a": 1, "c": 3}"#;
650
651        let result = driver.merge(base, ours, theirs).unwrap();
652        assert!(result.is_some());
653        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
654        assert!(
655            !merged.as_object().unwrap().contains_key("b"),
656            "both deleted 'b'"
657        );
658    }
659
660    #[test]
661    fn test_correctness_key_deletion_conflict() {
662        let driver = JsonDriver::new();
663        let base = r#"{"a": 1, "b": 2}"#;
664        let ours = r#"{"a": 1}"#;
665        let theirs = r#"{"a": 1, "b": 99}"#;
666
667        let result = driver.merge(base, ours, theirs).unwrap();
668        assert!(
669            result.is_some(),
670            "ours deletes, theirs modifies → theirs wins"
671        );
672        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
673        assert_eq!(
674            merged["b"], 99,
675            "theirs modification is preserved since ours didn't have the key"
676        );
677    }
678
679    #[test]
680    fn test_correctness_empty_objects() {
681        let driver = JsonDriver::new();
682        let base = r#"{}"#;
683        let ours = r#"{"a": 1}"#;
684        let theirs = r#"{"b": 2}"#;
685
686        let result = driver.merge(base, ours, theirs).unwrap();
687        assert!(result.is_some());
688        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
689        assert_eq!(merged["a"], 1);
690        assert_eq!(merged["b"], 2);
691    }
692
693    #[test]
694    fn test_correctness_mixed_types_no_conflict() {
695        let driver = JsonDriver::new();
696        let base = r#"{"a": 1, "b": "hello", "c": true, "d": [1,2], "e": {"nested": true}}"#;
697        let ours = r#"{"a": 10, "b": "hello", "c": true, "d": [1,2], "e": {"nested": true}}"#;
698        let theirs = r#"{"a": 1, "b": "world", "c": false, "d": [1,2], "e": {"nested": true}}"#;
699
700        let result = driver.merge(base, ours, theirs).unwrap();
701        assert!(result.is_some());
702        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
703        assert_eq!(merged["a"], 10);
704        assert_eq!(merged["b"], "world");
705        assert_eq!(merged["c"], false);
706        assert_eq!(merged["e"]["nested"], true);
707    }
708
709    #[test]
710    fn test_correctness_type_change_conflict() {
711        let driver = JsonDriver::new();
712        let base = r#"{"key": 42}"#;
713        let ours = r#"{"key": "string"}"#;
714        let theirs = r#"{"key": [1,2,3]}"#;
715
716        let result = driver.merge(base, ours, theirs).unwrap();
717        assert!(
718            result.is_none(),
719            "both changing type differently should conflict"
720        );
721    }
722
723    #[test]
724    fn test_correctness_type_change_one_side() {
725        let driver = JsonDriver::new();
726        let base = r#"{"key": 42}"#;
727        let ours = r#"{"key": 42}"#;
728        let theirs = r#"{"key": "string"}"#;
729
730        let result = driver.merge(base, ours, theirs).unwrap();
731        assert!(result.is_some());
732        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
733        assert_eq!(merged["key"], "string");
734    }
735
736    #[test]
737    fn test_correctness_merge_associativity() {
738        let driver = JsonDriver::new();
739        let base = r#"{"a": 1, "b": 2, "c": 3, "d": 4}"#;
740        let a = r#"{"a": 10, "b": 2, "c": 3, "d": 4}"#;
741        let b = r#"{"a": 1, "b": 20, "c": 3, "d": 4}"#;
742        let c = r#"{"a": 1, "b": 2, "c": 30, "d": 4}"#;
743
744        let ab = driver.merge(base, a, b).unwrap().expect("merge(base, A, B) should succeed");
745        let merge_left = driver
746            .merge(base, &ab, c)
747            .unwrap()
748            .expect("merge(base, merge(A,B), C) should succeed");
749
750        let bc = driver.merge(base, b, c).unwrap().expect("merge(base, B, C) should succeed");
751        let merge_right = driver
752            .merge(base, a, &bc)
753            .unwrap()
754            .expect("merge(base, A, merge(B,C)) should succeed");
755
756        let v_left: Value = serde_json::from_str(&merge_left).unwrap();
757        let v_right: Value = serde_json::from_str(&merge_right).unwrap();
758
759        assert_eq!(
760            v_left, v_right,
761            "merge(base, merge(A,B), C) must equal merge(base, A, merge(B,C))"
762        );
763        assert_eq!(v_left["a"], 10);
764        assert_eq!(v_left["b"], 20);
765        assert_eq!(v_left["c"], 30);
766        assert_eq!(v_left["d"], 4);
767    }
768}