1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-23 03:24:20 +00:00

⚗️ Write more tests, why do they crash

This commit is contained in:
Steffo 2020-12-18 22:52:17 +01:00
parent 9b4b382145
commit b8705c59cd
3 changed files with 161 additions and 31 deletions

View file

@ -42,12 +42,11 @@ class Blueprint(metaclass=abc.ABCMeta):
""" """
@abc.abstractmethod
def __init__(self): def __init__(self):
""" """
:return: The created object. :return: The created object.
""" """
raise NotImplementedError() pass
@abc.abstractmethod @abc.abstractmethod
def __hash__(self): def __hash__(self):

View file

@ -112,7 +112,7 @@ class Filter:
return decorated return decorated
return decorator return decorator
def map(self, c: Callable[[Any], bool]) -> Filter: def map(self, c: Callable[[Any], object]) -> Filter:
""" """
Apply the function ``c`` on all objects transiting through the queue: Apply the function ``c`` on all objects transiting through the queue:
- If the function **returns**, its return value replaces the object in the queue; - If the function **returns**, its return value replaces the object in the queue;
@ -184,18 +184,6 @@ class Filter:
""" """
return self.requires(blueprints.Message.text).map(lambda o: o.text()) return self.requires(blueprints.Message.text).map(lambda o: o.text())
@staticmethod
def _deco_startswith(prefix: str):
def decorator(func):
@functools.wraps(func)
def decorated(obj):
result: str = func(obj)
if not result.startswith(prefix):
raise exc.Discard(result, f"Text didn't start with {prefix}")
return result
return decorated
return decorator
def startswith(self, prefix: str): def startswith(self, prefix: str):
""" """
Check if an object starts with the specified prefix and discard the objects that do not. Check if an object starts with the specified prefix and discard the objects that do not.
@ -203,20 +191,16 @@ class Filter:
:param prefix: The prefix object should start with. :param prefix: The prefix object should start with.
:return: A new :class:`Filter` with the new requirements. :return: A new :class:`Filter` with the new requirements.
""" """
return self.__class__(self._deco_startswith(prefix)(self.func)) return self.filter(lambda x: x.startswith(prefix), error=f"Text didn't start with {prefix}")
@staticmethod def endswith(self, suffix: str):
def _deco_regex(pattern: Pattern): """
def decorator(func): Check if an object ends with the specified suffix and discard the objects that do not.
@functools.wraps(func)
def decorated(obj): :param suffix: The prefix object should start with.
result: str = func(obj) :return: A new :class:`Filter` with the new requirements.
if match := pattern.match(result): """
return match return self.filter(lambda x: x.endswith(suffix), error=f"Text didn't end with {suffix}")
else:
raise exc.Discard(result, f"Text didn't match pattern {pattern}")
return decorated
return decorator
def regex(self, pattern: Pattern): def regex(self, pattern: Pattern):
""" """
@ -225,7 +209,13 @@ class Filter:
:param pattern: The pattern that should be matched by the text. :param pattern: The pattern that should be matched by the text.
:return: A new :class:`Filter` with the new requirements. :return: A new :class:`Filter` with the new requirements.
""" """
return self.__class__(self._deco_regex(pattern)(self.func)) def mapping(x):
if match := pattern.match(x):
return match
else:
raise exc.Discard(x, f"Text didn't match pattern {pattern}")
return self.map(mapping)
def choices(self, *choices): def choices(self, *choices):
""" """

View file

@ -1,7 +1,8 @@
import pytest import pytest
import asyncio import asyncio
import async_timeout import async_timeout
from .. import sentry, exc import re
from .. import sentry, exc, blueprints
@pytest.fixture @pytest.fixture
@ -40,6 +41,14 @@ def discarding_filter() -> sentry.Filter:
return sentry.Filter(discard) return sentry.Filter(discard)
class ErrorTest(Exception):
pass
def error_test(*_, **__):
raise ErrorTest("This was raised by error_raiser.")
class TestFilter: class TestFilter:
def test_creation(self): def test_creation(self):
f = sentry.Filter(lambda _: _) f = sentry.Filter(lambda _: _)
@ -66,5 +75,137 @@ class TestFilter:
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_timeout(self, s: sentry.Sentry): async def test_timeout(self, s: sentry.Sentry):
with pytest.raises(asyncio.TimeoutError): with pytest.raises(asyncio.TimeoutError):
async with async_timeout.timeout(0.05): async with async_timeout.timeout(0.001):
await s.f().get() await s.f().get()
@pytest.mark.asyncio
async def test_filter(self, s: sentry.Sentry):
await s.queue.put(None)
await s.queue.put(None)
assert await s.f().filter(lambda x: x is None, "Is not None").get_single() is None
with pytest.raises(exc.Discard):
await s.f().filter(lambda x: isinstance(x, type), error="Is not type").get_single()
with pytest.raises(ErrorTest):
await s.f().filter(error_test, error="Is error").get_single()
@pytest.mark.asyncio
async def test_map(self, s: sentry.Sentry):
await s.queue.put(None)
await s.queue.put(None)
assert await s.f().map(lambda x: 1).get_single() == 1
with pytest.raises(ErrorTest):
await s.f().map(error_test).get_single()
@pytest.mark.asyncio
async def test_type(self, s: sentry.Sentry):
await s.queue.put(1)
await s.queue.put("no")
assert await s.f().type(int).get_single() == 1
with pytest.raises(exc.Discard):
await s.f().type(int).get_single()
@pytest.mark.asyncio
async def test_msg(self, s: sentry.Sentry):
class ExampleMessage(blueprints.Message):
def __hash__(self):
return 1
msg = ExampleMessage()
await s.queue.put(msg)
await s.queue.put("no")
assert await s.f().msg().get_single() is msg
with pytest.raises(exc.Discard):
await s.f().msg().get_single()
@pytest.mark.asyncio
async def test_requires(self, s: sentry.Sentry):
class AvailableMessage(blueprints.Message):
def __hash__(self):
return 1
def text(self) -> str:
return "1"
class NotAvailableMessage(blueprints.Message):
def __hash__(self):
return 2
def text(self) -> str:
raise exc.NotAvailableError()
class NeverAvailableMessage(blueprints.Message):
def __hash__(self):
return 3
avmsg = AvailableMessage()
namsg = NotAvailableMessage()
nvmsg = NeverAvailableMessage()
await s.queue.put(avmsg)
await s.queue.put(namsg)
await s.queue.put(nvmsg)
await s.queue.put(namsg)
await s.queue.put(nvmsg)
assert await s.f().requires(blueprints.Message.text).get_single() is avmsg
with pytest.raises(exc.Discard):
await s.f().requires(blueprints.Message.text).get_single()
with pytest.raises(exc.NeverAvailableError):
await s.f().requires(blueprints.Message.text).get_single()
with pytest.raises(exc.NotAvailableError):
await s.f().requires(blueprints.Message.text, propagate_not_available=True).get_single()
with pytest.raises(exc.Discard):
await s.f().requires(blueprints.Message.text, propagate_never_available=False).get_single()
@pytest.mark.asyncio
async def test_startswith(self, s: sentry.Sentry):
await s.queue.put("yarrharr")
await s.queue.put("yohoho")
assert await s.f().startswith("yarr").get_single() == "yarrharr"
with pytest.raises(exc.Discard):
await s.f().startswith("yarr").get_single()
@pytest.mark.asyncio
async def test_endswith(self, s: sentry.Sentry):
await s.queue.put("yarrharr")
await s.queue.put("yohoho")
assert await s.f().endswith("harr").get_single() == "yarrharr"
with pytest.raises(exc.Discard):
await s.f().endswith("harr").get_single()
@pytest.mark.asyncio
async def test_regex(self, s: sentry.Sentry):
await s.queue.put("yarrharr")
await s.queue.put("yohoho")
assert isinstance(await s.f().regex(re.compile(r"[yh]arr")).get_single(), re.Match)
with pytest.raises(exc.Discard):
await s.f().regex(re.compile(r"[yh]arr")).get_single()
@pytest.mark.asyncio
async def test_choices(self, s: sentry.Sentry):
await s.queue.put("yarrharr")
await s.queue.put("yohoho")
assert await s.f().choices("yarrharr", "banana").get_single() == "yarrharr"
with pytest.raises(exc.Discard):
await s.f().choices("yarrharr", "banana").get_single()