be6dc4cc19
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: abdoelsayed2016 <27821589+abdoelsayed2016@users.noreply.github.com>
88 lines
3.3 KiB
Python
88 lines
3.3 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from src.permissions import ToolPermissionContext
|
|
|
|
|
|
class TestToolPermissionContext(unittest.TestCase):
|
|
# 1. Empty context blocks nothing
|
|
def test_empty_context_blocks_nothing(self) -> None:
|
|
ctx = ToolPermissionContext()
|
|
self.assertFalse(ctx.blocks("anything"))
|
|
self.assertFalse(ctx.blocks(""))
|
|
|
|
# 2. Exact name blocking (case insensitive)
|
|
def test_exact_name_blocking(self) -> None:
|
|
ctx = ToolPermissionContext.from_iterables(deny_names=["dangerous_tool"])
|
|
self.assertTrue(ctx.blocks("dangerous_tool"))
|
|
self.assertTrue(ctx.blocks("Dangerous_Tool"))
|
|
self.assertTrue(ctx.blocks("DANGEROUS_TOOL"))
|
|
self.assertFalse(ctx.blocks("safe_tool"))
|
|
|
|
# 3. Prefix blocking (case insensitive)
|
|
def test_prefix_blocking(self) -> None:
|
|
ctx = ToolPermissionContext.from_iterables(deny_prefixes=["admin_"])
|
|
self.assertTrue(ctx.blocks("admin_delete"))
|
|
self.assertTrue(ctx.blocks("Admin_Delete"))
|
|
self.assertTrue(ctx.blocks("ADMIN_CREATE"))
|
|
self.assertFalse(ctx.blocks("user_admin"))
|
|
|
|
# 4. Combined name + prefix blocking
|
|
def test_combined_name_and_prefix_blocking(self) -> None:
|
|
ctx = ToolPermissionContext.from_iterables(
|
|
deny_names=["rm"],
|
|
deny_prefixes=["sudo_"],
|
|
)
|
|
self.assertTrue(ctx.blocks("rm"))
|
|
self.assertTrue(ctx.blocks("sudo_restart"))
|
|
self.assertFalse(ctx.blocks("ls"))
|
|
|
|
# 5. Non-matching names are allowed
|
|
def test_non_matching_names_allowed(self) -> None:
|
|
ctx = ToolPermissionContext.from_iterables(
|
|
deny_names=["blocked"],
|
|
deny_prefixes=["bad_"],
|
|
)
|
|
self.assertFalse(ctx.blocks("allowed"))
|
|
self.assertFalse(ctx.blocks("good_tool"))
|
|
self.assertFalse(ctx.blocks("not_bad"))
|
|
|
|
# 6. from_iterables with None args
|
|
def test_from_iterables_none_args(self) -> None:
|
|
ctx = ToolPermissionContext.from_iterables(deny_names=None, deny_prefixes=None)
|
|
self.assertEqual(ctx.deny_names, frozenset())
|
|
self.assertEqual(ctx.deny_prefixes, ())
|
|
self.assertFalse(ctx.blocks("anything"))
|
|
|
|
def test_from_iterables_default_args(self) -> None:
|
|
ctx = ToolPermissionContext.from_iterables()
|
|
self.assertEqual(ctx.deny_names, frozenset())
|
|
self.assertEqual(ctx.deny_prefixes, ())
|
|
|
|
# 7. from_iterables normalizes to lowercase
|
|
def test_from_iterables_normalizes_to_lowercase(self) -> None:
|
|
ctx = ToolPermissionContext.from_iterables(
|
|
deny_names=["FooBar"],
|
|
deny_prefixes=["PFX_"],
|
|
)
|
|
self.assertIn("foobar", ctx.deny_names)
|
|
self.assertNotIn("FooBar", ctx.deny_names)
|
|
self.assertEqual(ctx.deny_prefixes, ("pfx_",))
|
|
self.assertTrue(ctx.blocks("FOOBAR"))
|
|
self.assertTrue(ctx.blocks("pfx_something"))
|
|
|
|
# 8. Multiple deny_names
|
|
def test_multiple_deny_names(self) -> None:
|
|
ctx = ToolPermissionContext.from_iterables(
|
|
deny_names=["tool_a", "tool_b", "tool_c"],
|
|
)
|
|
self.assertTrue(ctx.blocks("tool_a"))
|
|
self.assertTrue(ctx.blocks("tool_b"))
|
|
self.assertTrue(ctx.blocks("tool_c"))
|
|
self.assertFalse(ctx.blocks("tool_d"))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|