mirror of
https://github.com/goauthentik/authentik.git
synced 2026-06-17 19:09:11 +03:00
5839b40efa
Co-authored-by: Ryan Pesek <rpesek@cloudflare.com> Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
69 lines
3.0 KiB
Python
69 lines
3.0 KiB
Python
"""Tests for ``DatabaseCache.keys`` glob-to-SQL translation.
|
|
|
|
``cache.keys("prefix*")`` must use ``__startswith`` (LIKE), not the regex
|
|
path. Pure unit tests — ``CacheEntry.objects`` is mocked.
|
|
"""
|
|
|
|
from typing import Any, cast
|
|
from unittest import TestCase, mock
|
|
|
|
from django_postgres_cache.backend import DatabaseCache
|
|
|
|
|
|
def _make_cache() -> DatabaseCache:
|
|
"""Construct a ``DatabaseCache`` without Django settings or a real DB."""
|
|
cache = DatabaseCache.__new__(DatabaseCache)
|
|
cache.key_prefix = ""
|
|
cache.version = 1
|
|
cache.key_func = lambda key, key_prefix, version: f":{version}:{key}"
|
|
# Reverse-key is not invoked in these tests (filter mocks return []), so
|
|
# an identity function is enough.
|
|
cache.reverse_key_func = lambda k: k
|
|
return cache
|
|
|
|
|
|
class TestKeysGlobToLookup(TestCase):
|
|
"""The SQL lookup chosen for each glob pattern shape."""
|
|
|
|
def _captured_filter_kwargs(self, pattern: str) -> dict[str, Any]:
|
|
"""Run ``cache.keys(pattern)`` and return the kwargs passed to
|
|
``CacheEntry.objects.filter(...)``."""
|
|
cache = _make_cache()
|
|
with mock.patch("django_postgres_cache.backend.CacheEntry") as mock_entry:
|
|
mock_entry.objects.filter.return_value.values_list.return_value = []
|
|
cache.keys(pattern)
|
|
self.assertEqual(mock_entry.objects.filter.call_count, 1)
|
|
return cast(dict[str, Any], mock_entry.objects.filter.call_args.kwargs)
|
|
|
|
def test_simple_prefix_glob_uses_startswith(self) -> None:
|
|
"""``cache.keys("foo*")`` uses ``__startswith``, not ``__regex``."""
|
|
kwargs = self._captured_filter_kwargs("foo*")
|
|
self.assertIn("cache_key__startswith", kwargs)
|
|
self.assertNotIn("cache_key__regex", kwargs)
|
|
self.assertNotIn("cache_key", kwargs)
|
|
|
|
def test_realistic_authentik_prefix_glob_uses_startswith(self) -> None:
|
|
"""The actual hot-query pattern from the bug report uses ``__startswith``."""
|
|
kwargs = self._captured_filter_kwargs("goauthentik.io/policies/app_access/*")
|
|
self.assertIn("cache_key__startswith", kwargs)
|
|
self.assertNotIn("cache_key__regex", kwargs)
|
|
|
|
def test_exact_match_uses_equality(self) -> None:
|
|
"""No-wildcard patterns use primary-key equality."""
|
|
kwargs = self._captured_filter_kwargs("exact")
|
|
self.assertIn("cache_key", kwargs)
|
|
self.assertNotIn("cache_key__startswith", kwargs)
|
|
self.assertNotIn("cache_key__regex", kwargs)
|
|
|
|
def test_complex_glob_falls_back_to_regex(self) -> None:
|
|
"""Multiple wildcards or non-suffix wildcards fall back to ``__regex``."""
|
|
kwargs = self._captured_filter_kwargs("foo*bar*")
|
|
self.assertIn("cache_key__regex", kwargs)
|
|
self.assertNotIn("cache_key__startswith", kwargs)
|
|
|
|
def test_leading_wildcard_falls_back_to_regex(self) -> None:
|
|
"""A leading wildcard cannot reduce to LIKE — fall back to ``__regex``."""
|
|
kwargs = self._captured_filter_kwargs("*foo")
|
|
self.assertIn("cache_key__regex", kwargs)
|
|
self.assertNotIn("cache_key__startswith", kwargs)
|