Files
kaya/packages/kaya-core/tests/test_tree.py
T
woggioni fa3ff32f66 Implemented modular code structure
Refactored repository into kaya-core and kaya-rsgi packages
2026-07-15 22:18:45 +08:00

104 lines
4.6 KiB
Python

from typing import Sequence, Tuple, Optional, List
from kaya.core import Tree, PathHandler, HttpContext, HttpMethod, PathIterator
from pwo import Maybe
import unittest
class PathIteratorTest(unittest.TestCase):
cases: Tuple[Tuple[str, Tuple[str, ...]], ...] = (
('/', tuple()),
('root/foo', ('root', 'foo')),
('/root', ('root',)),
('/root', ('root',)),
('/root/', ('root',)),
('/root/bar/', ('root', 'bar')),
)
def test_path_iterator(self):
for (case, expected) in self.cases:
with self.subTest(case) as _:
components = tuple((c for c in PathIterator(case)))
self.assertEqual(expected, components)
class TreeTest(unittest.TestCase):
tree: Tree
handlers: List[PathHandler]
def setUp(self):
self.tree = Tree()
class TestHandler(PathHandler):
def handle_request(self, ctx: HttpContext):
pass
@property
def recursive(self) -> bool:
return True
self.handlers = [TestHandler() for _ in range(20)]
routes: Tuple[Tuple[Tuple[str, ...], Optional[HttpMethod], PathHandler], ...] = (
(('home', 'something'), HttpMethod.GET, self.handlers[0]),
(('home', 'something_else'), HttpMethod.GET, self.handlers[1]),
(('home', 'something_else'), HttpMethod.POST, self.handlers[2]),
(('home', 'something', 'object'), HttpMethod.GET, self.handlers[3]),
(('home', 'something_else', 'foo'), HttpMethod.GET, self.handlers[4]),
(('home',), HttpMethod.GET, self.handlers[5]),
(('home',), HttpMethod.POST, self.handlers[6]),
(('home',), None, self.handlers[7]),
(('home', '*.md'), None, self.handlers[8]),
(('home', 'something', '*', 'blah', '*.md'), None, self.handlers[9]),
(('home', 'bar', '*'), None, self.handlers[10]),
)
for path, method, handler in routes:
self.tree.add((p for p in path), method, handler)
def test_tree(self):
cases: Tuple[Tuple[str, HttpMethod, Optional[int]], ...] = (
('http://localhost:127.0.0.1:5432/home/something', HttpMethod.GET, 0),
('http://localhost:127.0.0.1:5432/home/something_else', HttpMethod.GET, 1),
('http://localhost:127.0.0.1:5432/home/something_else', HttpMethod.POST, 2),
('http://localhost:127.0.0.1:5432/home/something/object', HttpMethod.GET, 3),
('http://localhost:127.0.0.1:5432/home/something_else/foo', HttpMethod.GET, 4),
('http://localhost:127.0.0.1:5432/', HttpMethod.GET, None),
('http://localhost:127.0.0.1:5432/home', HttpMethod.GET, 5),
('http://localhost:127.0.0.1:5432/home', HttpMethod.POST, 6),
('http://localhost:127.0.0.1:5432/home', HttpMethod.PUT, 7),
('http://localhost:127.0.0.1:5432/home/README.md', HttpMethod.GET, 8),
('http://localhost:127.0.0.1:5432/home/something/ciao/blah/README.md', HttpMethod.GET, 9),
('http://localhost:127.0.0.1:5432/home/bar/ciao/blah/README.md', HttpMethod.GET, 10),
)
for url, method, handler_num in cases:
with self.subTest(f"{str(method)} {url}"):
res = self.tree.get_handler(url, method)
self.assertIs(Maybe.of(handler_num).map(self.handlers.__getitem__).or_none(),
Maybe.of_nullable(res).map(lambda it: it[0]).or_none())
def test_two_method_agnostic_matchers_raise(self):
tree = Tree()
tree.add((p for p in ('foo', '*')), None, self.handlers[0])
with self.assertRaises(ValueError):
tree.add((p for p in ('foo', '*')), None, self.handlers[1])
def test_two_overlapping_method_specific_matchers_raise(self):
tree = Tree()
tree.add((p for p in ('foo', '${id:int}')), HttpMethod.PUT, self.handlers[0])
with self.assertRaises(ValueError):
tree.add((p for p in ('foo', '${name:str}')), HttpMethod.PUT, self.handlers[1])
def test_disjoint_method_specific_matchers_allowed(self):
tree = Tree()
tree.add((p for p in ('foo', '*')), HttpMethod.PUT, self.handlers[0])
tree.add((p for p in ('foo', '*')), HttpMethod.GET, self.handlers[1])
put_handler = Maybe.of_nullable(tree.get_handler('/foo/bar', HttpMethod.PUT)).map(lambda it: it[0]).or_none()
get_handler = Maybe.of_nullable(tree.get_handler('/foo/bar', HttpMethod.GET)).map(lambda it: it[0]).or_none()
self.assertIs(self.handlers[0], put_handler)
self.assertIs(self.handlers[1], get_handler)