"""Stress tests for the watch service file change handling. Verifies that the watcher handles large batches of file operations correctly and maintains state consistency under load. """ from pathlib import Path import pytest from watchfiles import Change async def create_test_file(path: Path, content: str = "test content") -> None: """Create a test file with given content.""" path.parent.mkdir(parents=True, exist_ok=True) path.write_text(content) @pytest.mark.asyncio async def test_handle_large_batch_of_file_adds( watch_service, project_config, test_project, entity_repository ): """Watcher handles 50+ file creations in a single batch.""" project_dir = project_config.home file_count = 50 # Create all files changes = set() for i in range(file_count): path = project_dir / f"batch_note_{i:03d}.md" content = f"""--- type: knowledge --- # Batch Note {i} Content for batch note {i} with unique text. """ await create_test_file(path, content) changes.add((Change.added, str(path))) # Handle all changes in one batch await watch_service.handle_changes(test_project, changes) # Verify all files were synced synced_count = 0 for i in range(file_count): entity = await entity_repository.get_by_file_path(f"batch_note_{i:03d}.md") if entity is not None: synced_count += 1 assert synced_count == file_count, f"Only {synced_count}/{file_count} files synced" @pytest.mark.asyncio async def test_handle_mixed_operations_batch( watch_service, project_config, sync_service, test_project, entity_repository ): """Watcher handles mixed add/modify/delete operations in one batch.""" project_dir = project_config.home # Phase 1: Create initial files via the sync pipeline initial_files = [] for i in range(10): path = project_dir / f"mixed_note_{i:03d}.md" content = f"""--- type: knowledge --- # Mixed Note {i} Initial content for note {i}. """ await create_test_file(path, content) initial_files.append(path) # Sync initial files initial_changes = {(Change.added, str(p)) for p in initial_files} await watch_service.handle_changes(test_project, initial_changes) # Phase 2: Mixed operations — modify some, delete some, add new ones mixed_changes = set() # Modify first 3 files for i in range(3): path = initial_files[i] path.write_text(f"""--- type: knowledge --- # Mixed Note {i} MODIFIED content for note {i}. """) mixed_changes.add((Change.modified, str(path))) # Delete next 3 files for i in range(3, 6): path = initial_files[i] path.unlink() mixed_changes.add((Change.deleted, str(path))) # Add 5 new files for i in range(10, 15): path = project_dir / f"mixed_note_{i:03d}.md" content = f"""--- type: knowledge --- # Mixed Note {i} New content for note {i}. """ await create_test_file(path, content) mixed_changes.add((Change.added, str(path))) await watch_service.handle_changes(test_project, mixed_changes) # Verify: modified files still exist with updated content for i in range(3): entity = await entity_repository.get_by_file_path(f"mixed_note_{i:03d}.md") assert entity is not None, f"Modified entity {i} should still exist" # Verify: deleted files are gone for i in range(3, 6): entity = await entity_repository.get_by_file_path(f"mixed_note_{i:03d}.md") assert entity is None, f"Deleted entity {i} should be gone" # Verify: new files were added for i in range(10, 15): entity = await entity_repository.get_by_file_path(f"mixed_note_{i:03d}.md") assert entity is not None, f"New entity {i} should exist" @pytest.mark.asyncio async def test_rapid_modifications_to_same_file( watch_service, project_config, test_project, entity_repository ): """Watcher handles multiple rapid changes to the same file.""" project_dir = project_config.home path = project_dir / "rapid_note.md" # Create initial file await create_test_file( path, """--- type: knowledge --- # Rapid Note Version 1. """, ) await watch_service.handle_changes(test_project, {(Change.added, str(path))}) # Rapidly modify the file multiple times, processing each change for version in range(2, 7): path.write_text(f"""--- type: knowledge --- # Rapid Note Version {version}. """) await watch_service.handle_changes(test_project, {(Change.modified, str(path))}) # The entity should exist and reflect the final state entity = await entity_repository.get_by_file_path("rapid_note.md") assert entity is not None assert entity.title == "rapid_note" # State should have recorded all events events = [e for e in watch_service.state.recent_events if "rapid_note" in e.path] assert len(events) >= 2 # At least the add and some modifications