Skip to main content

suture_driver_json/
lib.rs

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