mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
commit tests for file_sync_service
This commit is contained in:
@@ -63,6 +63,7 @@ class FileSyncService:
|
||||
try:
|
||||
content = path.read_text()
|
||||
checksum = await self.document_service.compute_checksum(content)
|
||||
# Store path relative to root directory
|
||||
rel_path = str(path.relative_to(directory))
|
||||
files[rel_path] = checksum
|
||||
except Exception as e:
|
||||
@@ -117,6 +118,7 @@ class FileSyncService:
|
||||
full_path = directory / path
|
||||
try:
|
||||
content = full_path.read_text()
|
||||
# Use relative path for document
|
||||
await self.document_service.create_document(path, content)
|
||||
except Exception as e:
|
||||
raise SyncError(f"Failed to sync new file {path}: {e}")
|
||||
@@ -135,6 +137,7 @@ class FileSyncService:
|
||||
full_path = directory / path
|
||||
try:
|
||||
content = full_path.read_text()
|
||||
# Use relative path for document
|
||||
await self.document_service.update_document(path, content)
|
||||
except Exception as e:
|
||||
raise SyncError(f"Failed to sync modified file {path}: {e}")
|
||||
@@ -179,6 +182,7 @@ class FileSyncService:
|
||||
# Process deleted files
|
||||
for path in changes.deleted:
|
||||
logger.debug(f"Processing deleted file: {path}")
|
||||
# Use relative path for deletion
|
||||
await self.document_service.delete_document(path)
|
||||
|
||||
logger.info("Sync completed successfully")
|
||||
|
||||
@@ -22,23 +22,24 @@ async def docs_dir(test_project_path) -> Path:
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def sample_files(docs_dir) -> dict[str, str]:
|
||||
"""Create some sample files for testing."""
|
||||
"""Create some sample test files."""
|
||||
# Create test structure
|
||||
design_dir = docs_dir / "design"
|
||||
notes_dir = docs_dir / "notes"
|
||||
design_dir.mkdir()
|
||||
notes_dir.mkdir()
|
||||
design_dir.mkdir(exist_ok=True)
|
||||
notes_dir.mkdir(exist_ok=True)
|
||||
|
||||
# Map of relative paths to content
|
||||
files = {
|
||||
"design/architecture.md": "# Architecture\nSome design notes",
|
||||
"notes/meeting.md": "# Meeting Notes\nDiscussion points",
|
||||
"README.md": "# Project\nOverview doc",
|
||||
}
|
||||
|
||||
# Create files
|
||||
for path, content in files.items():
|
||||
file_path = docs_dir / path
|
||||
file_path.write_text(content)
|
||||
# Create files with full paths
|
||||
for rel_path, content in files.items():
|
||||
full_path = docs_dir / rel_path
|
||||
full_path.write_text(content)
|
||||
|
||||
return files
|
||||
|
||||
@@ -47,13 +48,13 @@ async def sample_files(docs_dir) -> dict[str, str]:
|
||||
async def test_scan_files(file_sync_service, docs_dir, sample_files):
|
||||
"""Test scanning directory for files."""
|
||||
scanned = await file_sync_service.scan_files(docs_dir)
|
||||
|
||||
|
||||
# Should find all files
|
||||
assert len(scanned) == len(sample_files)
|
||||
|
||||
# Paths should be relative
|
||||
assert all(str(docs_dir) not in path for path in scanned)
|
||||
|
||||
|
||||
# Paths should be relative and match sample files
|
||||
assert set(scanned.keys()) == set(sample_files.keys())
|
||||
|
||||
# All files should have checksums
|
||||
assert all(isinstance(checksum, str) for checksum in scanned.values())
|
||||
|
||||
@@ -61,8 +62,10 @@ async def test_scan_files(file_sync_service, docs_dir, sample_files):
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_new_files(file_sync_service, docs_dir, sample_files):
|
||||
"""Test detecting new files."""
|
||||
changes = await file_sync_service.find_changes(await file_sync_service.scan_files(docs_dir))
|
||||
|
||||
changes = await file_sync_service.find_changes(
|
||||
await file_sync_service.scan_files(docs_dir)
|
||||
)
|
||||
|
||||
# All files should be new
|
||||
assert len(changes.new) == len(sample_files)
|
||||
assert len(changes.modified) == 0
|
||||
@@ -74,14 +77,16 @@ async def test_find_modified_files(file_sync_service, docs_dir, sample_files):
|
||||
"""Test detecting modified files."""
|
||||
# First sync to create DB records
|
||||
await file_sync_service.sync(docs_dir)
|
||||
|
||||
|
||||
# Modify a file
|
||||
mod_path = docs_dir / "design/architecture.md"
|
||||
mod_path.write_text("# Updated Architecture")
|
||||
|
||||
|
||||
# Check changes
|
||||
changes = await file_sync_service.find_changes(await file_sync_service.scan_files(docs_dir))
|
||||
|
||||
changes = await file_sync_service.find_changes(
|
||||
await file_sync_service.scan_files(docs_dir)
|
||||
)
|
||||
|
||||
assert len(changes.modified) == 1
|
||||
assert "design/architecture.md" in changes.modified
|
||||
assert len(changes.new) == 0
|
||||
@@ -93,14 +98,16 @@ async def test_find_deleted_files(file_sync_service, docs_dir, sample_files):
|
||||
"""Test detecting deleted files."""
|
||||
# First sync to create DB records
|
||||
await file_sync_service.sync(docs_dir)
|
||||
|
||||
|
||||
# Delete a file
|
||||
del_path = docs_dir / "notes/meeting.md"
|
||||
del_path.unlink()
|
||||
|
||||
|
||||
# Check changes
|
||||
changes = await file_sync_service.find_changes(await file_sync_service.scan_files(docs_dir))
|
||||
|
||||
changes = await file_sync_service.find_changes(
|
||||
await file_sync_service.scan_files(docs_dir)
|
||||
)
|
||||
|
||||
assert len(changes.deleted) == 1
|
||||
assert "notes/meeting.md" in changes.deleted
|
||||
assert len(changes.new) == 0
|
||||
@@ -113,30 +120,28 @@ async def test_full_sync_process(file_sync_service, docs_dir, sample_files):
|
||||
# First sync to create initial state
|
||||
initial_sync = await file_sync_service.sync(docs_dir)
|
||||
assert initial_sync.total_changes == len(sample_files)
|
||||
|
||||
|
||||
# Make some changes:
|
||||
# 1. Add new file
|
||||
new_file = docs_dir / "notes/todo.md"
|
||||
new_file.write_text("# TODO\n- First item")
|
||||
|
||||
(docs_dir / "notes").mkdir(exist_ok=True) # Ensure parent exists
|
||||
(docs_dir / "notes/todo.md").write_text("# TODO\n- First item")
|
||||
|
||||
# 2. Modify existing file
|
||||
mod_file = docs_dir / "README.md"
|
||||
mod_file.write_text("# Updated Project")
|
||||
|
||||
(docs_dir / "README.md").write_text("# Updated Project")
|
||||
|
||||
# 3. Delete a file
|
||||
del_file = docs_dir / "design/architecture.md"
|
||||
del_file.unlink()
|
||||
|
||||
(docs_dir / "design/architecture.md").unlink()
|
||||
|
||||
# Run sync
|
||||
changes = await file_sync_service.sync(docs_dir)
|
||||
|
||||
|
||||
# Verify changes
|
||||
assert len(changes.new) == 1
|
||||
assert "notes/todo.md" in changes.new
|
||||
|
||||
|
||||
assert len(changes.modified) == 1
|
||||
assert "README.md" in changes.modified
|
||||
|
||||
|
||||
assert len(changes.deleted) == 1
|
||||
assert "design/architecture.md" in changes.deleted
|
||||
|
||||
@@ -146,10 +151,10 @@ async def test_no_changes_sync(file_sync_service, docs_dir, sample_files):
|
||||
"""Test sync when no changes are present."""
|
||||
# First sync to create initial state
|
||||
await file_sync_service.sync(docs_dir)
|
||||
|
||||
|
||||
# Sync again immediately
|
||||
changes = await file_sync_service.sync(docs_dir)
|
||||
|
||||
|
||||
# Should detect no changes
|
||||
assert changes.total_changes == 0
|
||||
|
||||
@@ -168,6 +173,9 @@ async def test_error_on_unreadable_file(file_sync_service, docs_dir):
|
||||
bad_file = docs_dir / "bad.md"
|
||||
bad_file.write_text("test")
|
||||
bad_file.chmod(0o000) # Remove all permissions
|
||||
|
||||
|
||||
with pytest.raises(SyncError):
|
||||
await file_sync_service.sync(docs_dir)
|
||||
|
||||
# Clean up
|
||||
bad_file.chmod(0o666) # Make readable/writable for cleanup
|
||||
Reference in New Issue
Block a user