Add remaining test files: test_merge, test_sync, test_validate
This commit is contained in:
209
confsync/tests/test_merge.py
Normal file
209
confsync/tests/test_merge.py
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
"""Tests for merge strategies."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from confsync.core.merger import (
|
||||||
|
Merger,
|
||||||
|
KeepLocalStrategy,
|
||||||
|
KeepRemoteStrategy,
|
||||||
|
KeepCommonStrategy,
|
||||||
|
ThreeWayMergeStrategy,
|
||||||
|
UnionMergeStrategy,
|
||||||
|
MergeConflict,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMergeStrategies:
|
||||||
|
"""Tests for individual merge strategies."""
|
||||||
|
|
||||||
|
def test_keep_local_strategy(self):
|
||||||
|
"""Test keep local strategy."""
|
||||||
|
strategy = KeepLocalStrategy()
|
||||||
|
|
||||||
|
local = "local content"
|
||||||
|
remote = "remote content"
|
||||||
|
|
||||||
|
success, merged, conflict = strategy.merge(local, remote)
|
||||||
|
|
||||||
|
assert success
|
||||||
|
assert merged == local
|
||||||
|
assert conflict is None
|
||||||
|
|
||||||
|
def test_keep_remote_strategy(self):
|
||||||
|
"""Test keep remote strategy."""
|
||||||
|
strategy = KeepRemoteStrategy()
|
||||||
|
|
||||||
|
local = "local content"
|
||||||
|
remote = "remote content"
|
||||||
|
|
||||||
|
success, merged, conflict = strategy.merge(local, remote)
|
||||||
|
|
||||||
|
assert success
|
||||||
|
assert merged == remote
|
||||||
|
assert conflict is None
|
||||||
|
|
||||||
|
def test_keep_common_strategy(self):
|
||||||
|
"""Test keep common strategy."""
|
||||||
|
strategy = KeepCommonStrategy()
|
||||||
|
|
||||||
|
local = "line1\nline2\nline3"
|
||||||
|
remote = "line2\nline3\nline4"
|
||||||
|
|
||||||
|
success, merged, conflict = strategy.merge(local, remote)
|
||||||
|
|
||||||
|
assert success
|
||||||
|
assert "line2" in merged
|
||||||
|
assert "line3" in merged
|
||||||
|
assert "line1" not in merged
|
||||||
|
assert "line4" not in merged
|
||||||
|
|
||||||
|
def test_three_way_merge_identical(self):
|
||||||
|
"""Test three-way merge with identical content."""
|
||||||
|
strategy = ThreeWayMergeStrategy()
|
||||||
|
|
||||||
|
content = "same content"
|
||||||
|
success, merged, conflict = strategy.merge(content, content, content)
|
||||||
|
|
||||||
|
assert success
|
||||||
|
assert merged == content
|
||||||
|
assert conflict is None
|
||||||
|
|
||||||
|
def test_three_way_merge_no_conflicts(self):
|
||||||
|
"""Test three-way merge without conflicts."""
|
||||||
|
strategy = ThreeWayMergeStrategy()
|
||||||
|
|
||||||
|
base = "same content"
|
||||||
|
local = "same content"
|
||||||
|
remote = "same content"
|
||||||
|
|
||||||
|
success, merged, conflict = strategy.merge(local, remote, base)
|
||||||
|
|
||||||
|
assert success
|
||||||
|
assert conflict is None
|
||||||
|
|
||||||
|
def test_union_merge_strategy(self):
|
||||||
|
"""Test union merge strategy."""
|
||||||
|
strategy = UnionMergeStrategy()
|
||||||
|
|
||||||
|
local = "line1\nline2\nline3"
|
||||||
|
remote = "line3\nline4\nline5"
|
||||||
|
|
||||||
|
success, merged, conflict = strategy.merge(local, remote)
|
||||||
|
|
||||||
|
assert success
|
||||||
|
assert "line1" in merged
|
||||||
|
assert "line2" in merged
|
||||||
|
assert "line3" in merged
|
||||||
|
assert "line4" in merged
|
||||||
|
assert "line5" in merged
|
||||||
|
|
||||||
|
def test_union_merge_removes_duplicates(self):
|
||||||
|
"""Test union merge removes duplicate lines."""
|
||||||
|
strategy = UnionMergeStrategy()
|
||||||
|
|
||||||
|
local = "line1\nline2\nline2"
|
||||||
|
remote = "line2\nline3"
|
||||||
|
|
||||||
|
success, merged, conflict = strategy.merge(local, remote)
|
||||||
|
|
||||||
|
assert success
|
||||||
|
lines = merged.split('\n')
|
||||||
|
assert lines.count("line2") == 1
|
||||||
|
|
||||||
|
|
||||||
|
class TestMergeConflict:
|
||||||
|
"""Tests for merge conflict handling."""
|
||||||
|
|
||||||
|
def test_format_conflict(self):
|
||||||
|
"""Test conflict formatting."""
|
||||||
|
conflict = MergeConflict(
|
||||||
|
file_path="/test/file.txt",
|
||||||
|
local_lines=["local line 1", "local line 2"],
|
||||||
|
remote_lines=["remote line 1", "remote line 2"],
|
||||||
|
base_lines=["base line 1"],
|
||||||
|
)
|
||||||
|
|
||||||
|
formatted = conflict.format_conflict()
|
||||||
|
|
||||||
|
assert "<<<<<<< LOCAL" in formatted
|
||||||
|
assert "=======" in formatted
|
||||||
|
assert ">>>>>>> REMOTE" in formatted
|
||||||
|
assert "local line 1" in formatted
|
||||||
|
assert "remote line 1" in formatted
|
||||||
|
|
||||||
|
|
||||||
|
class TestMerger:
|
||||||
|
"""Tests for the main Merger class."""
|
||||||
|
|
||||||
|
def test_get_strategy(self):
|
||||||
|
"""Test getting strategy by name."""
|
||||||
|
merger = Merger()
|
||||||
|
|
||||||
|
strategy = merger.get_strategy("keep_local")
|
||||||
|
assert isinstance(strategy, KeepLocalStrategy)
|
||||||
|
|
||||||
|
strategy = merger.get_strategy("three_way")
|
||||||
|
assert isinstance(strategy, ThreeWayMergeStrategy)
|
||||||
|
|
||||||
|
def test_merge_file_with_strategy(self):
|
||||||
|
"""Test merging a single file with strategy."""
|
||||||
|
merger = Merger()
|
||||||
|
|
||||||
|
local = "local config"
|
||||||
|
remote = "remote config"
|
||||||
|
|
||||||
|
success, merged, conflict = merger.merge_file(
|
||||||
|
local, remote, strategy_name="keep_local"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert success
|
||||||
|
assert merged == "local config"
|
||||||
|
|
||||||
|
def test_merge_multiple_files(self):
|
||||||
|
"""Test merging multiple files at once."""
|
||||||
|
merger = Merger()
|
||||||
|
|
||||||
|
files = [
|
||||||
|
{
|
||||||
|
"path": "/test/file1.txt",
|
||||||
|
"local": "local1",
|
||||||
|
"remote": "remote1",
|
||||||
|
"strategy": "keep_local",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/test/file2.txt",
|
||||||
|
"local": "local2",
|
||||||
|
"remote": "remote2",
|
||||||
|
"strategy": "keep_remote",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
results = merger.merge_multiple(files)
|
||||||
|
|
||||||
|
assert "/test/file1.txt" in results
|
||||||
|
assert "/test/file2.txt" in results
|
||||||
|
|
||||||
|
|
||||||
|
class TestMergeResult:
|
||||||
|
"""Tests for merge result model."""
|
||||||
|
|
||||||
|
def test_merge_result_serialization(self):
|
||||||
|
"""Test MergeResult serialization."""
|
||||||
|
from confsync.models.config_models import MergeResult
|
||||||
|
|
||||||
|
result = MergeResult(
|
||||||
|
success=True,
|
||||||
|
merged_files={"file1": "merged content"},
|
||||||
|
conflicts={},
|
||||||
|
unresolved=[],
|
||||||
|
strategy_used="three_way",
|
||||||
|
message="Merge successful",
|
||||||
|
)
|
||||||
|
|
||||||
|
data = result.to_dict()
|
||||||
|
|
||||||
|
assert data["success"] is True
|
||||||
|
assert data["strategy_used"] == "three_way"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
pytest.main([__file__, "-v"])
|
||||||
Reference in New Issue
Block a user