Skip to content

Commit

Permalink
Merge pull request #2 from Never-Over/test-boundary-trie
Browse files Browse the repository at this point in the history
Write tests for BoundaryTrie functionality
  • Loading branch information
emdoyle authored Feb 9, 2024
2 parents d4922eb + e786bb7 commit 5ef0ed8
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 22 deletions.
19 changes: 12 additions & 7 deletions modguard/core/boundary.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,26 @@ class BoundaryTrie:
def __iter__(self):
return boundary_trie_iterator(self)

@staticmethod
def _split_mod_path(path: str) -> list[str]:
# By default "".split(".") -> ['']
# so we want to remove any whitespace path components
return [part for part in path.split(".") if part]

def get(self, path: str) -> Optional[BoundaryNode]:
node = self.root
parts = path.split(".")
parts = self._split_mod_path(path)

for part in parts:
if part not in node.children:
return None
node = node.children[part]

return node
return node if node.is_end_of_path else None

def insert(self, path: str, public_members: Optional[list[PublicMember]] = None):
node = self.root
parts = path.split(".")
parts = [part for part in parts if part]
parts = self._split_mod_path(path)

for part in parts:
if part not in node.children:
Expand Down Expand Up @@ -66,8 +71,8 @@ def register_public_member(self, path: str, member: PublicMember):

def find_nearest(self, path: str) -> Optional[BoundaryNode]:
node = self.root
parts = path.split(".")
nearest_parent = node if node.is_end_of_path else None
parts = self._split_mod_path(path)
nearest_parent = node

for part in parts:
if part in node.children:
Expand All @@ -77,7 +82,7 @@ def find_nearest(self, path: str) -> Optional[BoundaryNode]:
else:
break

return nearest_parent
return nearest_parent if nearest_parent.is_end_of_path else None


def boundary_trie_iterator(trie: BoundaryTrie) -> Generator[BoundaryNode, None, None]:
Expand Down
Empty file removed tests/mocks/__init__.py
Empty file.
12 changes: 0 additions & 12 deletions tests/mocks/boundary_trie.py

This file was deleted.

160 changes: 160 additions & 0 deletions tests/test_boundary_trie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import pytest

from modguard.core import BoundaryTrie, PublicMember, BoundaryNode


@pytest.fixture
def boundary_trie():
return BoundaryTrie(
root=BoundaryNode(
public_members={},
children={
"domain_one": BoundaryNode(
public_members={},
children={},
is_end_of_path=True,
full_path="domain_one",
),
"domain_two": BoundaryNode(
public_members={},
children={
"subdomain": BoundaryNode(
public_members={},
children={},
is_end_of_path=True,
full_path="domain_two.subdomain",
)
},
is_end_of_path=True,
full_path="domain_two",
),
"domain_three": BoundaryNode(
public_members={},
children={},
is_end_of_path=True,
full_path="domain_three",
),
"domain_four": BoundaryNode(
public_members={
"domain_four.public_api": PublicMember(
name="domain_four.public_api", allowlist=None
)
},
children={},
is_end_of_path=True,
full_path="domain_four",
),
},
is_end_of_path=True,
full_path="",
)
)


def test_iterate_over_empty_trie():
assert list(BoundaryTrie()) == []


def test_iterate_over_populated_trie(boundary_trie):
assert set((node.full_path for node in boundary_trie)) == {
"",
"domain_one",
"domain_two",
"domain_two.subdomain",
"domain_three",
"domain_four",
}


def test_get_nonexistent_path(boundary_trie):
assert boundary_trie.get("fakepath") is None


def test_get_nonexistent_empty_path():
trie = BoundaryTrie()
assert trie.get("") is None


def test_get_actual_path(boundary_trie):
assert boundary_trie.get("domain_one") is not None


def test_get_actual_empty_path(boundary_trie):
assert boundary_trie.get("") is not None


def test_insert_empty_path():
trie = BoundaryTrie()
trie.insert("")
assert set((node.full_path for node in trie)) == {""}


def test_insert_single_level_path():
trie = BoundaryTrie()
trie.insert("domain")
assert set((node.full_path for node in trie)) == {"domain"}


def test_insert_multi_level_path():
trie = BoundaryTrie()
trie.insert("domain.subdomain")
assert set((node.full_path for node in trie)) == {"domain.subdomain"}


def test_register_unnamed_public_member_at_root(boundary_trie):
pub_member = PublicMember(name="")
boundary_trie.register_public_member("member_path", pub_member)
assert boundary_trie.get("").public_members == {"member_path": pub_member}


def test_register_named_public_member_at_root(boundary_trie):
pub_member = PublicMember(name="member_variable")
boundary_trie.register_public_member("member_path", pub_member)
assert boundary_trie.get("").public_members == {
"member_path.member_variable": pub_member
}


def test_register_named_public_member_at_single_level_domain(boundary_trie):
pub_member = PublicMember(name="member_variable")
boundary_trie.register_public_member("domain_one", pub_member)
assert boundary_trie.get("domain_one").public_members == {
"domain_one.member_variable": pub_member
}


def test_register_unnamed_public_member_at_single_level_domain(boundary_trie):
pub_member = PublicMember(name="")
boundary_trie.register_public_member("domain_one", pub_member)
assert boundary_trie.get("domain_one").public_members == {"domain_one": pub_member}


def test_register_named_public_member_at_nested_domain(boundary_trie):
pub_member = PublicMember(name="member_variable")
boundary_trie.register_public_member("domain_two.subdomain", pub_member)
assert boundary_trie.get("domain_two.subdomain").public_members == {
"domain_two.subdomain.member_variable": pub_member
}


def test_register_unnamed_public_member_at_nested_domain(boundary_trie):
pub_member = PublicMember(name="")
boundary_trie.register_public_member("domain_two.subdomain", pub_member)
assert boundary_trie.get("domain_two.subdomain").public_members == {
"domain_two.subdomain": pub_member
}


def test_find_nearest_at_root(boundary_trie):
boundary = boundary_trie.find_nearest("other_domain")
assert boundary.full_path == ""


def test_find_nearest_in_single_domain(boundary_trie):
boundary = boundary_trie.find_nearest("domain_one.thing")
assert boundary.full_path == "domain_one"


def test_find_nearest_in_nested_domain(boundary_trie):
boundary = boundary_trie.find_nearest("domain_two.subdomain.thing")
assert boundary.full_path == "domain_two.subdomain"
11 changes: 8 additions & 3 deletions tests/test_check.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import pytest
from modguard.check import check, ErrorInfo, check_import
from modguard.core import BoundaryTrie
from .mocks.boundary_trie import build_example_boundary_trie
from modguard.core import BoundaryTrie, PublicMember


@pytest.fixture
def boundary_trie() -> BoundaryTrie:
return build_example_boundary_trie()
trie = BoundaryTrie()
trie.insert("")
trie.insert("domain_one")
trie.insert("domain_two")
trie.insert("domain_three")
trie.insert("domain_four", [PublicMember(name="domain_four.public_api")])
return trie


def _test_check_import(
Expand Down

0 comments on commit 5ef0ed8

Please sign in to comment.