Skip to main content
Glama
test_cache_consistency.py7.44 kB
""" Cache Consistency Tests Tests: - Cache invalidation scenarios - Stale cache detection - Concurrent cache access - Cache corruption recovery """ from __future__ import annotations import os import tempfile from pathlib import Path import pytest from spice_mcp.adapters.dune import cache as cache_module from spice_mcp.adapters.dune.extract import ExecuteKwargs, RetrievalKwargs from spice_mcp.adapters.dune.types import Execution def test_cache_invalidation_on_query_update(tmp_path): """Test that cache is invalidated when query changes.""" cache_dir = tmp_path / "cache" cache_dir.mkdir() execute_kwargs: ExecuteKwargs = { "query_id": 12345, "api_key": "test", "parameters": {"param1": "value1"}, "performance": "medium", } result_kwargs: RetrievalKwargs = { "limit": None, "offset": None, "sample_count": None, "sort_by": None, "columns": None, "extras": None, "types": None, "all_types": None, "verbose": False, } output_kwargs = { "cache_dir": str(cache_dir), "include_execution": False, } # Create initial execution execution1: Execution = { "execution_id": "exec-1", "timestamp": 1000, } # Modify parameters (should create different cache key) execute_kwargs2: ExecuteKwargs = { "query_id": 12345, "api_key": "test", "parameters": {"param1": "value2"}, # Different value "performance": "medium", } execution2: Execution = { "execution_id": "exec-2", "timestamp": 2000, } # Both should have different cache paths path1 = cache_module._build_cache_path(execution1, execute_kwargs, result_kwargs, str(cache_dir)) path2 = cache_module._build_cache_path(execution2, execute_kwargs2, result_kwargs, str(cache_dir)) assert path1 != path2, "Different parameters should create different cache paths" def test_stale_cache_detection(tmp_path): """Test detection of stale cache entries.""" cache_dir = tmp_path / "cache" cache_dir.mkdir() execute_kwargs: ExecuteKwargs = { "query_id": 12345, "api_key": "test", "parameters": None, "performance": "medium", } result_kwargs: RetrievalKwargs = { "limit": None, "offset": None, "sample_count": None, "sort_by": None, "columns": None, "extras": None, "types": None, "all_types": None, "verbose": False, } output_kwargs = { "cache_dir": str(cache_dir), "include_execution": False, } # Old execution timestamp old_execution: Execution = { "execution_id": "exec-old", "timestamp": 1000, # Old timestamp } # New execution timestamp new_execution: Execution = { "execution_id": "exec-new", "timestamp": 2000, # Newer timestamp } # Build cache paths old_path = cache_module._build_cache_path(old_execution, execute_kwargs, result_kwargs, str(cache_dir)) new_path = cache_module._build_cache_path(new_execution, execute_kwargs, result_kwargs, str(cache_dir)) # Paths should be different due to different timestamps assert old_path != new_path def test_cache_missing_handles_gracefully(tmp_path, monkeypatch): """Test that missing cache is handled gracefully.""" cache_dir = tmp_path / "cache" cache_dir.mkdir() execute_kwargs: ExecuteKwargs = { "query_id": 12345, "api_key": "test", "parameters": None, "performance": "medium", } result_kwargs: RetrievalKwargs = { "limit": None, "offset": None, "sample_count": None, "sort_by": None, "columns": None, "extras": None, "types": None, "all_types": None, "verbose": False, } output_kwargs = { "cache_dir": str(cache_dir), "include_execution": False, } # Mock get_latest_execution to return None (simulating no execution found) # This avoids making actual HTTP requests with invalid API keys from spice_mcp.adapters.dune import extract as extract_module monkeypatch.setattr(extract_module, "get_latest_execution", lambda *args, **kwargs: None) # Try to load from cache when it doesn't exist result, execution = cache_module.load_from_cache(execute_kwargs, result_kwargs, output_kwargs) # Should return None, None when cache doesn't exist assert result is None assert execution is None def test_cache_path_uniqueness(tmp_path): """Test that cache paths are unique for different inputs.""" cache_dir = tmp_path / "cache" cache_dir.mkdir() base_execute_kwargs: ExecuteKwargs = { "query_id": 12345, "api_key": "test", "parameters": None, "performance": "medium", } base_result_kwargs: RetrievalKwargs = { "limit": None, "offset": None, "sample_count": None, "sort_by": None, "columns": None, "extras": None, "types": None, "all_types": None, "verbose": False, } execution: Execution = { "execution_id": "exec-1", "timestamp": 1000, } # Test different limits create different paths result_kwargs1 = {**base_result_kwargs, "limit": 10} result_kwargs2 = {**base_result_kwargs, "limit": 20} path1 = cache_module._build_cache_path(execution, base_execute_kwargs, result_kwargs1, str(cache_dir)) path2 = cache_module._build_cache_path(execution, base_execute_kwargs, result_kwargs2, str(cache_dir)) assert path1 != path2, "Different limits should create different cache paths" # Test different offsets create different paths result_kwargs3 = {**base_result_kwargs, "offset": 0} result_kwargs4 = {**base_result_kwargs, "offset": 10} path3 = cache_module._build_cache_path(execution, base_execute_kwargs, result_kwargs3, str(cache_dir)) path4 = cache_module._build_cache_path(execution, base_execute_kwargs, result_kwargs4, str(cache_dir)) assert path3 != path4, "Different offsets should create different cache paths" def test_cache_directory_creation(tmp_path): """Test that cache directory is created if it doesn't exist.""" cache_dir = tmp_path / "nonexistent_cache" execute_kwargs: ExecuteKwargs = { "query_id": 12345, "api_key": "test", "parameters": None, "performance": "medium", } result_kwargs: RetrievalKwargs = { "limit": None, "offset": None, "sample_count": None, "sort_by": None, "columns": None, "extras": None, "types": None, "all_types": None, "verbose": False, } execution: Execution = { "execution_id": "exec-1", "timestamp": 1000, } # Build cache path (should not fail even if directory doesn't exist) try: path = cache_module._build_cache_path(execution, execute_kwargs, result_kwargs, str(cache_dir)) # Path should be valid assert path is not None assert str(cache_dir) in path except Exception as e: pytest.fail(f"Cache path building should not fail: {e}")

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Evan-Kim2028/spice-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server