Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,11 @@ jobs:
cd rust && cargo clippy -- -D warnings

# Critical test suite (parallel matrix)
# Push to main: runs on lab self-hosted runners (consistent perf, free minutes)
# PRs: runs on GitHub-hosted runners (untrusted code never touches lab infra)
test-critical:
name: Tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
runs-on: ${{ github.event_name == 'push' && 'cachekit' || 'ubuntu-latest' }}
timeout-minutes: 15
permissions:
contents: read
Expand Down
14 changes: 8 additions & 6 deletions tests/unit/test_consolidated_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
Requirements: 5.1, 5.2, 5.3
"""

from __future__ import annotations

import asyncio
import time
from unittest.mock import patch
Expand All @@ -32,11 +34,11 @@ def test_all_feature_combinations_sync(

# Use intent-based presets instead of individual feature flags
if use_preset == "minimal":
decorator = cache.minimal(ttl=300, namespace="feature_test")
decorator = cache.minimal(ttl=300, namespace="feature_test_minimal")
elif use_preset == "production":
decorator = cache.production(ttl=300, namespace="feature_test")
decorator = cache.production(ttl=300, namespace="feature_test_production")
else:
decorator = cache(ttl=300, namespace="feature_test")
decorator = cache(ttl=300, namespace="feature_test_default")

@decorator
def test_function(x: int) -> str:
Expand Down Expand Up @@ -95,11 +97,11 @@ async def test_all_feature_combinations_async(

# Use intent-based presets instead of individual feature flags
if use_preset == "minimal":
decorator = cache.minimal(ttl=300, namespace="async_feature_test")
decorator = cache.minimal(ttl=300, namespace="async_feature_test_minimal")
elif use_preset == "production":
decorator = cache.production(ttl=300, namespace="async_feature_test")
decorator = cache.production(ttl=300, namespace="async_feature_test_production")
else:
decorator = cache(ttl=300, namespace="async_feature_test")
decorator = cache(ttl=300, namespace="async_feature_test_default")

@decorator
async def async_test_function(x: int) -> str:
Expand Down
38 changes: 28 additions & 10 deletions tests/unit/test_key_generator_blake2b.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,36 @@ def test_func(data):
# Should complete within reasonable time
assert blake2b_time < 1.0

def test_blake2b_with_numpy_arrays_raises_type_error(self):
"""Test that NumPy arrays raise TypeError (fail fast)."""
def test_blake2b_with_numpy_arrays_supported(self):
"""Test that 1D NumPy arrays with supported dtypes generate valid keys."""

def test_func(arr):
return arr.sum()

arr = np.arange(1000)
arr = np.arange(1000) # 1D, int64, well under 100KB
gen = CacheKeyGenerator()

# Should raise TypeError for unsupported type
with pytest.raises(TypeError, match="Unsupported type for cache key generation"):
gen.generate_key(test_func, (arr,), {})
# Constrained numpy arrays are now supported (round-table review 2025-12-18)
key = gen.generate_key(test_func, (arr,), {})
assert isinstance(key, str)
assert len(key) > 0

# Deterministic
key2 = gen.generate_key(test_func, (arr,), {})
assert key == key2

def test_blake2b_with_unsupported_numpy_arrays_raises(self):
"""Test that numpy arrays violating constraints raise TypeError."""

def test_func(arr):
return arr.sum()

gen = CacheKeyGenerator()

# 2D array — not supported
arr_2d = np.arange(100).reshape(10, 10)
with pytest.raises(TypeError, match="Only 1D arrays supported"):
gen.generate_key(test_func, (arr_2d,), {})

def test_blake2b_with_custom_objects(self):
"""Test Blake2b with basic objects that can be pickled."""
Expand Down Expand Up @@ -223,14 +241,14 @@ def test_unsupported_types_raise_type_error(self):
def test_func(data):
return data

# Test datetime
# Test naive datetime (rejected for timezone ambiguity)
import datetime

with pytest.raises(TypeError, match="Unsupported type"):
with pytest.raises(TypeError, match="Naive datetime not allowed"):
gen.generate_key(test_func, (datetime.datetime.now(),), {})

# Test set
with pytest.raises(TypeError, match="Unsupported type"):
# Test set (rejected for non-deterministic sorting)
with pytest.raises(TypeError, match="set/frozenset not supported"):
gen.generate_key(test_func, ({1, 2, 3},), {})

# Test custom class
Expand Down
Loading