()
| 541 | |
| 542 | #[test] |
| 543 | fn conflict_on_overlapping_edits() { |
| 544 | let mut txn = MockTxn::new(); |
| 545 | let store = MemoryChangeStore::new(); |
| 546 | |
| 547 | // Base: "x = 1" |
| 548 | let base_hash = make_change(&store, b"x = 1"); |
| 549 | let base_id = NodeId::new(1); |
| 550 | txn.register(base_id, base_hash); |
| 551 | |
| 552 | // Left: "x = 2" |
| 553 | let left_hash = make_change(&store, b"x = 2"); |
| 554 | let left_id = NodeId::new(2); |
| 555 | txn.register(left_id, left_hash); |
| 556 | |
| 557 | // Right: "x = 3" |
| 558 | let right_hash = make_change(&store, b"x = 3"); |
| 559 | let right_id = NodeId::new(3); |
| 560 | txn.register(right_id, right_hash); |
| 561 | |
| 562 | let engine = SemanticMergeEngine::new(&txn, &store); |
| 563 | |
| 564 | let v_base = GraphNode::new(base_id, ChangePosition::new(0), ChangePosition::new(5)); |
| 565 | let v_left = GraphNode::new(left_id, ChangePosition::new(0), ChangePosition::new(5)); |
| 566 | let v_right = GraphNode::new(right_id, ChangePosition::new(0), ChangePosition::new(5)); |
| 567 | |
| 568 | let group = ConflictGroup::new(vec![v_left, v_right]).with_ancestor(v_base); |
| 569 | let outcome = engine.try_merge(&group).unwrap(); |
| 570 | |
| 571 | assert!( |
| 572 | outcome.is_conflict(), |
| 573 | "expected Conflict, got {:?}", |
| 574 | outcome, |
| 575 | ); |
| 576 | if let MergeOutcome::Conflict { |
| 577 | base, |
| 578 | left, |
| 579 | right, |
| 580 | left_change, |
| 581 | right_change, |
| 582 | } = &outcome |
| 583 | { |
| 584 | assert_eq!(base, b"x = 1"); |
| 585 | assert_eq!(left, b"x = 2"); |
| 586 | assert_eq!(right, b"x = 3"); |
| 587 | assert_eq!(*left_change, left_id); |
| 588 | assert_eq!(*right_change, right_id); |
| 589 | } |
| 590 | } |
| 591 | |
| 592 | // ---- SemanticMergeEngine: both sides same edit → AutoMerged ----------- |
| 593 |
nothing calls this directly
no test coverage detected