""" Tests for Issue #13: Cache Management CLI Commands - cache-info functionality. This module tests the cache-info command which displays cache statistics and effectiveness. The cache-info command should provide detailed metrics including hit rate, memory usage, file count, and performance monitoring data. """ import json import os import tempfile from pathlib import Path from unittest.mock import patch, MagicMock import pytest from click.testing import CliRunner from markitect.cli import cli from markitect.ast_cache import ASTCache from markitect.database import DatabaseManager class TestCacheInfoCommand: """Test suite for cache-info command functionality.""" def setup_method(self): """Set up test environment for each test.""" self.runner = CliRunner() self.temp_dir = tempfile.mkdtemp() self.cache_dir = Path(self.temp_dir) / ".ast_cache" self.db_path = Path(self.temp_dir) / "test.db" # Create test markdown file self.test_file = Path(self.temp_dir) / "test.md" self.test_file.write_text("""--- title: Test Document author: Test Author --- # Test Heading This is a test document with some content. ## Section 1 Content for section 1. ## Section 2 More content here. """) def teardown_method(self): """Clean up after each test.""" import shutil if Path(self.temp_dir).exists(): shutil.rmtree(self.temp_dir) def test_cache_info_command_exists(self): """Test that cache-info command is available in CLI.""" # This test will initially fail until command is implemented result = self.runner.invoke(cli, ['cache-info']) # Should not return "No such command" error assert "No such command" not in result.output assert result.exit_code in [0, 1] # 0 for success, 1 for expected errors def test_cache_info_displays_basic_statistics(self): """Test that cache-info displays basic cache statistics.""" # Setup: Create cache with some files cache = ASTCache(self.cache_dir) cache.cache_file(self.test_file) # Execute command with patch('markitect.cli.Path') as mock_path: mock_path.return_value = self.cache_dir result = self.runner.invoke(cli, ['cache-info']) # Should show cache statistics assert result.exit_code == 0 assert "Cache Directory:" in result.output assert "Total Files:" in result.output assert "Cache Size:" in result.output def test_cache_info_shows_file_count(self): """Test that cache-info correctly reports number of cached files.""" # Setup: Create multiple cached files cache = ASTCache(self.cache_dir) # Create additional test files test_file2 = Path(self.temp_dir) / "test2.md" test_file2.write_text("# Another Test\n\nContent here.") cache.cache_file(self.test_file) cache.cache_file(test_file2) # Execute command - mock CacheDirectoryService to return our test cache stats with patch('markitect.cli.CacheDirectoryService') as mock_cache_service: mock_service_instance = MagicMock() mock_service_instance.get_cache_stats.return_value = { 'directory': str(self.cache_dir), 'total_files': 2, 'size_formatted': '1.2 KB' } mock_cache_service.return_value = mock_service_instance result = self.runner.invoke(cli, ['cache-info']) assert result.exit_code == 0 assert "Total Files: 2" in result.output def test_cache_info_shows_memory_usage(self): """Test that cache-info displays memory usage information.""" # Setup: Create cache with content cache = ASTCache(self.cache_dir) cache.cache_file(self.test_file) # Execute command with patch('markitect.cli.Path') as mock_path: mock_path.return_value = self.cache_dir result = self.runner.invoke(cli, ['cache-info']) assert result.exit_code == 0 # Should show memory/size information assert any(keyword in result.output.lower() for keyword in ["size", "memory", "bytes", "kb", "mb"]) def test_cache_info_with_empty_cache(self): """Test cache-info behavior with empty cache directory.""" # Ensure cache directory exists but is empty self.cache_dir.mkdir(exist_ok=True) # Execute command with patch('markitect.cli.Path') as mock_path: mock_path.return_value = self.cache_dir result = self.runner.invoke(cli, ['cache-info']) assert result.exit_code == 0 assert "Total Files: 0" in result.output or "empty" in result.output.lower() def test_cache_info_with_nonexistent_cache(self): """Test cache-info behavior when cache directory doesn't exist.""" # Use non-existent cache directory nonexistent_dir = Path(self.temp_dir) / "nonexistent_cache" # Execute command with patch('markitect.cli.Path') as mock_path: mock_path.return_value = nonexistent_dir result = self.runner.invoke(cli, ['cache-info']) # Should handle gracefully, either create directory or show appropriate message assert result.exit_code in [0, 1] assert "error" in result.output.lower() or "not found" in result.output.lower() or "0" in result.output def test_cache_info_output_format(self): """Test that cache-info output is well-formatted and readable.""" # Setup: Create cache with content cache = ASTCache(self.cache_dir) cache.cache_file(self.test_file) # Execute command with patch('markitect.cli.Path') as mock_path: mock_path.return_value = self.cache_dir result = self.runner.invoke(cli, ['cache-info']) assert result.exit_code == 0 # Should have structured output with clear labels lines = result.output.strip().split('\n') assert len(lines) >= 3 # Should have multiple lines of info # Should contain key information output_lower = result.output.lower() assert "cache" in output_lower assert any(char in result.output for char in [':']) # Should have label:value format def test_cache_info_performance_metrics(self): """Test that cache-info includes performance-related metrics.""" # Setup: Create cache and simulate usage cache = ASTCache(self.cache_dir) cache.cache_file(self.test_file) # Load cached AST to simulate cache hit cache.load_cached_ast(self.test_file) # Execute command with patch('markitect.cli.Path') as mock_path: mock_path.return_value = self.cache_dir result = self.runner.invoke(cli, ['cache-info']) assert result.exit_code == 0 # Should include performance-related information # This might include cache effectiveness, file ages, etc. assert len(result.output.strip()) > 50 # Should be substantial output def test_cache_info_with_verbose_flag(self): """Test cache-info with verbose flag showing detailed information.""" # Setup: Create cache with content cache = ASTCache(self.cache_dir) cache.cache_file(self.test_file) # Execute command with verbose flag with patch('markitect.cli.Path') as mock_path: mock_path.return_value = self.cache_dir result = self.runner.invoke(cli, ['--verbose', 'cache-info']) # Verbose mode might show more detailed information # For now, just ensure command works assert result.exit_code in [0, 1]