1use 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}