Add test files: test_core, test_detect, test_manifest
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
2026-02-04 20:09:06 +00:00
parent c51c1f3369
commit bb3f2f655f

280
confsync/tests/test_core.py Normal file
View File

@@ -0,0 +1,280 @@
"""Tests for core utilities and encryption."""
import pytest
import tempfile
import os
from pathlib import Path
from confsync.utils.file_utils import (
calculate_file_hash,
read_file_safe,
write_file_safe,
find_files_matching,
get_file_size,
)
from confsync.utils.path_utils import (
expand_path,
normalize_path,
get_home_directory,
get_xdg_config_dir,
is_subpath,
)
from confsync.utils.encryption import EncryptionManager, EncryptedData
class TestFileUtils:
"""Tests for file utilities."""
def test_calculate_hash(self):
"""Test hash calculation."""
content1 = "test content"
content2 = "test content"
hash1 = calculate_file_hash(content1)
hash2 = calculate_file_hash(content2)
assert hash1 == hash2
assert len(hash1) == 64
def test_calculate_hash_different(self):
"""Test hash calculation for different content."""
hash1 = calculate_file_hash("content 1")
hash2 = calculate_file_hash("content 2")
assert hash1 != hash2
def test_read_file_safe_success(self):
"""Test reading file successfully."""
with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
f.write("test content")
temp_path = f.name
try:
content = read_file_safe(temp_path)
assert content == "test content"
finally:
os.unlink(temp_path)
def test_read_file_safe_nonexistent(self):
"""Test reading nonexistent file."""
content = read_file_safe("/nonexistent/path/file.txt")
assert content is None
def test_write_file_safe_success(self):
"""Test writing file successfully."""
with tempfile.TemporaryDirectory() as tmpdir:
path = os.path.join(tmpdir, "test.txt")
success = write_file_safe("test content", path)
assert success
assert os.path.exists(path)
with open(path, 'r') as f:
assert f.read() == "test content"
def test_find_files_matching(self):
"""Test finding files by pattern."""
with tempfile.TemporaryDirectory() as tmpdir:
Path(os.path.join(tmpdir, "file1.json")).touch()
Path(os.path.join(tmpdir, "file2.json")).touch()
Path(os.path.join(tmpdir, "file3.yaml")).touch()
json_files = find_files_matching(tmpdir, ["*.json"])
assert len(json_files) == 2
assert all(f.endswith('.json') for f in json_files)
def test_get_file_size(self):
"""Test getting file size."""
with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
f.write("1234567890")
temp_path = f.name
try:
size = get_file_size(temp_path)
assert size == 10
finally:
os.unlink(temp_path)
class TestPathUtils:
"""Tests for path utilities."""
def test_expand_path_tilde(self):
"""Test expanding home directory."""
expanded = expand_path("~/config")
assert expanded.startswith("/")
assert "config" in expanded
def test_expand_path_env(self):
"""Test expanding environment variables."""
os.environ["TEST_VAR"] = "test_value"
expanded = expand_path("$TEST_VAR/path")
assert "test_value" in expanded
def test_normalize_path(self):
"""Test normalizing paths."""
path = normalize_path("~/./config")
assert path.startswith("/")
def test_get_home_directory(self):
"""Test getting home directory."""
home = get_home_directory()
assert home.startswith("/")
assert os.path.exists(home)
def test_get_xdg_config_dir(self):
"""Test getting XDG config directory."""
xdg = get_xdg_config_dir()
assert xdg.startswith("/")
def test_is_subpath(self):
"""Test subpath detection."""
assert is_subpath("/home/user/config", "/home/user")
assert is_subpath("/home/user/.config/file", "/home/user/.config")
class TestEncryption:
"""Tests for encryption utilities."""
def test_encrypt_decrypt(self):
"""Test encryption and decryption."""
enc_manager = EncryptionManager(passphrase="test_passphrase")
original = "sensitive data"
encrypted = enc_manager.encrypt(original)
assert isinstance(encrypted, EncryptedData)
assert len(encrypted.salt) == 16
decrypted = enc_manager.decrypt(encrypted, passphrase="test_passphrase")
assert decrypted == original
def test_encrypt_manifest_roundtrip(self):
"""Test manifest encryption roundtrip."""
enc_manager = EncryptionManager(passphrase="test_passphrase")
manifest_data = '{"version": "1.0.0", "entries": []}'
encrypted = enc_manager.encrypt_manifest(manifest_data)
assert isinstance(encrypted, str)
decrypted = enc_manager.decrypt_manifest(encrypted)
assert decrypted == manifest_data
def test_encrypt_file(self):
"""Test file encryption."""
enc_manager = EncryptionManager(passphrase="test_passphrase")
with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
f.write("sensitive content")
input_path = f.name
try:
output_path = enc_manager.encrypt_file(input_path)
assert os.path.exists(output_path)
assert output_path != input_path
with open(output_path, 'rb') as f:
content = f.read()
assert len(content) > 16
os.unlink(output_path)
finally:
os.unlink(input_path)
def test_verify_key(self):
"""Test key verification."""
with tempfile.TemporaryDirectory() as tmpdir:
key_path = os.path.join(tmpdir, "test.key")
enc_manager = EncryptionManager(key_file=key_path, passphrase="test_passphrase")
enc_manager.generate_key_file(key_path, "test_passphrase")
assert os.path.exists(key_path)
assert enc_manager.verify_key(key_path, "test_passphrase") is True
assert enc_manager.verify_key(key_path, "wrong_passphrase") is False
class TestSyncMetadata:
"""Tests for sync metadata model."""
def test_sync_metadata_serialization(self):
"""Test SyncMetadata serialization."""
from confsync.models.config_models import SyncMetadata, SyncOperation
metadata = SyncMetadata(
operation=SyncOperation.PUSH,
source="/local",
destination="/remote",
)
data = metadata.to_dict()
assert data["operation"] == "push"
assert data["source"] == "/local"
assert data["destination"] == "/remote"
def test_sync_metadata_from_dict(self):
"""Test SyncMetadata deserialization."""
from confsync.models.config_models import SyncMetadata, SyncOperation
data = {
"operation": "pull",
"source": "/remote",
"destination": "/local",
"timestamp": "2024-01-01T00:00:00",
"committed_files": [],
"conflicts": [],
"merged_files": [],
"status": "success",
"error_message": None,
}
metadata = SyncMetadata.from_dict(data)
assert metadata.operation == SyncOperation.PULL
assert metadata.status == "success"
class TestHistoryEntry:
"""Tests for history entry model."""
def test_history_entry_serialization(self):
"""Test HistoryEntry serialization."""
from confsync.models.config_models import HistoryEntry
entry = HistoryEntry(
operation="sync",
files_changed=[".vimrc", ".bashrc"],
commit_message="Update configs",
)
data = entry.to_dict()
assert data["operation"] == "sync"
assert len(data["files_changed"]) == 2
def test_history_entry_from_dict(self):
"""Test HistoryEntry deserialization."""
from confsync.models.config_models import HistoryEntry
data = {
"id": "test-id",
"timestamp": "2024-01-01T00:00:00",
"operation": "rollback",
"files_changed": [".vimrc"],
"commit_message": "Rollback to previous",
"diff": None,
"tags": [],
}
entry = HistoryEntry.from_dict(data)
assert entry.id == "test-id"
assert entry.operation == "rollback"
if __name__ == "__main__":
pytest.main([__file__, "-v"])