Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

125 lines
4.8 KiB
Python

"""High-value tests for metrics/pricing module.
Covers gaps in PricingCache and CostCalculator not addressed by existing tests:
- Cache overwrite behavior, TTL-based expiration
- CostCalculator.calculate_cost_sync exact arithmetic and edge cases
"""
import pytest
from local_deep_research.metrics.pricing.pricing_cache import PricingCache
from local_deep_research.metrics.pricing.cost_calculator import CostCalculator
class TestPricingCacheOverwrite:
"""Test cache key overwrite behavior."""
def test_set_overwrites_existing_key_data(self):
"""Overwriting a key replaces the data."""
cache = PricingCache(cache_ttl=3600)
cache.set("k", {"old": True})
cache.set("k", {"new": True})
assert cache.get("k") == {"new": True}
def test_get_with_primitive_value_round_trips(self):
"""Non-dict values (strings) are preserved through set/get."""
cache = PricingCache(cache_ttl=3600)
cache.set("k", "hello")
assert cache.get("k") == "hello"
class TestPricingCacheTTLExpiration:
"""Test TTL-based expiration via cachetools.TTLCache."""
def test_zero_ttl_makes_every_entry_expired(self):
"""With cache_ttl=0, entries are immediately expired."""
cache = PricingCache(cache_ttl=0)
cache.set("k", "data")
# Give a tiny amount of time for clock to advance
assert cache.get("k") is None
def test_clear_then_stats_all_zeros(self):
"""After clear(), stats show zero entries."""
cache = PricingCache(cache_ttl=3600)
cache.set("a", 1)
cache.set("b", 2)
cache.clear()
stats = cache.get_cache_stats()
assert stats["total_entries"] == 0
class TestCostCalculatorSync:
"""Test CostCalculator.calculate_cost_sync."""
def test_unknown_model_returns_zero_cost(self):
"""Unknown model returns zero cost with error message."""
calc = CostCalculator()
result = calc.calculate_cost_sync("totally-unknown-model-xyz", 500, 500)
assert result["prompt_cost"] == 0.0
assert result["completion_cost"] == 0.0
assert result["total_cost"] == 0.0
assert result["pricing_used"] is None
assert "error" in result
def test_prompt_plus_completion_equals_total(self):
"""prompt_cost + completion_cost == total_cost for known models."""
calc = CostCalculator()
result = calc.calculate_cost_sync("gpt-4", 3000, 1500)
if result["pricing_used"] is not None:
assert (
abs(
(result["prompt_cost"] + result["completion_cost"])
- result["total_cost"]
)
< 1e-9
)
def test_zero_completion_tokens(self):
"""Zero completion tokens yields completion_cost == 0."""
calc = CostCalculator()
result = calc.calculate_cost_sync("gpt-4", 1000, 0)
if result["pricing_used"] is not None:
assert result["completion_cost"] == 0.0
assert result["total_cost"] == result["prompt_cost"]
def test_provider_prefixed_model_resolved(self):
"""Model with provider prefix (e.g. 'openai/gpt-4') is resolved."""
calc = CostCalculator()
result = calc.calculate_cost_sync("openai/gpt-4", 1000, 1000)
# Should find gpt-4 via the split("/")[-1] fallback
if result["pricing_used"] is not None:
assert result["total_cost"] > 0.0
def test_provider_prefix_unresolvable_returns_zero(self):
"""Unresolvable provider-prefixed model returns zero cost."""
calc = CostCalculator()
result = calc.calculate_cost_sync(
"fakeprovider/no-such-model", 500, 500
)
assert result["total_cost"] == 0.0
assert result["pricing_used"] is None
def test_cache_used_over_static_pricing(self):
"""Pre-seeded cache values are used instead of static pricing."""
calc = CostCalculator()
custom_pricing = {"prompt": 0.1, "completion": 0.2}
calc.cache.set_model_pricing("my-custom-model", custom_pricing)
result = calc.calculate_cost_sync("my-custom-model", 1000, 1000)
assert result["pricing_used"] == custom_pricing
assert result["prompt_cost"] == pytest.approx(0.1)
assert result["completion_cost"] == pytest.approx(0.2)
def test_success_result_has_expected_keys(self):
"""Successful result has exactly 4 keys (no error key)."""
calc = CostCalculator()
calc.cache.set_model_pricing(
"test-model", {"prompt": 0.01, "completion": 0.02}
)
result = calc.calculate_cost_sync("test-model", 100, 100)
assert set(result.keys()) == {
"prompt_cost",
"completion_cost",
"total_cost",
"pricing_used",
}