Files
cleveragents-core/features/three_way_merge_conflict.feature
T
HAL9000 cb27538a73
CI / lint (pull_request) Successful in 45s
CI / typecheck (pull_request) Successful in 1m12s
CI / security (pull_request) Successful in 1m13s
CI / quality (pull_request) Successful in 40s
CI / push-validation (pull_request) Successful in 35s
CI / helm (pull_request) Successful in 37s
CI / build (pull_request) Successful in 46s
CI / integration_tests (pull_request) Successful in 4m52s
CI / unit_tests (pull_request) Successful in 6m20s
CI / docker (pull_request) Successful in 1m34s
CI / coverage (pull_request) Successful in 11m20s
CI / status-check (pull_request) Successful in 3s
test(planconfig): add BDD coverage for ThreeWayMergeConflictDetector
Add feature file and Behave steps covering all reachable code paths in
merge_conflict.py: MODIFY_MODIFY/DELETE/ADD_ADD conflict types, auto-
resolution for MODIFY_DELETE/DELETE_MODIFY/convergent ADD_ADD, DELETE_DELETE
absence, detect_diff_text formatting, describe_all status types, and direct
_analyse_field call for the unreachable ADD_ADD branch.

Restores coverage above the 96.5% threshold after the merge_conflict module
was added with zero test coverage.

ISSUES CLOSED: #11000
2026-05-28 12:52:19 -04:00

135 lines
6.6 KiB
Gherkin

Feature: Three-Way Merge Conflict Detector
Exercises ThreeWayMergeConflictDetector, ConflictReport, ConflictContext,
MergeResult, and ConflictType for structured plan config merge conflict reporting.
Scenario: Identical values produce a clean merge
Given a three-way merge where all versions agree on key "x" value "hello"
When I run the three-way merge detector
Then the merge should have no conflicts
And the merged config should contain key "x" with value "hello"
Scenario: Both sides modify a key independently raises MODIFY_MODIFY
Given a three-way merge with ancestor "x"="a", parent "x"="b", subplan "x"="c"
When I run the three-way merge detector
Then the merge should have 1 conflict
And the conflict key is "x" with type "MODIFY_MODIFY"
And the conflict has no auto-resolved entries
Scenario: Both sides converge on the same new value is auto-resolved as ADD_ADD
Given a three-way merge with ancestor "x"="old", parent "x"="new", subplan "x"="new"
When I run the three-way merge detector
Then the merge should have no conflicts
And key "x" is auto-resolved to "new"
Scenario: Parent modifies and subplan deletes is auto-resolved to parent value
Given a three-way merge with key "x", ancestor "old", parent changed to "new", subplan deleted it
When I run the three-way merge detector
Then the merge should have no conflicts
And key "x" is auto-resolved to "new"
Scenario: Parent deletes and subplan modifies is auto-resolved to subplan value
Given a three-way merge with key "x", ancestor "old", parent deleted it, subplan changed to "new"
When I run the three-way merge detector
Then the merge should have no conflicts
And key "x" is auto-resolved to "new"
Scenario: Both sides add the same new key is auto-resolved
Given a three-way merge where ancestor lacks "x", parent and subplan both add it as "same"
When I run the three-way merge detector
Then the merge should have no conflicts
And key "x" is auto-resolved to "same"
Scenario: Both sides add different values for the same new key raises ADD_ADD conflict
Given a three-way merge where ancestor lacks "x", parent adds "val1" and subplan adds "val2"
When I run the three-way merge detector
Then the merge should have 1 conflict
And the conflict key is "x" with type "ADD_ADD"
Scenario: Parent deletes a key the subplan kept unchanged removes it from output
Given a three-way merge where parent deletes "x" and subplan keeps it at "val"
When I run the three-way merge detector
Then the merge should have no conflicts
And the merged config should not contain key "x"
Scenario: Subplan deletes a key the parent kept unchanged removes it from output
Given a three-way merge where subplan deletes "x" and parent keeps it at "val"
When I run the three-way merge detector
Then the merge should have no conflicts
And the merged config should not contain key "x"
Scenario: Only parent changes a key is auto-resolved to parent value
Given a three-way merge where only parent changed key "y" from "old" to "new", subplan kept "old"
When I run the three-way merge detector
Then the merge should have no conflicts
And key "y" is auto-resolved to "new"
Scenario: Only subplan changes a key is auto-resolved to subplan value
Given a three-way merge where only subplan changed key "y" from "old" to "new", parent kept "old"
When I run the three-way merge detector
Then the merge should have no conflicts
And key "y" is auto-resolved to "new"
Scenario: detect_diff_text returns a clean message when there are no conflicts
Given a three-way merge where all versions agree on key "z" value "ok"
When I call detect_diff_text
Then the diff text should say "No conflicts detected"
Scenario: detect_diff_text includes absent ancestor in ADD_ADD conflict report
Given a three-way merge where ancestor lacks "m", parent adds "v1" and subplan adds "v2"
When I call detect_diff_text
Then the diff text should contain "ADD_ADD"
And the diff text should contain "(absent)"
And the diff text should contain "Key: m"
Scenario: detect_diff_text includes auto-resolved and merged config sections
Given a mixed three-way merge scenario
When I call detect_diff_text
Then the diff text should contain "MODIFY_MODIFY"
And the diff text should contain "Auto-resolved"
And the diff text should contain "Merged config"
Scenario: describe_all returns CONFLICT AUTO_RESOLVED and MERGED_OK entries
Given a mixed three-way merge scenario
When I call describe_all
Then the summary should contain a CONFLICT entry
And the summary should contain an AUTO_RESOLVED entry
And the summary should contain a MERGED_OK entry
Scenario: ConflictReport resolved_value is None for MODIFY_MODIFY
Given a ConflictReport of type "MODIFY_MODIFY" with ancestor "a" parent "b" subplan "c"
When I check the resolved_value
Then the resolved_value should be None
Scenario: ConflictReport resolved_value returns parent value for MODIFY_DELETE
Given a ConflictReport of type "MODIFY_DELETE" with ancestor "a" parent "new_val" and no subplan
When I check the resolved_value
Then the resolved_value should equal "new_val"
Scenario: ConflictReport resolved_value returns subplan value for DELETE_MODIFY
Given a ConflictReport of type "DELETE_MODIFY" with ancestor "a" no parent and subplan "new_val"
When I check the resolved_value
Then the resolved_value should equal "new_val"
Scenario: ConflictReport resolved_value is None for ADD_ADD with mismatched values
Given a ConflictReport of type "ADD_ADD" with no ancestor parent "p1" subplan "p2"
When I check the resolved_value
Then the resolved_value should be None
Scenario: ConflictReport resolved_value returns parent for ADD_ADD with matching values
Given a ConflictReport of type "ADD_ADD" with no ancestor parent "same" subplan "same"
When I check the resolved_value
Then the resolved_value should equal "same"
Scenario: ThreeWayMergeConflictDetector handles None inputs gracefully
Given a three-way merge detector initialized with all None inputs
When I run the three-way merge detector
Then the merge should have no conflicts
Scenario: _analyse_field direct call covers the not-p-changed not-s-changed ADD_ADD branch
Given I directly call analyse_field with all-False has_key flags and None values
Then the analyse_field result type should be "ADD_ADD"
Scenario: planconfig package __init__ exports are importable and helpers callable
Given I import the planconfig package and call its internal helper
Then the helper returns a non-empty list