Spaces:
Configuration error
Configuration error
Niranjan-Murugarasu024
feat: TradeSense AI Chairman Edition production release ready for Hugging Face Spaces
0125724 Download backend/tests/data/test_cache_integrity.py from BlueMen/tradesenseAi: direct link, hf CLI and curl.
- Browser
- Download file 6.71 kB
-
https://huggingface.co/spaces/BlueMen/tradesenseAi/resolve/main/backend/tests/data/test_cache_integrity.py
- Command line
-
hf download hf://spaces/BlueMen/tradesenseAi/backend/tests/data/test_cache_integrity.py
-
curl -L -o test_cache_integrity.py https://huggingface.co/spaces/BlueMen/tradesenseAi/resolve/main/backend/tests/data/test_cache_integrity.py
6.71 kB
| """ | |
| TradeSense AI — Market Data Cache Integrity Tests | |
| Tests cache hit/miss semantics, TTL expiry, temporal cutoff validation on retrieval, | |
| and confirms that API keys/secrets are NEVER cached in metadata. | |
| """ | |
| import time | |
| from datetime import date, datetime, timezone | |
| import pandas as pd | |
| import pytest | |
| from backend.config.settings import settings | |
| from backend.app.schemas.contracts import ( | |
| DatasetMetadata, | |
| DataQualityReport, | |
| DataQualityStatus, | |
| DataFreshness, | |
| CrossSourceAgreement, | |
| AdjustmentMethod, | |
| ) | |
| from backend.data.cache import MarketDataCache, CacheEntryMetadata | |
| def create_sample_df(ticker: str = "AAPL", days: int = 10, end_date: date = date(2024, 12, 31)) -> pd.DataFrame: | |
| dates = pd.bdate_range(end=end_date, periods=days).date | |
| return pd.DataFrame({ | |
| "session": dates, | |
| "Open": [150.0 + i for i in range(days)], | |
| "High": [155.0 + i for i in range(days)], | |
| "Low": [149.0 + i for i in range(days)], | |
| "Close": [153.0 + i for i in range(days)], | |
| "Volume": [1000000.0 for _ in range(days)], | |
| "VWAP": [152.0 + i for i in range(days)], | |
| }) | |
| def create_sample_metadata(ticker: str = "AAPL", cutoff: date = date(2024, 12, 31), count: int = 10) -> DatasetMetadata: | |
| return DatasetMetadata( | |
| dataset_version=f"ds_{ticker.lower()}_20241231_abc12345", | |
| snapshot_id=f"snap_{ticker.lower()}_123", | |
| ticker=ticker, | |
| source_primary="Polygon.io", | |
| source_secondary=None, | |
| fallback_used=False, | |
| retrieved_at=datetime.now(timezone.utc), | |
| start_session=date(2024, 1, 2), | |
| cutoff_session=cutoff, | |
| total_bars=count, | |
| splits_adjusted=True, | |
| dividends_adjusted=True, | |
| adjustment_method=AdjustmentMethod.PROVIDER_ADJUSTED, | |
| timezone="America/New_York", | |
| quality_report=DataQualityReport( | |
| quality_status=DataQualityStatus.VERIFIED, | |
| quality_score=95, | |
| source="Polygon.io", | |
| fallback_used=False, | |
| cross_source_agreement=CrossSourceAgreement.UNCHECKED, | |
| freshness=DataFreshness.LATEST_AVAILABLE, | |
| corporate_action_status="VALIDATED", | |
| calendar_status="VALIDATED", | |
| temporal_integrity="PASS", | |
| ohlc_invariants_passed=True, | |
| ), | |
| sha256_hash="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", | |
| ) | |
| class TestCacheIntegrity: | |
| def setup_method(self): | |
| self.cache = MarketDataCache() | |
| def test_cache_miss_on_empty_cache(self): | |
| result = self.cache.get("AAPL", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31)) | |
| assert result is None | |
| def test_cache_set_and_get_hit(self): | |
| df = create_sample_df("AAPL") | |
| meta = create_sample_metadata("AAPL") | |
| self.cache.set("AAPL", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31), df, meta) | |
| hit = self.cache.get("AAPL", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31)) | |
| assert hit is not None | |
| cached_df, cached_meta = hit | |
| assert len(cached_df) == len(df) | |
| assert cached_meta.ticker == "AAPL" | |
| assert cached_meta.sha256_hash == meta.sha256_hash | |
| def test_cache_miss_on_different_ticker(self): | |
| df = create_sample_df("AAPL") | |
| meta = create_sample_metadata("AAPL") | |
| self.cache.set("AAPL", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31), df, meta) | |
| hit = self.cache.get("MSFT", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31)) | |
| assert hit is None | |
| def test_cache_temporal_cutoff_enforcement(self): | |
| """A cache entry stored for cutoff T1 must NOT match a request for cutoff T2.""" | |
| df = create_sample_df("AAPL", end_date=date(2024, 6, 30)) | |
| meta = create_sample_metadata("AAPL", cutoff=date(2024, 6, 30)) | |
| self.cache.set("AAPL", date(2024, 1, 1), date(2024, 6, 30), date(2024, 6, 30), df, meta) | |
| # Requesting with different cutoff date must miss | |
| hit = self.cache.get("AAPL", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31)) | |
| assert hit is None | |
| def test_cache_expiry_enforcement(self): | |
| """Expired entries must return None and be evicted.""" | |
| df = create_sample_df("NVDA") | |
| meta = create_sample_metadata("NVDA") | |
| # Store with 0-second TTL (instant expiration) | |
| key = self.cache._build_key("NVDA", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31)) | |
| from backend.data.cache import CacheEntry | |
| self.cache._cache[key] = CacheEntry(df, meta, ttl_seconds=-1) | |
| hit = self.cache.get("NVDA", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31)) | |
| assert hit is None | |
| # Verify it was evicted from internal dict | |
| assert key not in self.cache._cache | |
| def test_cache_metadata_never_contains_credentials(self): | |
| """Safe dict export must contain only public audit fields and never secrets.""" | |
| df = create_sample_df("TSLA") | |
| meta = create_sample_metadata("TSLA") | |
| self.cache.set("TSLA", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31), df, meta) | |
| entry_meta = self.cache.get_entry_metadata( | |
| "TSLA", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31) | |
| ) | |
| assert entry_meta is not None | |
| assert "ticker" in entry_meta | |
| assert "lineage_hash" in entry_meta | |
| assert "provider" in entry_meta | |
| # Check no sensitive keys | |
| forbidden = ["api_key", "apiKey", "secret", "token", "password", "authorization"] | |
| for key in entry_meta: | |
| assert key.lower() not in forbidden | |
| val_str = str(entry_meta[key]).lower() | |
| for f in forbidden: | |
| assert f not in val_str | |
| def test_cache_invalidation_by_ticker(self): | |
| df = create_sample_df("AMZN") | |
| meta = create_sample_metadata("AMZN") | |
| self.cache.set("AMZN", date(2024, 1, 1), date(2024, 6, 30), date(2024, 6, 30), df, meta) | |
| self.cache.set("AMZN", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31), df, meta) | |
| evicted = self.cache.invalidate("AMZN") | |
| assert evicted == 2 | |
| assert self.cache.get("AMZN", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31)) is None | |
| def test_cache_stats_accuracy(self): | |
| self.cache.clear() | |
| df = create_sample_df("SPY") | |
| meta = create_sample_metadata("SPY") | |
| self.cache.set("SPY", date(2024, 1, 1), date(2024, 12, 31), date(2024, 12, 31), df, meta) | |
| stats = self.cache.stats() | |
| assert stats["total_entries"] == 1 | |
| assert stats["live_entries"] == 1 | |
| assert stats["expired_entries"] == 0 | |