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):
"""
:return: The created object.
"""
raise NotImplementedError()
pass
@abc.abstractmethod
def __hash__(self):

View file

@ -112,7 +112,7 @@ class Filter:
return decorated
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:
- 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())
@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):
"""
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.
: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 _deco_regex(pattern: Pattern):
def decorator(func):
@functools.wraps(func)
def decorated(obj):
result: str = func(obj)
if match := pattern.match(result):
return match
else:
raise exc.Discard(result, f"Text didn't match pattern {pattern}")
return decorated
return decorator
def endswith(self, suffix: str):
"""
Check if an object ends with the specified suffix and discard the objects that do not.
:param suffix: The prefix object should start with.
:return: A new :class:`Filter` with the new requirements.
"""
return self.filter(lambda x: x.endswith(suffix), error=f"Text didn't end with {suffix}")
def regex(self, pattern: Pattern):
"""
@ -225,7 +209,13 @@ class Filter:
:param pattern: The pattern that should be matched by the text.
: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):
"""

View file

@ -1,7 +1,8 @@
import pytest
import asyncio
import async_timeout
from .. import sentry, exc
import re
from .. import sentry, exc, blueprints
@pytest.fixture
@ -40,6 +41,14 @@ def discarding_filter() -> sentry.Filter:
return sentry.Filter(discard)
class ErrorTest(Exception):
pass
def error_test(*_, **__):
raise ErrorTest("This was raised by error_raiser.")
class TestFilter:
def test_creation(self):
f = sentry.Filter(lambda _: _)
@ -66,5 +75,137 @@ class TestFilter:
@pytest.mark.asyncio
async def test_timeout(self, s: sentry.Sentry):
with pytest.raises(asyncio.TimeoutError):
async with async_timeout.timeout(0.05):
async with async_timeout.timeout(0.001):
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()