mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
chore: move ccw-skill-hub to standalone repository
Migrated ccw-skill-hub to D:/ccw-skill-hub as independent git project. Removed nested git repos (ccw/frontend/ccw-skill-hub, skill-hub-repo, skill-hub-temp).
This commit is contained in:
278
codex-lens/tests/conftest.py
Normal file
278
codex-lens/tests/conftest.py
Normal file
@@ -0,0 +1,278 @@
|
||||
"""Pytest configuration and shared fixtures for codex-lens tests.
|
||||
|
||||
This module provides common fixtures and test utilities to reduce code duplication
|
||||
across the test suite. Using fixtures ensures consistent test setup and makes tests
|
||||
more maintainable.
|
||||
|
||||
Common Fixtures:
|
||||
- temp_dir: Temporary directory for test files
|
||||
- sample_index_db: Sample index database with test data
|
||||
- mock_config: Mock configuration object
|
||||
- sample_code_files: Factory for creating sample code files
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import tempfile
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any
|
||||
import sqlite3
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def temp_dir():
|
||||
"""Create a temporary directory for test files.
|
||||
|
||||
The directory is automatically cleaned up after the test.
|
||||
|
||||
Yields:
|
||||
Path: Path to the temporary directory.
|
||||
"""
|
||||
temp_path = Path(tempfile.mkdtemp())
|
||||
yield temp_path
|
||||
# Cleanup
|
||||
if temp_path.exists():
|
||||
shutil.rmtree(temp_path)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_index_db(temp_dir):
|
||||
"""Create a sample index database with test data.
|
||||
|
||||
The database has a basic schema with files and chunks tables
|
||||
populated with sample data.
|
||||
|
||||
Args:
|
||||
temp_dir: Temporary directory fixture.
|
||||
|
||||
Yields:
|
||||
Path: Path to the sample index database.
|
||||
"""
|
||||
db_path = temp_dir / "_index.db"
|
||||
|
||||
# Create database with basic schema
|
||||
conn = sqlite3.connect(db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Files table
|
||||
cursor.execute("""
|
||||
CREATE TABLE files (
|
||||
id INTEGER PRIMARY KEY,
|
||||
path TEXT NOT NULL UNIQUE,
|
||||
content TEXT,
|
||||
language TEXT,
|
||||
hash TEXT,
|
||||
indexed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""")
|
||||
|
||||
# Insert sample files
|
||||
sample_files = [
|
||||
("test.py", "def hello():\n print('world')", "python", "hash1"),
|
||||
("test.js", "function hello() { console.log('world'); }", "javascript", "hash2"),
|
||||
("README.md", "# Test Project", "markdown", "hash3"),
|
||||
]
|
||||
cursor.executemany(
|
||||
"INSERT INTO files (path, content, language, hash) VALUES (?, ?, ?, ?)",
|
||||
sample_files
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
yield db_path
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config():
|
||||
"""Create a mock configuration object with default values.
|
||||
|
||||
Returns:
|
||||
Mock: Mock object with common config attributes.
|
||||
"""
|
||||
from unittest.mock import Mock
|
||||
|
||||
config = Mock()
|
||||
config.index_path = Path("/tmp/test_index")
|
||||
config.chunk_size = 2000
|
||||
config.overlap = 200
|
||||
config.embedding_backend = "fastembed"
|
||||
config.embedding_model = "code"
|
||||
config.max_results = 10
|
||||
|
||||
return config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_code_factory(temp_dir):
|
||||
"""Factory for creating sample code files.
|
||||
|
||||
Args:
|
||||
temp_dir: Temporary directory fixture.
|
||||
|
||||
Returns:
|
||||
callable: Function that creates sample code files.
|
||||
"""
|
||||
def _create_file(filename: str, content: str, language: str = "python") -> Path:
|
||||
"""Create a sample code file.
|
||||
|
||||
Args:
|
||||
filename: Name of the file to create.
|
||||
content: Content of the file.
|
||||
language: Programming language (default: python).
|
||||
|
||||
Returns:
|
||||
Path: Path to the created file.
|
||||
"""
|
||||
file_path = temp_dir / filename
|
||||
file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
file_path.write_text(content)
|
||||
return file_path
|
||||
|
||||
return _create_file
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_python_code():
|
||||
"""Sample Python code for testing.
|
||||
|
||||
Returns:
|
||||
str: Sample Python code snippet.
|
||||
"""
|
||||
return '''
|
||||
def calculate_sum(a: int, b: int) -> int:
|
||||
"""Calculate the sum of two integers."""
|
||||
return a + b
|
||||
|
||||
class Calculator:
|
||||
"""A simple calculator class."""
|
||||
|
||||
def __init__(self):
|
||||
self.value = 0
|
||||
|
||||
def add(self, x: int) -> None:
|
||||
"""Add a value to the calculator."""
|
||||
self.value += x
|
||||
|
||||
if __name__ == "__main__":
|
||||
calc = Calculator()
|
||||
calc.add(5)
|
||||
print(f"Result: {calc.value}")
|
||||
'''
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_javascript_code():
|
||||
"""Sample JavaScript code for testing.
|
||||
|
||||
Returns:
|
||||
str: Sample JavaScript code snippet.
|
||||
"""
|
||||
return '''
|
||||
// Simple utility functions
|
||||
function add(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
const Calculator = class {
|
||||
constructor() {
|
||||
this.value = 0;
|
||||
}
|
||||
|
||||
add(x) {
|
||||
this.value += x;
|
||||
}
|
||||
};
|
||||
|
||||
// Example usage
|
||||
const calc = new Calculator();
|
||||
calc.add(5);
|
||||
console.log(`Result: ${calc.value}`);
|
||||
'''
|
||||
|
||||
|
||||
class CodeSampleFactory:
|
||||
"""Factory class for generating various code samples.
|
||||
|
||||
This class provides methods to generate code samples in different
|
||||
languages with various patterns (classes, functions, imports, etc.).
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def python_function(name: str = "example", docstring: bool = True) -> str:
|
||||
"""Generate a Python function sample.
|
||||
|
||||
Args:
|
||||
name: Function name.
|
||||
docstring: Whether to include docstring.
|
||||
|
||||
Returns:
|
||||
str: Python function code.
|
||||
"""
|
||||
doc = f' """Example function."""\n' if docstring else ''
|
||||
return f'''
|
||||
def {name}(param1: str, param2: int = 10) -> str:
|
||||
{doc} return param1 * param2
|
||||
'''.strip()
|
||||
|
||||
@staticmethod
|
||||
def python_class(name: str = "Example") -> str:
|
||||
"""Generate a Python class sample.
|
||||
|
||||
Args:
|
||||
name: Class name.
|
||||
|
||||
Returns:
|
||||
str: Python class code.
|
||||
"""
|
||||
return f'''
|
||||
class {name}:
|
||||
"""Example class."""
|
||||
|
||||
def __init__(self, value: int = 0):
|
||||
self.value = value
|
||||
|
||||
def increment(self) -> None:
|
||||
"""Increment the value."""
|
||||
self.value += 1
|
||||
'''.strip()
|
||||
|
||||
@staticmethod
|
||||
def javascript_function(name: str = "example") -> str:
|
||||
"""Generate a JavaScript function sample.
|
||||
|
||||
Args:
|
||||
name: Function name.
|
||||
|
||||
Returns:
|
||||
str: JavaScript function code.
|
||||
"""
|
||||
return f'''function {name}(param1, param2 = 10) {{
|
||||
return param1 * param2;
|
||||
}}'''.strip()
|
||||
|
||||
@staticmethod
|
||||
def typescript_interface(name: str = "Example") -> str:
|
||||
"""Generate a TypeScript interface sample.
|
||||
|
||||
Args:
|
||||
name: Interface name.
|
||||
|
||||
Returns:
|
||||
str: TypeScript interface code.
|
||||
"""
|
||||
return f'''interface {name} {{
|
||||
id: number;
|
||||
name: string;
|
||||
getValue(): number;
|
||||
}}'''.strip()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def code_sample_factory():
|
||||
"""Create a code sample factory instance.
|
||||
|
||||
Returns:
|
||||
CodeSampleFactory: Factory for generating code samples.
|
||||
"""
|
||||
return CodeSampleFactory()
|
||||
101
codex-lens/tests/lsp/test_lsp_edge_cases.py
Normal file
101
codex-lens/tests/lsp/test_lsp_edge_cases.py
Normal file
@@ -0,0 +1,101 @@
|
||||
"""LSP Edge Case Tests.
|
||||
|
||||
This module tests edge cases and error conditions in LSP (Language Server Protocol)
|
||||
operations, including timeout handling, protocol errors, and connection failures.
|
||||
|
||||
Test Coverage:
|
||||
- Timeout scenarios for LSP operations
|
||||
- Protocol errors and malformed responses
|
||||
- Connection failures and recovery
|
||||
- Concurrent request handling
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
import time
|
||||
|
||||
|
||||
class TestLSPTimeouts:
|
||||
"""Test timeout handling in LSP operations."""
|
||||
|
||||
def test_hover_request_timeout(self):
|
||||
"""Test that hover requests timeout appropriately after configured duration."""
|
||||
# This is a placeholder for actual timeout testing
|
||||
# Implementation requires mocking LSP client with delayed response
|
||||
pytest.skip("Requires LSP server fixture setup")
|
||||
|
||||
def test_definition_request_timeout(self):
|
||||
"""Test that go-to-definition requests timeout appropriately."""
|
||||
pytest.skip("Requires LSP server fixture setup")
|
||||
|
||||
def test_references_request_timeout(self):
|
||||
"""Test that find-references requests timeout appropriately."""
|
||||
pytest.skip("Requires LSP server fixture setup")
|
||||
|
||||
def test_concurrent_requests_with_timeout(self):
|
||||
"""Test behavior when multiple requests exceed timeout threshold."""
|
||||
pytest.skip("Requires LSP server fixture setup")
|
||||
|
||||
|
||||
class TestLSPProtocolErrors:
|
||||
"""Test handling of LSP protocol errors."""
|
||||
|
||||
def test_malformed_json_response(self):
|
||||
"""Test handling of malformed JSON in LSP responses."""
|
||||
pytest.skip("Requires LSP client fixture")
|
||||
|
||||
def test_invalid_method_error(self):
|
||||
"""Test handling of unknown/invalid method calls."""
|
||||
pytest.skip("Requires LSP client fixture")
|
||||
|
||||
def test_missing_required_params(self):
|
||||
"""Test handling of responses with missing required parameters."""
|
||||
pytest.skip("Requires LSP client fixture")
|
||||
|
||||
def test_null_result_handling(self):
|
||||
"""Test that null results from LSP are handled gracefully."""
|
||||
pytest.skip("Requires LSP client fixture")
|
||||
|
||||
|
||||
class TestLSPConnectionFailures:
|
||||
"""Test LSP connection failure scenarios."""
|
||||
|
||||
def test_server_not_found(self):
|
||||
"""Test behavior when LSP server is not available."""
|
||||
pytest.skip("Requires LSP client fixture")
|
||||
|
||||
def test_connection_dropped_mid_request(self):
|
||||
"""Test handling of dropped connections during active requests."""
|
||||
pytest.skip("Requires LSP client fixture")
|
||||
|
||||
def test_connection_retry_logic(self):
|
||||
"""Test that connection retry logic works as expected."""
|
||||
pytest.skip("Requires LSP client fixture")
|
||||
|
||||
def test_server_startup_failure(self):
|
||||
"""Test handling of LSP server startup failures."""
|
||||
pytest.skip("Requires LSP server fixture")
|
||||
|
||||
|
||||
class TestLSPResourceLimits:
|
||||
"""Test LSP behavior under resource constraints."""
|
||||
|
||||
def test_large_file_handling(self):
|
||||
"""Test LSP operations on very large source files."""
|
||||
pytest.skip("Requires test file fixtures")
|
||||
|
||||
def test_memory_pressure(self):
|
||||
"""Test LSP behavior under memory pressure."""
|
||||
pytest.skip("Requires memory simulation")
|
||||
|
||||
def test_concurrent_request_limits(self):
|
||||
"""Test handling of too many concurrent LSP requests."""
|
||||
pytest.skip("Requires LSP client fixture")
|
||||
|
||||
|
||||
# TODO: Implement actual tests using pytest fixtures and LSP mock objects
|
||||
# The test infrastructure needs to be set up with:
|
||||
# - LSP server fixture (maybe using pygls test server)
|
||||
# - LSP client fixture with configurable delays/errors
|
||||
# - Test file fixtures with various code patterns
|
||||
125
codex-lens/tests/test_incremental_indexer.py
Normal file
125
codex-lens/tests/test_incremental_indexer.py
Normal file
@@ -0,0 +1,125 @@
|
||||
"""Incremental Indexer File Event Processing Tests.
|
||||
|
||||
This module tests the file event processing in the incremental indexer,
|
||||
covering all file system event types (CREATED, MODIFIED, DELETED, MOVED).
|
||||
|
||||
Test Coverage:
|
||||
- CREATED events: New files being indexed
|
||||
- MODIFIED events: Changed files being re-indexed
|
||||
- DELETED events: Removed files being handled
|
||||
- MOVED events: File renames being tracked
|
||||
- Batch processing of multiple events
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
|
||||
class TestCreatedEvents:
|
||||
"""Test handling of CREATED file events."""
|
||||
|
||||
def test_new_file_indexed(self):
|
||||
"""Test that newly created files are properly indexed."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_created_in_subdirectory(self):
|
||||
"""Test that files created in subdirectories are indexed."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_batch_created_events(self):
|
||||
"""Test handling multiple files created simultaneously."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
|
||||
class TestModifiedEvents:
|
||||
"""Test handling of MODIFIED file events."""
|
||||
|
||||
def test_file_content_updated(self):
|
||||
"""Test that file content changes trigger re-indexing."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_metadata_only_change(self):
|
||||
"""Test handling of metadata-only changes (permissions, etc)."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_rapid_modifications(self):
|
||||
"""Test handling of rapid successive modifications to same file."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
|
||||
class TestDeletedEvents:
|
||||
"""Test handling of DELETED file events."""
|
||||
|
||||
def test_file_removed_from_index(self):
|
||||
"""Test that deleted files are removed from the index."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_directory_deleted(self):
|
||||
"""Test handling of directory deletion events."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_delete_non_indexed_file(self):
|
||||
"""Test handling deletion of files that were never indexed."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
|
||||
class TestMovedEvents:
|
||||
"""Test handling of MOVED/RENAMED file events."""
|
||||
|
||||
def test_file_renamed(self):
|
||||
"""Test that renamed files are tracked in the index."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_file_moved_to_subdirectory(self):
|
||||
"""Test that files moved to subdirectories are tracked."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_file_moved_out_of_watch_root(self):
|
||||
"""Test handling of files moved outside the watch directory."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_directory_renamed(self):
|
||||
"""Test handling of directory rename events."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
|
||||
class TestEventBatching:
|
||||
"""Test batching and deduplication of file events."""
|
||||
|
||||
def test_duplicate_events_deduplicated(self):
|
||||
"""Test that duplicate events for the same file are deduplicated."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_event_ordering_preserved(self):
|
||||
"""Test that events are processed in the correct order."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_mixed_event_types_batch(self):
|
||||
"""Test handling a batch with mixed event types."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
|
||||
class TestErrorHandling:
|
||||
"""Test error handling in file event processing."""
|
||||
|
||||
def test_unreadable_file_skipped(self):
|
||||
"""Test that unreadable files are handled gracefully."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_corrupted_event_continues(self):
|
||||
"""Test that processing continues after a corrupted event."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
def test_indexer_error_recovery(self):
|
||||
"""Test recovery from indexer errors during event processing."""
|
||||
pytest.skip("Requires incremental indexer fixture")
|
||||
|
||||
|
||||
# TODO: Implement actual tests using pytest fixtures and the incremental indexer
|
||||
# The test infrastructure needs:
|
||||
# - IncrementalIndexer fixture with mock filesystem watcher
|
||||
# - Temporary directory fixtures for test files
|
||||
# - Mock event queue for controlled event injection
|
||||
114
codex-lens/tests/test_migrations.py
Normal file
114
codex-lens/tests/test_migrations.py
Normal file
@@ -0,0 +1,114 @@
|
||||
"""Database Migration Tests.
|
||||
|
||||
This module tests the database migration system for the codex-lens index,
|
||||
ensuring that forward and backward compatibility is maintained across schema versions.
|
||||
|
||||
Test Coverage:
|
||||
- Forward migrations: Old schema to new schema
|
||||
- Backward compatibility: New code can read old schemas
|
||||
- Migration rollback capabilities
|
||||
- Data integrity during migrations
|
||||
- Edge cases (empty databases, corrupted data, etc.)
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import json
|
||||
|
||||
|
||||
class TestForwardMigrations:
|
||||
"""Test upgrading from older schema versions to newer ones."""
|
||||
|
||||
def test_v0_to_v1_migration(self):
|
||||
"""Test migration from schema v0 to v1."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
def test_v1_to_v2_migration(self):
|
||||
"""Test migration from schema v1 to v2."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
def test_migration_preserves_data(self):
|
||||
"""Test that migration preserves existing data."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
def test_migration_adds_new_columns(self):
|
||||
"""Test that new columns are added with correct defaults."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
|
||||
class TestBackwardCompatibility:
|
||||
"""Test that newer code can read and work with older database schemas."""
|
||||
|
||||
def test_new_code_reads_old_schema(self):
|
||||
"""Test that current code can read old schema databases."""
|
||||
pytest.skip("Requires old schema fixture")
|
||||
|
||||
def test_new_code_writes_to_old_schema(self):
|
||||
"""Test that current code handles writes to old schema gracefully."""
|
||||
pytest.skip("Requires old schema fixture")
|
||||
|
||||
def test_old_code_rejects_new_schema(self):
|
||||
"""Test that old code fails appropriately on new schemas."""
|
||||
pytest.skip("Requires old code fixture")
|
||||
|
||||
|
||||
class TestMigrationRollback:
|
||||
"""Test rollback capabilities for failed migrations."""
|
||||
|
||||
def test_failed_migration_rolls_back(self):
|
||||
"""Test that failed migrations are rolled back completely."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
def test_partial_migration_recovery(self):
|
||||
"""Test recovery from partially completed migrations."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
def test_rollback_preserves_original_data(self):
|
||||
"""Test that rollback restores original state."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
|
||||
class TestMigrationEdgeCases:
|
||||
"""Test migration behavior in edge cases."""
|
||||
|
||||
def test_empty_database_migration(self):
|
||||
"""Test migration of an empty database."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
def test_large_database_migration(self):
|
||||
"""Test migration of a large database."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
def test_corrupted_database_handling(self):
|
||||
"""Test handling of corrupted databases during migration."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
def test_concurrent_migration_protection(self):
|
||||
"""Test that concurrent migrations are prevented."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
|
||||
class TestSchemaVersionTracking:
|
||||
"""Test schema version tracking and detection."""
|
||||
|
||||
def test_version_table_exists(self):
|
||||
"""Test that version tracking table exists and is populated."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
def test_version_auto_detection(self):
|
||||
"""Test that schema version is auto-detected from database."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
def test_version_update_after_migration(self):
|
||||
"""Test that version is updated correctly after migration."""
|
||||
pytest.skip("Requires migration infrastructure setup")
|
||||
|
||||
|
||||
# TODO: Implement actual tests using pytest fixtures
|
||||
# The test infrastructure needs:
|
||||
# - Migration runner fixture that can apply and rollback migrations
|
||||
# - Old schema fixtures (pre-built databases with known schemas)
|
||||
# - Temporary database fixtures for isolated testing
|
||||
# - Mock data generators for various schema versions
|
||||
Reference in New Issue
Block a user