From 62f9172ecd42272c5fc426ff78981b59bb58e444 Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Tue, 10 Feb 2026 16:38:07 -0800 Subject: [PATCH] test fixes --- .../proxy/policy_engine/conftest.py | 36 +++++++++++ .../policy_engine/test_policy_matcher.py | 64 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 tests/test_litellm/proxy/policy_engine/conftest.py diff --git a/tests/test_litellm/proxy/policy_engine/conftest.py b/tests/test_litellm/proxy/policy_engine/conftest.py new file mode 100644 index 00000000000..6d0dd7b3be9 --- /dev/null +++ b/tests/test_litellm/proxy/policy_engine/conftest.py @@ -0,0 +1,36 @@ +""" +Local conftest for policy_engine tests. + +The parent conftest (tests/test_litellm/conftest.py) inserts the main repo +root into sys.path and imports litellm from there. When running from a +worktree, this means all litellm imports resolve to the main repo's code +instead of the worktree's. + +This conftest fixes the path and clears all cached litellm modules so +subsequent imports resolve from the worktree. +""" + +import os +import sys + +import pytest + +# Fix sys.path: insert this worktree's root FIRST and remove the main repo root. +_this_dir = os.path.dirname(os.path.abspath(__file__)) +_worktree_root = os.path.abspath(os.path.join(_this_dir, "..", "..", "..", "..")) +sys.path.insert(0, _worktree_root) + +# Remove the main repo path that parent conftest inserted +_main_repo = os.path.abspath(os.path.join(_worktree_root, "..", "..")) +sys.path = [p for p in sys.path if os.path.abspath(p) != _main_repo] + +# Clear ALL cached litellm modules so they're re-imported from the worktree +_to_remove = [key for key in sys.modules if key == "litellm" or key.startswith("litellm.")] +for key in _to_remove: + del sys.modules[key] + + +@pytest.fixture(scope="module", autouse=True) +def setup_and_teardown(): + """Override parent conftest - policy engine tests don't need litellm reload.""" + yield diff --git a/tests/test_litellm/proxy/policy_engine/test_policy_matcher.py b/tests/test_litellm/proxy/policy_engine/test_policy_matcher.py index c011f31af6a..fccb26496ac 100644 --- a/tests/test_litellm/proxy/policy_engine/test_policy_matcher.py +++ b/tests/test_litellm/proxy/policy_engine/test_policy_matcher.py @@ -64,6 +64,70 @@ class TestPolicyMatcherScopeMatching: assert PolicyMatcher.scope_matches(scope, context) is True +class TestPolicyMatcherScopeMatchingWithTags: + """Test scope matching with tag patterns.""" + + def test_scope_tag_matching(self): + """Test scope tag matching: exact, wildcard, no-match, and empty context tags.""" + # Exact match + scope = PolicyScope(teams=["*"], keys=["*"], models=["*"], tags=["healthcare"]) + context = PolicyMatchContext( + team_alias="team", key_alias="key", model="gpt-4", + tags=["healthcare", "internal"], + ) + assert PolicyMatcher.scope_matches(scope, context) is True + + # Wildcard match + scope_wc = PolicyScope(teams=["*"], keys=["*"], models=["*"], tags=["health-*"]) + context_wc = PolicyMatchContext( + team_alias="team", key_alias="key", model="gpt-4", + tags=["health-prod"], + ) + assert PolicyMatcher.scope_matches(scope_wc, context_wc) is True + + # No match — wrong tag + context_wrong = PolicyMatchContext( + team_alias="team", key_alias="key", model="gpt-4", + tags=["finance"], + ) + assert PolicyMatcher.scope_matches(scope, context_wrong) is False + + # No match — context has no tags + context_none = PolicyMatchContext( + team_alias="team", key_alias="key", model="gpt-4", tags=None, + ) + assert PolicyMatcher.scope_matches(scope, context_none) is False + + # Scope without tags matches any context (opt-in semantics) + scope_no_tags = PolicyScope(teams=["*"], keys=["*"], models=["*"]) + assert PolicyMatcher.scope_matches(scope_no_tags, context) is True + + def test_scope_tags_and_team_combined(self): + """Test scope with both tags and team — both must match (AND logic).""" + scope = PolicyScope(teams=["team-a"], keys=["*"], models=["*"], tags=["healthcare"]) + + # Both match + context_both = PolicyMatchContext( + team_alias="team-a", key_alias="key", model="gpt-4", + tags=["healthcare"], + ) + assert PolicyMatcher.scope_matches(scope, context_both) is True + + # Tag matches, team doesn't + context_wrong_team = PolicyMatchContext( + team_alias="team-b", key_alias="key", model="gpt-4", + tags=["healthcare"], + ) + assert PolicyMatcher.scope_matches(scope, context_wrong_team) is False + + # Team matches, tag doesn't + context_wrong_tag = PolicyMatchContext( + team_alias="team-a", key_alias="key", model="gpt-4", + tags=["finance"], + ) + assert PolicyMatcher.scope_matches(scope, context_wrong_tag) is False + + class TestPolicyMatcherWithAttachments: """Test getting matching policies via attachments."""