Files
litellm/tests/test_litellm/proxy/policy_engine/test_policy_resolver.py
T
Ishaan Jaff c23e4b87dc [Feat] New LiteLLM Policy engine - create policies to manage guardrails, conditions - permissions per Key, Team (#19612)
* init PolicyMatcher

* TestPolicyMatcherGetMatchingPolicies

* TestPolicyMatcherGetMatchingPolicies

* feat: init PolicyResolver

* init resolver types

* init policy from config

* inint PolicyValidator

* validate policy

* init Architecture Diagram

* test_add_guardrails_from_policy_engine

* init _init_policy_engine

* test updates

* test fixws

* new attachment config

* simplify types

* TestPolicyResolverInheritance

* fix policy resolver

* fix policies

* fix applied policy

* docs fix

* docs fix

* fix linting + QA checks

* fix linting + QA fixes

* test fixes
2026-01-22 19:49:53 -08:00

194 lines
6.6 KiB
Python

"""
Unit tests for PolicyResolver - tests guardrail resolution.
Tests:
- Inheritance chain resolution
- Inheritance with add/remove
- Model conditions
"""
import pytest
from litellm.proxy.policy_engine.policy_resolver import PolicyResolver
from litellm.types.proxy.policy_engine import (
Policy,
PolicyCondition,
PolicyGuardrails,
PolicyMatchContext,
)
class TestPolicyResolverInheritance:
"""Test resolve_policy_guardrails - inheritance and add/remove."""
def test_resolve_simple_policy(self):
"""Test resolving guardrails for a simple policy."""
policies = {
"global": Policy(
guardrails=PolicyGuardrails(add=["pii_blocker", "toxicity_filter"]),
),
}
resolved = PolicyResolver.resolve_policy_guardrails(
policy_name="global", policies=policies
)
assert set(resolved.guardrails) == {"pii_blocker", "toxicity_filter"}
assert resolved.inheritance_chain == ["global"]
def test_resolve_with_inheritance(self):
"""Test child policy inherits and adds guardrails from parent."""
policies = {
"base": Policy(
guardrails=PolicyGuardrails(add=["pii_blocker"]),
),
"healthcare": Policy(
inherit="base",
guardrails=PolicyGuardrails(add=["hipaa_audit"]),
),
}
resolved = PolicyResolver.resolve_policy_guardrails(
policy_name="healthcare", policies=policies
)
# Healthcare inherits pii_blocker from base and adds hipaa_audit
assert set(resolved.guardrails) == {"pii_blocker", "hipaa_audit"}
assert resolved.inheritance_chain == ["base", "healthcare"]
def test_resolve_with_remove(self):
"""Test child policy can remove guardrails from parent."""
policies = {
"base": Policy(
guardrails=PolicyGuardrails(add=["pii_blocker", "phi_blocker"]),
),
"dev": Policy(
inherit="base",
guardrails=PolicyGuardrails(add=["toxicity_filter"], remove=["phi_blocker"]),
),
}
resolved = PolicyResolver.resolve_policy_guardrails(
policy_name="dev", policies=policies
)
# dev inherits pii_blocker from base, adds toxicity_filter, removes phi_blocker
assert "pii_blocker" in resolved.guardrails
assert "toxicity_filter" in resolved.guardrails
assert "phi_blocker" not in resolved.guardrails
def test_resolve_deep_inheritance_chain(self):
"""Test multi-level inheritance chain."""
policies = {
"root": Policy(
guardrails=PolicyGuardrails(add=["root_guardrail"]),
),
"middle": Policy(
inherit="root",
guardrails=PolicyGuardrails(add=["middle_guardrail"]),
),
"leaf": Policy(
inherit="middle",
guardrails=PolicyGuardrails(add=["leaf_guardrail"]),
),
}
resolved = PolicyResolver.resolve_policy_guardrails(
policy_name="leaf", policies=policies
)
assert set(resolved.guardrails) == {"root_guardrail", "middle_guardrail", "leaf_guardrail"}
assert resolved.inheritance_chain == ["root", "middle", "leaf"]
class TestPolicyResolverWithConditions:
"""Test resolve_policy_guardrails with model conditions."""
def test_condition_matches(self):
"""Test guardrails are added when condition matches."""
policies = {
"gpt4-policy": Policy(
guardrails=PolicyGuardrails(add=["toxicity_filter"]),
condition=PolicyCondition(model="gpt-4.*"),
),
}
# GPT-4 should get guardrails
context = PolicyMatchContext(team_alias="team", key_alias="k", model="gpt-4")
resolved = PolicyResolver.resolve_policy_guardrails(
policy_name="gpt4-policy",
policies=policies,
context=context,
)
assert "toxicity_filter" in resolved.guardrails
def test_condition_does_not_match(self):
"""Test guardrails are NOT added when condition doesn't match."""
policies = {
"gpt4-policy": Policy(
guardrails=PolicyGuardrails(add=["toxicity_filter"]),
condition=PolicyCondition(model="gpt-4.*"),
),
}
# GPT-3.5 should NOT get guardrails
context = PolicyMatchContext(team_alias="team", key_alias="k", model="gpt-3.5")
resolved = PolicyResolver.resolve_policy_guardrails(
policy_name="gpt4-policy",
policies=policies,
context=context,
)
assert "toxicity_filter" not in resolved.guardrails
def test_no_condition_always_applies(self):
"""Test policy without condition always applies."""
policies = {
"global": Policy(
guardrails=PolicyGuardrails(add=["pii_blocker"]),
),
}
context = PolicyMatchContext(team_alias="any", key_alias="any", model="any")
resolved = PolicyResolver.resolve_policy_guardrails(
policy_name="global",
policies=policies,
context=context,
)
assert "pii_blocker" in resolved.guardrails
def test_inheritance_with_condition(self):
"""Test inheritance works with conditions."""
policies = {
"base": Policy(
guardrails=PolicyGuardrails(add=["pii_blocker"]),
),
"child": Policy(
inherit="base",
guardrails=PolicyGuardrails(add=["child_guardrail"]),
condition=PolicyCondition(model="gpt-4"),
),
}
# GPT-4 should get both base and child guardrails
context_gpt4 = PolicyMatchContext(team_alias="t", key_alias="k", model="gpt-4")
resolved_gpt4 = PolicyResolver.resolve_policy_guardrails(
policy_name="child",
policies=policies,
context=context_gpt4,
)
assert "pii_blocker" in resolved_gpt4.guardrails
assert "child_guardrail" in resolved_gpt4.guardrails
# GPT-3.5 should only get base guardrails (child condition doesn't match)
context_gpt35 = PolicyMatchContext(team_alias="t", key_alias="k", model="gpt-3.5")
resolved_gpt35 = PolicyResolver.resolve_policy_guardrails(
policy_name="child",
policies=policies,
context=context_gpt35,
)
assert "pii_blocker" in resolved_gpt35.guardrails
assert "child_guardrail" not in resolved_gpt35.guardrails