Skip to main content

suture_driver_json/
lib.rs

1use serde_json::Value;
2use suture_driver::{DriverError, SemanticChange, SutureDriver};
3
4pub struct JsonDriver;
5
6impl JsonDriver {
7    pub fn new() -> Self {
8        Self
9    }
10
11    fn json_pointer_escape(s: &str) -> String {
12        s.replace('~', "~0").replace('/', "~1")
13    }
14
15    fn diff_values(old: &Value, new: &Value, path: &str) -> Vec<SemanticChange> {
16        let mut changes = Vec::new();
17
18        match (old, new) {
19            (Value::Object(old_map), Value::Object(new_map)) => {
20                let old_keys: std::collections::HashSet<&str> =
21                    old_map.keys().map(|s| s.as_str()).collect();
22                let new_keys: std::collections::HashSet<&str> =
23                    new_map.keys().map(|s| s.as_str()).collect();
24
25                for key in &old_keys {
26                    if !new_keys.contains(key) {
27                        let escaped = Self::json_pointer_escape(key);
28                        let child_path = if path == "/" {
29                            format!("/{escaped}")
30                        } else {
31                            format!("{path}/{escaped}")
32                        };
33                        changes.push(SemanticChange::Removed {
34                            path: child_path,
35                            old_value: old_map[*key].to_string(),
36                        });
37                    }
38                }
39
40                for key in &new_keys {
41                    if !old_keys.contains(key) {
42                        let escaped = Self::json_pointer_escape(key);
43                        let child_path = if path == "/" {
44                            format!("/{escaped}")
45                        } else {
46                            format!("{path}/{escaped}")
47                        };
48                        changes.push(SemanticChange::Added {
49                            path: child_path,
50                            value: new_map[*key].to_string(),
51                        });
52                    }
53                }
54
55                for key in &old_keys {
56                    if let Some(new_val) = new_keys.contains(key).then(|| &new_map[*key]) {
57                        let escaped = Self::json_pointer_escape(key);
58                        let child_path = if path == "/" {
59                            format!("/{escaped}")
60                        } else {
61                            format!("{path}/{escaped}")
62                        };
63                        changes.extend(Self::diff_values(&old_map[*key], new_val, &child_path));
64                    }
65                }
66            }
67            (Value::Array(old_arr), Value::Array(new_arr)) => {
68                let max_len = old_arr.len().max(new_arr.len());
69
70                for i in 0..max_len {
71                    let child_path = format!("{path}/{i}");
72                    match (old_arr.get(i), new_arr.get(i)) {
73                        (None, Some(new_val)) => {
74                            changes.push(SemanticChange::Added {
75                                path: child_path,
76                                value: new_val.to_string(),
77                            });
78                        }
79                        (Some(old_val), None) => {
80                            changes.push(SemanticChange::Removed {
81                                path: child_path,
82                                old_value: old_val.to_string(),
83                            });
84                        }
85                        (Some(old_val), Some(new_val)) => {
86                            changes.extend(Self::diff_values(old_val, new_val, &child_path));
87                        }
88                        (None, None) => {}
89                    }
90                }
91            }
92            (old_val, new_val) if old_val != new_val => {
93                changes.push(SemanticChange::Modified {
94                    path: path.to_string(),
95                    old_value: old_val.to_string(),
96                    new_value: new_val.to_string(),
97                });
98            }
99            _ => {}
100        }
101
102        changes
103    }
104
105    fn merge_values(
106        base: &Value,
107        ours: &Value,
108        theirs: &Value,
109    ) -> Result<Option<Value>, DriverError> {
110        match (base, ours, theirs) {
111            (Value::Object(base_map), Value::Object(ours_map), Value::Object(theirs_map)) => {
112                let base_keys: std::collections::HashSet<&str> =
113                    base_map.keys().map(|s| s.as_str()).collect();
114                let ours_keys: std::collections::HashSet<&str> =
115                    ours_map.keys().map(|s| s.as_str()).collect();
116                let theirs_keys: std::collections::HashSet<&str> =
117                    theirs_map.keys().map(|s| s.as_str()).collect();
118
119                let all_keys: std::collections::HashSet<&str> = base_keys
120                    .iter()
121                    .chain(ours_keys.iter())
122                    .chain(theirs_keys.iter())
123                    .copied()
124                    .collect();
125
126                let mut merged = serde_json::Map::new();
127
128                for key in &all_keys {
129                    let in_base = base_keys.contains(key);
130                    let in_ours = ours_keys.contains(key);
131                    let in_theirs = theirs_keys.contains(key);
132
133                    match (in_base, in_ours, in_theirs) {
134                        (true, true, false) => {
135                            merged.insert((*key).to_string(), ours_map[*key].clone());
136                        }
137                        (true, false, true) => {
138                            merged.insert((*key).to_string(), theirs_map[*key].clone());
139                        }
140                        (true, true, true) => {
141                            let base_val = &base_map[*key];
142                            let ours_val = &ours_map[*key];
143                            let theirs_val = &theirs_map[*key];
144
145                            if ours_val == theirs_val {
146                                merged.insert((*key).to_string(), ours_val.clone());
147                            } else if ours_val == base_val {
148                                merged.insert((*key).to_string(), theirs_val.clone());
149                            } else if theirs_val == base_val {
150                                merged.insert((*key).to_string(), ours_val.clone());
151                            } else if let Some(m) =
152                                Self::merge_values(base_val, ours_val, theirs_val)?
153                            {
154                                merged.insert((*key).to_string(), m);
155                            } else {
156                                return Ok(None);
157                            }
158                        }
159                        (false, true, true) => {
160                            if ours_map[*key] == theirs_map[*key] {
161                                merged.insert((*key).to_string(), ours_map[*key].clone());
162                            } else {
163                                return Ok(None);
164                            }
165                        }
166                        (false, true, false) => {
167                            merged.insert((*key).to_string(), ours_map[*key].clone());
168                        }
169                        (false, false, true) => {
170                            merged.insert((*key).to_string(), theirs_map[*key].clone());
171                        }
172                        (true, false, false) => {}
173                        (false, false, false) => {}
174                    }
175                }
176
177                Ok(Some(Value::Object(merged)))
178            }
179            (Value::Array(base_arr), Value::Array(ours_arr), Value::Array(theirs_arr)) => {
180                let max_len = base_arr.len().max(ours_arr.len()).max(theirs_arr.len());
181                let mut merged = Vec::new();
182
183                for i in 0..max_len {
184                    let base_val = base_arr.get(i);
185                    let ours_val = ours_arr.get(i);
186                    let theirs_val = theirs_arr.get(i);
187
188                    match (base_val, ours_val, theirs_val) {
189                        (None, Some(o), None) => merged.push(o.clone()),
190                        (None, None, Some(t)) => merged.push(t.clone()),
191                        (None, Some(o), Some(t)) => {
192                            if o == t {
193                                merged.push(o.clone());
194                            } else {
195                                return Ok(None);
196                            }
197                        }
198                        (None, None, _) => {}
199                        (Some(_), Some(o), None) => merged.push(o.clone()),
200                        (Some(_), None, Some(t)) => merged.push(t.clone()),
201                        (Some(_), None, None) => {}
202                        (Some(b), Some(o), Some(t)) => {
203                            if o == t {
204                                merged.push(o.clone());
205                            } else if o == b {
206                                merged.push(t.clone());
207                            } else if t == b {
208                                merged.push(o.clone());
209                            } else if let Some(m) = Self::merge_values(b, o, t)? {
210                                merged.push(m);
211                            } else {
212                                return Ok(None);
213                            }
214                        }
215                    }
216                }
217
218                Ok(Some(Value::Array(merged)))
219            }
220            (base_val, ours_val, theirs_val) => {
221                if ours_val == theirs_val {
222                    Ok(Some(ours_val.clone()))
223                } else if ours_val == base_val {
224                    Ok(Some(theirs_val.clone()))
225                } else if theirs_val == base_val {
226                    Ok(Some(ours_val.clone()))
227                } else {
228                    Ok(None)
229                }
230            }
231        }
232    }
233
234    fn format_change(change: &SemanticChange) -> String {
235        match change {
236            SemanticChange::Added { path, value } => {
237                format!("  ADDED     {path}: {value}")
238            }
239            SemanticChange::Removed { path, old_value } => {
240                format!("  REMOVED   {path}: {old_value}")
241            }
242            SemanticChange::Modified {
243                path,
244                old_value,
245                new_value,
246            } => {
247                format!("  MODIFIED  {path}: {old_value} → {new_value}")
248            }
249            SemanticChange::Moved {
250                old_path,
251                new_path,
252                value,
253            } => {
254                format!("  MOVED     {old_path} → {new_path}: {value}")
255            }
256        }
257    }
258}
259
260impl Default for JsonDriver {
261    fn default() -> Self {
262        Self::new()
263    }
264}
265
266impl SutureDriver for JsonDriver {
267    fn name(&self) -> &str {
268        "JSON"
269    }
270
271    fn supported_extensions(&self) -> &[&str] {
272        &[".json"]
273    }
274
275    fn diff(
276        &self,
277        base_content: Option<&str>,
278        new_content: &str,
279    ) -> Result<Vec<SemanticChange>, DriverError> {
280        let new_val: Value = serde_json::from_str(new_content)
281            .map_err(|e| DriverError::ParseError(e.to_string()))?;
282
283        match base_content {
284            None => {
285                let mut changes = Vec::new();
286                collect_all_paths(&new_val, "/".to_string(), &mut changes);
287                Ok(changes)
288            }
289            Some(base) => {
290                let old_val: Value = serde_json::from_str(base)
291                    .map_err(|e| DriverError::ParseError(e.to_string()))?;
292                Ok(Self::diff_values(&old_val, &new_val, "/"))
293            }
294        }
295    }
296
297    fn format_diff(
298        &self,
299        base_content: Option<&str>,
300        new_content: &str,
301    ) -> Result<String, DriverError> {
302        let changes = self.diff(base_content, new_content)?;
303
304        if changes.is_empty() {
305            return Ok("no changes".to_string());
306        }
307
308        let lines: Vec<String> = changes.iter().map(Self::format_change).collect();
309        Ok(lines.join("\n"))
310    }
311
312    fn merge(&self, base: &str, ours: &str, theirs: &str) -> Result<Option<String>, DriverError> {
313        let base_val: Value =
314            serde_json::from_str(base).map_err(|e| DriverError::ParseError(e.to_string()))?;
315        let ours_val: Value =
316            serde_json::from_str(ours).map_err(|e| DriverError::ParseError(e.to_string()))?;
317        let theirs_val: Value =
318            serde_json::from_str(theirs).map_err(|e| DriverError::ParseError(e.to_string()))?;
319
320        match Self::merge_values(&base_val, &ours_val, &theirs_val)? {
321            Some(merged) => Ok(Some(
322                serde_json::to_string_pretty(&merged)
323                    .map_err(|e| DriverError::SerializationError(e.to_string()))?,
324            )),
325            None => Ok(None),
326        }
327    }
328}
329
330fn collect_all_paths(val: &Value, path: String, out: &mut Vec<SemanticChange>) {
331    match val {
332        Value::Object(map) => {
333            for (key, child) in map {
334                let escaped = JsonDriver::json_pointer_escape(key);
335                let child_path = if path == "/" {
336                    format!("/{escaped}")
337                } else {
338                    format!("{path}/{escaped}")
339                };
340                collect_all_paths(child, child_path, out);
341            }
342        }
343        Value::Array(arr) => {
344            for (i, child) in arr.iter().enumerate() {
345                let child_path = format!("{path}/{i}");
346                collect_all_paths(child, child_path, out);
347            }
348        }
349        other => {
350            out.push(SemanticChange::Added {
351                path,
352                value: other.to_string(),
353            });
354        }
355    }
356}
357
358#[cfg(test)]
359mod tests {
360    use super::*;
361
362    #[test]
363    fn test_json_driver_name() {
364        let driver = JsonDriver::new();
365        assert_eq!(driver.name(), "JSON");
366    }
367
368    #[test]
369    fn test_json_driver_extensions() {
370        let driver = JsonDriver::new();
371        assert_eq!(driver.supported_extensions(), &[".json"]);
372    }
373
374    #[test]
375    fn test_diff_added_key() {
376        let driver = JsonDriver::new();
377        let old = r#"{"name": "Alice"}"#;
378        let new = r#"{"name": "Alice", "email": "alice@example.com"}"#;
379
380        let changes = driver.diff(Some(old), new).unwrap();
381        assert!(changes.contains(&SemanticChange::Added {
382            path: "/email".to_string(),
383            value: "\"alice@example.com\"".to_string(),
384        }));
385    }
386
387    #[test]
388    fn test_diff_removed_key() {
389        let driver = JsonDriver::new();
390        let old = r#"{"name": "Alice", "phone": "+1234567890"}"#;
391        let new = r#"{"name": "Alice"}"#;
392
393        let changes = driver.diff(Some(old), new).unwrap();
394        assert!(changes.contains(&SemanticChange::Removed {
395            path: "/phone".to_string(),
396            old_value: "\"+1234567890\"".to_string(),
397        }));
398    }
399
400    #[test]
401    fn test_diff_modified_key() {
402        let driver = JsonDriver::new();
403        let old = r#"{"name": "Alice"}"#;
404        let new = r#"{"name": "Bob"}"#;
405
406        let changes = driver.diff(Some(old), new).unwrap();
407        assert_eq!(changes.len(), 1);
408        assert_eq!(
409            changes[0],
410            SemanticChange::Modified {
411                path: "/name".to_string(),
412                old_value: "\"Alice\"".to_string(),
413                new_value: "\"Bob\"".to_string(),
414            }
415        );
416    }
417
418    #[test]
419    fn test_diff_nested() {
420        let driver = JsonDriver::new();
421        let old = r#"{"address": {"city": "NYC", "zip": "10001"}}"#;
422        let new = r#"{"address": {"city": "San Francisco", "zip": "10001"}}"#;
423
424        let changes = driver.diff(Some(old), new).unwrap();
425        assert!(changes.contains(&SemanticChange::Modified {
426            path: "/address/city".to_string(),
427            old_value: "\"NYC\"".to_string(),
428            new_value: "\"San Francisco\"".to_string(),
429        }));
430    }
431
432    #[test]
433    fn test_diff_new_file() {
434        let driver = JsonDriver::new();
435        let new = r#"{"name": "Alice", "age": 30}"#;
436
437        let changes = driver.diff(None, new).unwrap();
438        assert!(!changes.is_empty());
439        for change in &changes {
440            assert!(matches!(change, SemanticChange::Added { .. }));
441        }
442    }
443
444    #[test]
445    fn test_format_diff() {
446        let driver = JsonDriver::new();
447        let old = r#"{"name": "Alice"}"#;
448        let new = r#"{"name": "Bob", "email": "bob@example.com"}"#;
449
450        let output = driver.format_diff(Some(old), new).unwrap();
451        assert!(output.contains("MODIFIED"));
452        assert!(output.contains("ADDED"));
453        assert!(output.contains("/name"));
454        assert!(output.contains("/email"));
455    }
456
457    #[test]
458    fn test_format_diff_empty() {
459        let driver = JsonDriver::new();
460        let content = r#"{"name": "Alice"}"#;
461
462        let output = driver.format_diff(Some(content), content).unwrap();
463        assert_eq!(output, "no changes");
464    }
465
466    #[test]
467    fn test_array_changes() {
468        let driver = JsonDriver::new();
469        let old = r#"{"items": ["a", "b"]}"#;
470        let new = r#"{"items": ["a", "c", "d"]}"#;
471
472        let changes = driver.diff(Some(old), new).unwrap();
473        assert!(changes.contains(&SemanticChange::Modified {
474            path: "/items/1".to_string(),
475            old_value: "\"b\"".to_string(),
476            new_value: "\"c\"".to_string(),
477        }));
478        assert!(changes.contains(&SemanticChange::Added {
479            path: "/items/2".to_string(),
480            value: "\"d\"".to_string(),
481        }));
482    }
483
484    #[test]
485    fn test_merge_no_conflict() {
486        let driver = JsonDriver::new();
487        let base = r#"{"a": 1, "b": 2, "c": 3}"#;
488        let ours = r#"{"a": 10, "b": 2, "c": 3}"#;
489        let theirs = r#"{"a": 1, "b": 2, "c": 30}"#;
490
491        let result = driver.merge(base, ours, theirs).unwrap();
492        assert!(result.is_some());
493        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
494        assert_eq!(merged["a"], 10);
495        assert_eq!(merged["b"], 2);
496        assert_eq!(merged["c"], 30);
497    }
498
499    #[test]
500    fn test_merge_conflict() {
501        let driver = JsonDriver::new();
502        let base = r#"{"key": "original"}"#;
503        let ours = r#"{"key": "ours"}"#;
504        let theirs = r#"{"key": "theirs"}"#;
505
506        let result = driver.merge(base, ours, theirs).unwrap();
507        assert!(result.is_none());
508    }
509
510    #[test]
511    fn test_merge_both_add_different_keys() {
512        let driver = JsonDriver::new();
513        let base = r#"{"a": 1}"#;
514        let ours = r#"{"a": 1, "x": 100}"#;
515        let theirs = r#"{"a": 1, "y": 200}"#;
516
517        let result = driver.merge(base, ours, theirs).unwrap();
518        assert!(result.is_some());
519        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
520        assert_eq!(merged["a"], 1);
521        assert_eq!(merged["x"], 100);
522        assert_eq!(merged["y"], 200);
523    }
524
525    #[test]
526    fn test_merge_both_add_same_key() {
527        let driver = JsonDriver::new();
528        let base = r#"{"a": 1}"#;
529        let ours = r#"{"a": 1, "x": 100}"#;
530        let theirs = r#"{"a": 1, "x": 999}"#;
531
532        let result = driver.merge(base, ours, theirs).unwrap();
533        assert!(result.is_none());
534    }
535
536    #[test]
537    fn test_merge_nested() {
538        let driver = JsonDriver::new();
539        let base = r#"{"outer": {"inner": "base", "other": "keep"}}"#;
540        let ours = r#"{"outer": {"inner": "ours", "other": "keep"}}"#;
541        let theirs = r#"{"outer": {"inner": "base", "other": "changed"}}"#;
542
543        let result = driver.merge(base, ours, theirs).unwrap();
544        assert!(result.is_some());
545        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
546        assert_eq!(merged["outer"]["inner"], "ours");
547        assert_eq!(merged["outer"]["other"], "changed");
548    }
549
550    #[test]
551    fn test_merge_identical() {
552        let driver = JsonDriver::new();
553        let content = r#"{"a": 1, "b": 2}"#;
554
555        let result = driver.merge(content, content, content).unwrap();
556        assert!(result.is_some());
557        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
558        assert_eq!(merged["a"], 1);
559        assert_eq!(merged["b"], 2);
560    }
561
562    #[test]
563    fn test_correctness_merge_determinism() {
564        let driver = JsonDriver::new();
565        let base = r#"{"a": 1, "b": 2, "c": 3}"#;
566        let ours = r#"{"a": 10, "b": 2, "d": 4}"#;
567        let theirs = r#"{"a": 1, "b": 20, "e": 5}"#;
568
569        let r1 = driver.merge(base, ours, theirs).unwrap();
570        let r2 = driver.merge(base, theirs, ours).unwrap();
571        assert_eq!(r1.is_some(), r2.is_some());
572        if let (Some(m1), Some(m2)) = (r1, r2) {
573            let v1: Value = serde_json::from_str(&m1).unwrap();
574            let v2: Value = serde_json::from_str(&m2).unwrap();
575            assert_eq!(
576                v1, v2,
577                "merge(base, ours, theirs) must equal merge(base, theirs, ours)"
578            );
579        }
580    }
581
582    #[test]
583    fn test_correctness_merge_idempotency() {
584        let driver = JsonDriver::new();
585        let base = r#"{"a": 1, "b": 2}"#;
586        let ours = r#"{"a": 10, "b": 2, "c": 3}"#;
587
588        let result = driver.merge(base, ours, ours).unwrap();
589        assert!(result.is_some());
590        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
591        let expected: Value = serde_json::from_str(ours).unwrap();
592        assert_eq!(
593            merged, expected,
594            "merge(base, ours, ours) should equal ours"
595        );
596    }
597
598    #[test]
599    fn test_correctness_base_equals_ours() {
600        let driver = JsonDriver::new();
601        let base = r#"{"a": 1, "b": 2}"#;
602        let theirs = r#"{"a": 10, "b": 2, "c": 3}"#;
603
604        let result = driver.merge(base, base, theirs).unwrap();
605        assert!(result.is_some());
606        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
607        let expected: Value = serde_json::from_str(theirs).unwrap();
608        assert_eq!(
609            merged, expected,
610            "merge(base, base, theirs) should equal theirs"
611        );
612    }
613
614    #[test]
615    fn test_correctness_base_equals_theirs() {
616        let driver = JsonDriver::new();
617        let base = r#"{"a": 1, "b": 2}"#;
618        let ours = r#"{"a": 10, "b": 2, "c": 3}"#;
619
620        let result = driver.merge(base, ours, base).unwrap();
621        assert!(result.is_some());
622        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
623        let expected: Value = serde_json::from_str(ours).unwrap();
624        assert_eq!(
625            merged, expected,
626            "merge(base, ours, base) should equal ours"
627        );
628    }
629
630    #[test]
631    fn test_correctness_all_equal() {
632        let driver = JsonDriver::new();
633        let content = r#"{"x": 42, "y": "hello"}"#;
634
635        let result = driver.merge(content, content, content).unwrap();
636        assert!(result.is_some());
637        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
638        let expected: Value = serde_json::from_str(content).unwrap();
639        assert_eq!(merged, expected);
640    }
641
642    #[test]
643    fn test_correctness_both_add_different_keys() {
644        let driver = JsonDriver::new();
645        let base = r#"{"shared": true}"#;
646        let ours = r#"{"shared": true, "from_ours": 100}"#;
647        let theirs = r#"{"shared": true, "from_theirs": 200}"#;
648
649        let result = driver.merge(base, ours, theirs).unwrap();
650        assert!(result.is_some());
651        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
652        assert_eq!(merged["shared"], true);
653        assert_eq!(merged["from_ours"], 100);
654        assert_eq!(merged["from_theirs"], 200);
655        assert_eq!(merged.as_object().unwrap().len(), 3);
656    }
657
658    #[test]
659    fn test_correctness_both_modify_different_keys() {
660        let driver = JsonDriver::new();
661        let base = r#"{"a": 1, "b": 2, "c": 3}"#;
662        let ours = r#"{"a": 10, "b": 2, "c": 3}"#;
663        let theirs = r#"{"a": 1, "b": 2, "c": 30}"#;
664
665        let result = driver.merge(base, ours, theirs).unwrap();
666        assert!(result.is_some());
667        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
668        assert_eq!(merged["a"], 10, "ours change to 'a' should be kept");
669        assert_eq!(merged["c"], 30, "theirs change to 'c' should be kept");
670        assert_eq!(merged["b"], 2, "unchanged key should remain");
671    }
672
673    #[test]
674    fn test_correctness_both_modify_same_key_same_value() {
675        let driver = JsonDriver::new();
676        let base = r#"{"key": "original"}"#;
677        let ours = r#"{"key": "changed"}"#;
678        let theirs = r#"{"key": "changed"}"#;
679
680        let result = driver.merge(base, ours, theirs).unwrap();
681        assert!(result.is_some(), "identical changes should not conflict");
682        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
683        assert_eq!(merged["key"], "changed");
684    }
685
686    #[test]
687    fn test_correctness_both_modify_same_key_different_value() {
688        let driver = JsonDriver::new();
689        let base = r#"{"key": "original"}"#;
690        let ours = r#"{"key": "ours"}"#;
691        let theirs = r#"{"key": "theirs"}"#;
692
693        let result = driver.merge(base, ours, theirs).unwrap();
694        assert!(result.is_none(), "conflicting changes should return None");
695    }
696
697    #[test]
698    fn test_correctness_deeply_nested_merge() {
699        let driver = JsonDriver::new();
700        let base = r#"{"level1": {"level2": {"level3": {"a": 1, "b": 2, "c": 3}}}}"#;
701        let ours = r#"{"level1": {"level2": {"level3": {"a": 10, "b": 2, "c": 3}}}}"#;
702        let theirs = r#"{"level1": {"level2": {"level3": {"a": 1, "b": 2, "c": 30}}}}"#;
703
704        let result = driver.merge(base, ours, theirs).unwrap();
705        assert!(result.is_some());
706        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
707        assert_eq!(merged["level1"]["level2"]["level3"]["a"], 10);
708        assert_eq!(merged["level1"]["level2"]["level3"]["c"], 30);
709        assert_eq!(merged["level1"]["level2"]["level3"]["b"], 2);
710    }
711
712    #[test]
713    fn test_correctness_deeply_nested_merge_different_levels() {
714        let driver = JsonDriver::new();
715        let base = r#"{"outer": {"inner": "base", "other": "keep"}}"#;
716        let ours = r#"{"outer": {"inner": "ours", "other": "keep", "extra": 1}}"#;
717        let theirs = r#"{"outer": {"inner": "base", "other": "changed"}}"#;
718
719        let result = driver.merge(base, ours, theirs).unwrap();
720        assert!(result.is_some());
721        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
722        assert_eq!(merged["outer"]["inner"], "ours");
723        assert_eq!(merged["outer"]["other"], "changed");
724        assert_eq!(merged["outer"]["extra"], 1);
725    }
726
727    #[test]
728    fn test_correctness_unicode_keys_and_values() {
729        let driver = JsonDriver::new();
730        let base = r#"{"名前": "太郎", "age": 30}"#;
731        let ours = r#"{"名前": "太郎", "age": 31}"#;
732        let theirs = r#"{"名前": "次郎", "age": 30}"#;
733
734        let result = driver.merge(base, ours, theirs).unwrap();
735        assert!(result.is_some());
736        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
737        assert_eq!(merged["名前"], "次郎");
738        assert_eq!(merged["age"], 31);
739    }
740
741    #[test]
742    fn test_correctness_unicode_emoji_keys() {
743        let driver = JsonDriver::new();
744        let base = r#"{"🌍": "earth", "🚀": "rocket"}"#;
745        let ours = r#"{"🌍": "earth", "🚀": "falcon"}"#;
746        let theirs = r#"{"🌍": "terra", "🚀": "rocket"}"#;
747
748        let result = driver.merge(base, ours, theirs).unwrap();
749        assert!(result.is_some());
750        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
751        assert_eq!(merged["🌍"], "terra");
752        assert_eq!(merged["🚀"], "falcon");
753    }
754
755    #[test]
756    fn test_correctness_large_file() {
757        let driver = JsonDriver::new();
758        let mut base_obj = serde_json::Map::new();
759        let mut ours_obj = serde_json::Map::new();
760        let mut theirs_obj = serde_json::Map::new();
761
762        for i in 0..500 {
763            let key = format!("key_{i}");
764            base_obj.insert(key.clone(), Value::String(format!("value_{i}")));
765            ours_obj.insert(
766                key.clone(),
767                if i == 100 {
768                    Value::String("modified_by_ours".to_string())
769                } else {
770                    Value::String(format!("value_{i}"))
771                },
772            );
773            theirs_obj.insert(
774                key.clone(),
775                if i == 400 {
776                    Value::String("modified_by_theirs".to_string())
777                } else {
778                    Value::String(format!("value_{i}"))
779                },
780            );
781        }
782
783        let base = serde_json::to_string(&Value::Object(base_obj)).unwrap();
784        let ours = serde_json::to_string(&Value::Object(ours_obj)).unwrap();
785        let theirs = serde_json::to_string(&Value::Object(theirs_obj)).unwrap();
786
787        let result = driver.merge(&base, &ours, &theirs).unwrap();
788        assert!(result.is_some());
789        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
790        assert_eq!(merged["key_100"], "modified_by_ours");
791        assert_eq!(merged["key_400"], "modified_by_theirs");
792        assert_eq!(merged["key_0"], "value_0");
793        assert_eq!(merged["key_499"], "value_499");
794        assert_eq!(merged.as_object().unwrap().len(), 500);
795    }
796
797    #[test]
798    fn test_correctness_null_values() {
799        let driver = JsonDriver::new();
800        let base = r#"{"a": 1, "b": null, "c": "hello"}"#;
801        let ours = r#"{"a": 1, "b": "not_null", "c": "hello"}"#;
802        let theirs = r#"{"a": 10, "b": null, "c": "hello"}"#;
803
804        let result = driver.merge(base, ours, theirs).unwrap();
805        assert!(result.is_some());
806        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
807        assert_eq!(merged["a"], 10, "theirs change should apply");
808        assert_eq!(merged["b"], "not_null", "ours change should apply");
809        assert_eq!(merged["c"], "hello");
810    }
811
812    #[test]
813    fn test_correctness_null_to_value() {
814        let driver = JsonDriver::new();
815        let base = r#"{"key": null}"#;
816        let ours = r#"{"key": null}"#;
817        let theirs = r#"{"key": "now_set"}"#;
818
819        let result = driver.merge(base, ours, theirs).unwrap();
820        assert!(result.is_some());
821        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
822        assert_eq!(merged["key"], "now_set");
823    }
824
825    #[test]
826    fn test_correctness_output_validity() {
827        let driver = JsonDriver::new();
828        let base = r#"{"a": 1, "b": {"c": [1, 2, 3]}}"#;
829        let ours = r#"{"a": 10, "b": {"c": [1, 2, 3]}}"#;
830        let theirs = r#"{"a": 1, "b": {"c": [1, 2, 3], "d": "new"}}"#;
831
832        let result = driver.merge(base, ours, theirs).unwrap();
833        assert!(result.is_some());
834        let merged_str = result.unwrap();
835        let merged: Value = serde_json::from_str(&merged_str)
836            .unwrap_or_else(|e| panic!("merged output should be valid JSON: {e}"));
837        assert_eq!(merged["a"], 10);
838        assert_eq!(merged["b"]["d"], "new");
839    }
840
841    #[test]
842    fn test_correctness_array_merge_positional() {
843        let driver = JsonDriver::new();
844        let base = r#"{"items": [1, 2, 3, 4, 5]}"#;
845        let ours = r#"{"items": [10, 2, 3, 4, 5]}"#;
846        let theirs = r#"{"items": [1, 2, 3, 4, 50]}"#;
847
848        let result = driver.merge(base, ours, theirs).unwrap();
849        assert!(result.is_some());
850        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
851        assert_eq!(merged["items"][0], 10);
852        assert_eq!(merged["items"][1], 2);
853        assert_eq!(merged["items"][4], 50);
854        assert_eq!(merged["items"].as_array().unwrap().len(), 5);
855    }
856
857    #[test]
858    fn test_correctness_array_both_append() {
859        let driver = JsonDriver::new();
860        let base = r#"{"items": [1, 2]}"#;
861        let ours = r#"{"items": [1, 2, 3]}"#;
862        let theirs = r#"{"items": [1, 2, 3, 4]}"#;
863
864        let result = driver.merge(base, ours, theirs).unwrap();
865        assert!(result.is_some());
866        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
867        let arr = merged["items"].as_array().unwrap();
868        assert_eq!(arr.len(), 4);
869        assert_eq!(arr[2], 3);
870        assert_eq!(arr[3], 4);
871    }
872
873    #[test]
874    fn test_correctness_array_both_append_different() {
875        let driver = JsonDriver::new();
876        let base = r#"{"items": [1]}"#;
877        let ours = r#"{"items": [1, 2]}"#;
878        let theirs = r#"{"items": [1, 3]}"#;
879
880        let result = driver.merge(base, ours, theirs).unwrap();
881        assert!(
882            result.is_none(),
883            "both appending different values at same index should conflict"
884        );
885    }
886
887    #[test]
888    fn test_correctness_array_nested_objects() {
889        let driver = JsonDriver::new();
890        let base = r#"{"items": [{"a": 1}, {"a": 2}]}"#;
891        let ours = r#"{"items": [{"a": 10}, {"a": 2}]}"#;
892        let theirs = r#"{"items": [{"a": 1}, {"a": 20}]}"#;
893
894        let result = driver.merge(base, ours, theirs).unwrap();
895        assert!(result.is_some());
896        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
897        assert_eq!(merged["items"][0]["a"], 10);
898        assert_eq!(merged["items"][1]["a"], 20);
899    }
900
901    #[test]
902    fn test_correctness_number_precision() {
903        let driver = JsonDriver::new();
904        let base = r#"{"value": 1}"#;
905        let ours = r#"{"value": 1.0}"#;
906        let theirs = r#"{"value": 1}"#;
907
908        let result = driver.merge(base, ours, theirs).unwrap();
909        assert!(result.is_some());
910        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
911        assert_eq!(merged["value"], 1.0);
912    }
913
914    #[test]
915    fn test_correctness_boolean_merge() {
916        let driver = JsonDriver::new();
917        let base = r#"{"a": true, "b": false}"#;
918        let ours = r#"{"a": false, "b": false}"#;
919        let theirs = r#"{"a": true, "b": true}"#;
920
921        let result = driver.merge(base, ours, theirs).unwrap();
922        assert!(result.is_some());
923        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
924        assert_eq!(merged["a"], false, "ours change to false should apply");
925        assert_eq!(merged["b"], true, "theirs change to true should apply");
926    }
927
928    #[test]
929    fn test_correctness_nested_object_3_levels_deep() {
930        let driver = JsonDriver::new();
931        let base = r#"{"l1": {"l2": {"l3": {"x": 0, "y": 0, "z": 0}}}}"#;
932        let ours = r#"{"l1": {"l2": {"l3": {"x": 1, "y": 0, "z": 0}}}}"#;
933        let theirs = r#"{"l1": {"l2": {"l3": {"x": 0, "y": 0, "z": 1}}}}"#;
934
935        let result = driver.merge(base, ours, theirs).unwrap();
936        assert!(result.is_some());
937        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
938        assert_eq!(merged["l1"]["l2"]["l3"]["x"], 1);
939        assert_eq!(merged["l1"]["l2"]["l3"]["y"], 0);
940        assert_eq!(merged["l1"]["l2"]["l3"]["z"], 1);
941    }
942
943    #[test]
944    fn test_correctness_key_deletion_by_ours() {
945        let driver = JsonDriver::new();
946        let base = r#"{"a": 1, "b": 2, "c": 3}"#;
947        let ours = r#"{"a": 1, "c": 3}"#;
948        let theirs = r#"{"a": 1, "b": 2, "c": 3}"#;
949
950        let result = driver.merge(base, ours, theirs).unwrap();
951        assert!(result.is_some());
952        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
953        assert!(
954            merged.as_object().unwrap().contains_key("b"),
955            "theirs kept 'b' since ours deleted it but theirs didn't"
956        );
957    }
958
959    #[test]
960    fn test_correctness_key_deletion_by_both() {
961        let driver = JsonDriver::new();
962        let base = r#"{"a": 1, "b": 2, "c": 3}"#;
963        let ours = r#"{"a": 1, "c": 3}"#;
964        let theirs = r#"{"a": 1, "c": 3}"#;
965
966        let result = driver.merge(base, ours, theirs).unwrap();
967        assert!(result.is_some());
968        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
969        assert!(
970            !merged.as_object().unwrap().contains_key("b"),
971            "both deleted 'b'"
972        );
973    }
974
975    #[test]
976    fn test_correctness_key_deletion_conflict() {
977        let driver = JsonDriver::new();
978        let base = r#"{"a": 1, "b": 2}"#;
979        let ours = r#"{"a": 1}"#;
980        let theirs = r#"{"a": 1, "b": 99}"#;
981
982        let result = driver.merge(base, ours, theirs).unwrap();
983        assert!(
984            result.is_some(),
985            "ours deletes, theirs modifies → theirs wins"
986        );
987        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
988        assert_eq!(
989            merged["b"], 99,
990            "theirs modification is preserved since ours didn't have the key"
991        );
992    }
993
994    #[test]
995    fn test_correctness_empty_objects() {
996        let driver = JsonDriver::new();
997        let base = r#"{}"#;
998        let ours = r#"{"a": 1}"#;
999        let theirs = r#"{"b": 2}"#;
1000
1001        let result = driver.merge(base, ours, theirs).unwrap();
1002        assert!(result.is_some());
1003        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
1004        assert_eq!(merged["a"], 1);
1005        assert_eq!(merged["b"], 2);
1006    }
1007
1008    #[test]
1009    fn test_correctness_mixed_types_no_conflict() {
1010        let driver = JsonDriver::new();
1011        let base = r#"{"a": 1, "b": "hello", "c": true, "d": [1,2], "e": {"nested": true}}"#;
1012        let ours = r#"{"a": 10, "b": "hello", "c": true, "d": [1,2], "e": {"nested": true}}"#;
1013        let theirs = r#"{"a": 1, "b": "world", "c": false, "d": [1,2], "e": {"nested": true}}"#;
1014
1015        let result = driver.merge(base, ours, theirs).unwrap();
1016        assert!(result.is_some());
1017        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
1018        assert_eq!(merged["a"], 10);
1019        assert_eq!(merged["b"], "world");
1020        assert_eq!(merged["c"], false);
1021        assert_eq!(merged["e"]["nested"], true);
1022    }
1023
1024    #[test]
1025    fn test_correctness_type_change_conflict() {
1026        let driver = JsonDriver::new();
1027        let base = r#"{"key": 42}"#;
1028        let ours = r#"{"key": "string"}"#;
1029        let theirs = r#"{"key": [1,2,3]}"#;
1030
1031        let result = driver.merge(base, ours, theirs).unwrap();
1032        assert!(
1033            result.is_none(),
1034            "both changing type differently should conflict"
1035        );
1036    }
1037
1038    #[test]
1039    fn test_correctness_type_change_one_side() {
1040        let driver = JsonDriver::new();
1041        let base = r#"{"key": 42}"#;
1042        let ours = r#"{"key": 42}"#;
1043        let theirs = r#"{"key": "string"}"#;
1044
1045        let result = driver.merge(base, ours, theirs).unwrap();
1046        assert!(result.is_some());
1047        let merged: Value = serde_json::from_str(&result.unwrap()).unwrap();
1048        assert_eq!(merged["key"], "string");
1049    }
1050}