mirror of
https://github.com/rommapp/romm.git
synced 2026-04-23 06:54:40 +00:00
144 lines
5.4 KiB
Python
144 lines
5.4 KiB
Python
"""Tests for sync comparison algorithm."""
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
from handler.sync.comparison import SyncComparisonResult, compare_save_state
|
|
|
|
|
|
class TestCompareIdenticalHashes:
|
|
def test_identical_hashes_returns_no_op(self):
|
|
result = compare_save_state(
|
|
client_hash="abc123",
|
|
client_updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
server_hash="abc123",
|
|
server_updated_at=datetime(2026, 1, 2, tzinfo=timezone.utc),
|
|
device_last_synced_at=None,
|
|
)
|
|
assert result.action == "no_op"
|
|
assert "identical" in result.reason.lower()
|
|
|
|
def test_identical_hashes_with_sync_history(self):
|
|
result = compare_save_state(
|
|
client_hash="abc123",
|
|
client_updated_at=datetime(2026, 1, 5, tzinfo=timezone.utc),
|
|
server_hash="abc123",
|
|
server_updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
device_last_synced_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
)
|
|
assert result.action == "no_op"
|
|
|
|
|
|
class TestCompareWithSyncHistory:
|
|
"""Tests where device has synced before (device_last_synced_at is set)."""
|
|
|
|
def test_client_changed_returns_upload(self):
|
|
result = compare_save_state(
|
|
client_hash="new_hash",
|
|
client_updated_at=datetime(2026, 1, 10, tzinfo=timezone.utc),
|
|
server_hash="old_hash",
|
|
server_updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
device_last_synced_at=datetime(2026, 1, 5, tzinfo=timezone.utc),
|
|
)
|
|
assert result.action == "upload"
|
|
|
|
def test_server_changed_returns_download(self):
|
|
result = compare_save_state(
|
|
client_hash="old_hash",
|
|
client_updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
server_hash="new_hash",
|
|
server_updated_at=datetime(2026, 1, 10, tzinfo=timezone.utc),
|
|
device_last_synced_at=datetime(2026, 1, 5, tzinfo=timezone.utc),
|
|
)
|
|
assert result.action == "download"
|
|
|
|
def test_both_changed_returns_conflict(self):
|
|
result = compare_save_state(
|
|
client_hash="client_new",
|
|
client_updated_at=datetime(2026, 1, 10, tzinfo=timezone.utc),
|
|
server_hash="server_new",
|
|
server_updated_at=datetime(2026, 1, 10, tzinfo=timezone.utc),
|
|
device_last_synced_at=datetime(2026, 1, 5, tzinfo=timezone.utc),
|
|
)
|
|
assert result.action == "conflict"
|
|
|
|
def test_neither_changed_returns_no_op(self):
|
|
result = compare_save_state(
|
|
client_hash="different_hash",
|
|
client_updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
server_hash="other_hash",
|
|
server_updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
device_last_synced_at=datetime(2026, 1, 5, tzinfo=timezone.utc),
|
|
)
|
|
assert result.action == "no_op"
|
|
|
|
|
|
class TestCompareWithoutSyncHistory:
|
|
"""Tests where device has never synced (device_last_synced_at is None)."""
|
|
|
|
def test_client_newer_returns_upload(self):
|
|
result = compare_save_state(
|
|
client_hash="client_hash",
|
|
client_updated_at=datetime(2026, 1, 10, tzinfo=timezone.utc),
|
|
server_hash="server_hash",
|
|
server_updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
device_last_synced_at=None,
|
|
)
|
|
assert result.action == "upload"
|
|
|
|
def test_server_newer_returns_download(self):
|
|
result = compare_save_state(
|
|
client_hash="client_hash",
|
|
client_updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
server_hash="server_hash",
|
|
server_updated_at=datetime(2026, 1, 10, tzinfo=timezone.utc),
|
|
device_last_synced_at=None,
|
|
)
|
|
assert result.action == "download"
|
|
|
|
def test_same_timestamp_different_hashes_returns_conflict(self):
|
|
ts = datetime(2026, 1, 5, tzinfo=timezone.utc)
|
|
result = compare_save_state(
|
|
client_hash="hash_a",
|
|
client_updated_at=ts,
|
|
server_hash="hash_b",
|
|
server_updated_at=ts,
|
|
device_last_synced_at=None,
|
|
)
|
|
assert result.action == "conflict"
|
|
|
|
def test_same_timestamp_same_hashes_returns_no_op(self):
|
|
ts = datetime(2026, 1, 5, tzinfo=timezone.utc)
|
|
result = compare_save_state(
|
|
client_hash="same",
|
|
client_updated_at=ts,
|
|
server_hash="same",
|
|
server_updated_at=ts,
|
|
device_last_synced_at=None,
|
|
)
|
|
assert result.action == "no_op"
|
|
|
|
def test_same_timestamp_none_hashes_returns_no_op(self):
|
|
ts = datetime(2026, 1, 5, tzinfo=timezone.utc)
|
|
result = compare_save_state(
|
|
client_hash=None,
|
|
client_updated_at=ts,
|
|
server_hash=None,
|
|
server_updated_at=ts,
|
|
device_last_synced_at=None,
|
|
)
|
|
assert result.action == "no_op"
|
|
|
|
|
|
class TestCompareReturnType:
|
|
def test_returns_named_tuple(self):
|
|
result = compare_save_state(
|
|
client_hash="a",
|
|
client_updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
server_hash="a",
|
|
server_updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
|
device_last_synced_at=None,
|
|
)
|
|
assert isinstance(result, SyncComparisonResult)
|
|
assert isinstance(result.action, str)
|
|
assert isinstance(result.reason, str)
|