初始化提交
This commit is contained in:
commit
887c1f449e
963 files changed
+166869
No files matched your search
@@ -0,0 +1,141 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from app.ai_provider.routing.permissions import CapabilityPermissionController, PermissionRule
|
||||
|
||||
|
||||
class TestPermissionRule:
|
||||
def test_exact_match(self):
|
||||
rule = PermissionRule(model_pattern="fast-model", capability="vision", allowed=True)
|
||||
assert rule.match("fast-model") is True
|
||||
assert rule.match("pro-model") is False
|
||||
|
||||
def test_wildcard_match(self):
|
||||
rule = PermissionRule(model_pattern="deepseek-*", capability="thinking", allowed=False)
|
||||
assert rule.match("deepseek-v4-flash") is True
|
||||
assert rule.match("deepseek-v4-pro") is True
|
||||
assert rule.match("claude-sonnet-4-6") is False
|
||||
|
||||
def test_universal_match(self):
|
||||
rule = PermissionRule(model_pattern="*", capability="vision", allowed=True)
|
||||
assert rule.match("any-model") is True
|
||||
assert rule.match("another-one") is True
|
||||
|
||||
def test_suffix_wildcard(self):
|
||||
rule = PermissionRule(model_pattern="*-pro", capability="thinking", allowed=True)
|
||||
assert rule.match("deepseek-v4-pro") is True
|
||||
assert rule.match("fast-model") is False
|
||||
|
||||
def test_match_method_called_explicitly(self):
|
||||
rule = PermissionRule(model_pattern="vision-*", capability="vision")
|
||||
assert rule.match("vision-model") is True
|
||||
|
||||
def test_allowed_defaults_to_true(self):
|
||||
rule = PermissionRule(model_pattern="*", capability="vision")
|
||||
assert rule.allowed is True
|
||||
|
||||
def test_allowed_set_to_false(self):
|
||||
rule = PermissionRule(model_pattern="*", capability="vision", allowed=False)
|
||||
assert rule.allowed is False
|
||||
|
||||
def test_repr(self):
|
||||
rule = PermissionRule(model_pattern="*", capability="vision", allowed=True)
|
||||
r = repr(rule)
|
||||
assert "PermissionRule" in r
|
||||
assert "*" in r
|
||||
assert "vision" in r
|
||||
|
||||
def test_eq_same_rules(self):
|
||||
rule1 = PermissionRule(model_pattern="foo-*", capability="vision", allowed=True)
|
||||
rule2 = PermissionRule(model_pattern="foo-*", capability="vision", allowed=True)
|
||||
assert rule1 == rule2
|
||||
|
||||
def test_eq_different_rules(self):
|
||||
rule1 = PermissionRule(model_pattern="foo-*", capability="vision", allowed=True)
|
||||
rule2 = PermissionRule(model_pattern="bar-*", capability="vision", allowed=True)
|
||||
assert rule1 != rule2
|
||||
|
||||
|
||||
class TestCapabilityPermissionController:
|
||||
def test_allow_all_by_default(self):
|
||||
controller = CapabilityPermissionController([])
|
||||
assert controller.check("fast-model", "vision") is True
|
||||
|
||||
def test_deny_specific_capability_on_model(self):
|
||||
controller = CapabilityPermissionController(
|
||||
[
|
||||
PermissionRule(model_pattern="fast-*", capability="vision", allowed=False),
|
||||
]
|
||||
)
|
||||
assert controller.check("fast-model", "vision") is False
|
||||
assert controller.check("pro-model", "vision") is True
|
||||
|
||||
def test_deny_then_allow_more_specific(self):
|
||||
"""A more specific deny should override a broader allow."""
|
||||
controller = CapabilityPermissionController(
|
||||
[
|
||||
PermissionRule(model_pattern="*", capability="thinking", allowed=True),
|
||||
PermissionRule(model_pattern="fast-*", capability="thinking", allowed=False),
|
||||
]
|
||||
)
|
||||
assert controller.check("fast-model", "thinking") is False
|
||||
assert controller.check("pro-model", "thinking") is True
|
||||
|
||||
def test_filter_capabilities(self):
|
||||
controller = CapabilityPermissionController(
|
||||
[
|
||||
PermissionRule(model_pattern="*", capability="vision", allowed=False),
|
||||
PermissionRule(model_pattern="vision-*", capability="vision", allowed=True),
|
||||
]
|
||||
)
|
||||
filtered = controller.filter_capabilities("fast-model", {"chat", "vision", "thinking"})
|
||||
assert filtered == {"chat", "thinking"}
|
||||
|
||||
filtered_vision = controller.filter_capabilities(
|
||||
"vision-model", {"chat", "vision", "thinking"}
|
||||
)
|
||||
assert filtered_vision == {"chat", "vision", "thinking"}
|
||||
|
||||
def test_filter_with_no_rules(self):
|
||||
controller = CapabilityPermissionController([])
|
||||
filtered = controller.filter_capabilities("any-model", {"chat", "vision"})
|
||||
assert filtered == {"chat", "vision"}
|
||||
|
||||
def test_check_nonexistent_model(self):
|
||||
"""Non-existent models should still be checked against rules."""
|
||||
controller = CapabilityPermissionController(
|
||||
[
|
||||
PermissionRule(model_pattern="*", capability="vision", allowed=False),
|
||||
]
|
||||
)
|
||||
assert controller.check("unknown-model", "vision") is False
|
||||
|
||||
def test_multiple_rules_matching(self):
|
||||
"""When multiple rules match, the last one wins (most specific wins by order)."""
|
||||
controller = CapabilityPermissionController(
|
||||
[
|
||||
PermissionRule(model_pattern="*", capability="tool_use", allowed=True),
|
||||
PermissionRule(model_pattern="basic-*", capability="tool_use", allowed=False),
|
||||
PermissionRule(model_pattern="basic-pro", capability="tool_use", allowed=True),
|
||||
]
|
||||
)
|
||||
assert controller.check("basic-lite", "tool_use") is False
|
||||
assert controller.check("basic-pro", "tool_use") is True
|
||||
assert controller.check("pro-model", "tool_use") is True
|
||||
|
||||
def test_check_capability_not_in_rules(self):
|
||||
controller = CapabilityPermissionController(
|
||||
[
|
||||
PermissionRule(model_pattern="*", capability="vision", allowed=False),
|
||||
]
|
||||
)
|
||||
# 'chat' is not in any rule, so it's allowed by default
|
||||
assert controller.check("fast-model", "chat") is True
|
||||
|
||||
def test_is_allowed_model(self):
|
||||
controller = CapabilityPermissionController(
|
||||
[
|
||||
PermissionRule(model_pattern="*", capability="vision", allowed=False),
|
||||
]
|
||||
)
|
||||
assert controller.is_allowed("fast-model", "vision") is False
|
||||
assert controller.is_allowed("fast-model", "chat") is True
|
||||
Reference in new issue
Block a user