clean tests

This commit is contained in:
Guilhem Saurel 2021-07-13 01:16:24 +02:00
parent 999b824874
commit 6a2e0336d9
4 changed files with 80 additions and 72 deletions

View file

@ -12,6 +12,6 @@ ADD tests/homeserver.yaml .
RUN python -m synapse.app.homeserver --config-path homeserver.yaml --generate-keys RUN python -m synapse.app.homeserver --config-path homeserver.yaml --generate-keys
RUN chown -R 991:991 . RUN chown -R 991:991 .
RUN pip install --no-cache-dir aiohttp matrix-nio markdown coverage RUN pip install --no-cache-dir markdown matrix-nio httpx coverage
WORKDIR /app WORKDIR /app

View file

@ -1,13 +1,53 @@
#!/usr/bin/env python #!/usr/bin/env python
"""Entry point to start an instrumentalized bot for coverage and run tests.""" """Entry point to start an instrumentalized bot for coverage and run tests."""
from os import environ
from subprocess import Popen, run from subprocess import Popen, run
from time import time
from unittest import main from unittest import main
import httpx
import yaml
from synapse._scripts.register_new_matrix_user import request_registration
BOT_URL = 'http://localhost:4785'
MATRIX_URL, MATRIX_ID, MATRIX_PW = (environ[v] for v in ['MATRIX_URL', 'MATRIX_ID', 'MATRIX_PW'])
def check_json(url: str, key: str) -> bool:
"""Ensure a service at a given url answers with valid json containing a certain key."""
try:
data = httpx.get(url).json()
return key in data
except httpx.ConnectError:
return False
def wait_available(url: str, key: str, timeout: int = 10) -> bool:
"""Wait until a service answer correctly or timeout."""
start = time()
while True:
if check_json(url, key):
return True
if time() > start + timeout:
return False
def run_and_test(): def run_and_test():
"""Launch the bot and its tests.""" """Launch the bot and its tests."""
if not wait_available(f'{MATRIX_URL}/_matrix/client/r0/login', 'flows'):
return False
# Try to register an user for the bot.
with open('/srv/homeserver.yaml') as f:
secret = yaml.safe_load(f.read()).get("registration_shared_secret", None)
request_registration(MATRIX_ID, MATRIX_PW, MATRIX_URL, secret, admin=True)
bot = Popen(['coverage', 'run', 'matrix_webhook.py']) bot = Popen(['coverage', 'run', 'matrix_webhook.py'])
if not wait_available(BOT_URL, 'status'):
return False
ret = main(module=None, exit=False).result.wasSuccessful() ret = main(module=None, exit=False).result.wasSuccessful()
bot.terminate() bot.terminate()
for cmd in ['report', 'html', 'xml']: for cmd in ['report', 'html', 'xml']:

View file

@ -1,30 +1,35 @@
"""Main test module.""" """Main test module."""
import json
import os import os
import unittest
import aiohttp import httpx
import nio import nio
from .utils import BOT_URL, MATRIX_ID, MATRIX_PW, MATRIX_URL, AbstractBotTest from .start import BOT_URL, MATRIX_ID, MATRIX_PW, MATRIX_URL
KEY = os.environ['API_KEY'] KEY = os.environ['API_KEY']
FULL_ID = f'@{MATRIX_ID}:{MATRIX_URL.split("/")[2]}'
class BotTest(AbstractBotTest): def bot_req(req=None, key=None, room_id=None):
"""Bot requests boilerplate."""
if key is not None:
req['key'] = key
url = BOT_URL if room_id is None else f'{BOT_URL}/{room_id}'
return httpx.post(url, json=req).json()
class BotTest(unittest.IsolatedAsyncioTestCase):
"""Main test class.""" """Main test class."""
async def test_errors(self): def test_errors(self):
"""Check the bot's error paths.""" """Check the bot's error paths."""
async with aiohttp.ClientSession() as session: self.assertEqual(bot_req(), {'status': 400, 'ret': 'Invalid JSON'})
async with session.get(BOT_URL) as response: self.assertEqual(bot_req({'toto': 3}), {'status': 400, 'ret': 'Missing text and/or API key property'})
self.assertEqual(await response.json(), {'status': 400, 'ret': 'Invalid JSON'}) self.assertEqual(bot_req({'text': 3, 'key': None}), {'status': 401, 'ret': 'Invalid API key'})
async with session.post(BOT_URL, data=json.dumps({'toto': 3})) as response:
self.assertEqual(await response.json(), {'status': 400, 'ret': 'Missing text and/or API key property'}) # TODO: we are not sending to a real room, so this should not be "OK"
async with session.post(BOT_URL, data=json.dumps({'text': 3, 'key': None})) as response: self.assertEqual(bot_req({'text': 3}, KEY), {'status': 200, 'ret': 'OK'})
self.assertEqual(await response.json(), {'status': 401, 'ret': 'Invalid API key'})
async with session.post(BOT_URL, data=json.dumps({'text': 3, 'key': KEY})) as response:
# TODO: we are not sending to a real room, so this should not be "OK"
self.assertEqual(await response.json(), {'status': 200, 'ret': 'OK'})
async def test_message(self): async def test_message(self):
"""Send a markdown message, and check the result.""" """Send a markdown message, and check the result."""
@ -33,19 +38,32 @@ class BotTest(AbstractBotTest):
client = nio.AsyncClient(MATRIX_URL, MATRIX_ID) client = nio.AsyncClient(MATRIX_URL, MATRIX_ID)
await client.login(MATRIX_PW) await client.login(MATRIX_PW)
room = await client.room_create() room = await client.room_create()
url = f'{BOT_URL}/{room.room_id}' self.assertEqual(bot_req({'text': text}, KEY, room.room_id), {'status': 200, 'ret': 'OK'})
async with aiohttp.ClientSession() as session:
async with session.post(url, data=json.dumps({'text': text, 'key': KEY})) as response:
self.assertEqual(await response.json(), {'status': 200, 'ret': 'OK'})
sync = await client.sync() sync = await client.sync()
messages = await client.room_messages(room.room_id, sync.next_batch) messages = await client.room_messages(room.room_id, sync.next_batch)
await client.close()
message = messages.chunk[0] message = messages.chunk[0]
self.assertEqual(message.sender, '@bot:tests') self.assertEqual(message.sender, FULL_ID)
self.assertEqual(message.body, text) self.assertEqual(message.body, text)
self.assertEqual(message.formatted_body, '<h1>Hello</h1>') self.assertEqual(message.formatted_body, '<h1>Hello</h1>')
async def test_z_disconnected(self):
"""Send a message after disconnection, and check the error."""
client = nio.AsyncClient(MATRIX_URL, MATRIX_ID)
await client.login(MATRIX_PW)
token = client.access_token
resp = httpx.post(f'{MATRIX_URL}/_synapse/admin/v1/deactivate/{FULL_ID}',
json={'erase': True},
params={'access_token': token})
self.assertEqual(resp.json(), {'id_server_unbind_result': 'success'})
await client.logout(all_devices=True)
await client.close() await client.close()
# TODO: I was hopping that one wouldn't be happy
self.assertEqual(bot_req({'text': 'bye'}, KEY), {'status': 200, 'ret': 'OK'})

View file

@ -1,50 +0,0 @@
"""Utility tools to run tests."""
import asyncio
import os
import time
import unittest
import aiohttp
import yaml
from synapse._scripts.register_new_matrix_user import request_registration
BOT_URL = 'http://localhost:4785'
MATRIX_URL, MATRIX_ID, MATRIX_PW = (os.environ[v] for v in ['MATRIX_URL', 'MATRIX_ID', 'MATRIX_PW'])
class AbstractBotTest(unittest.IsolatedAsyncioTestCase):
"""Abstract test class."""
async def asyncSetUp(self):
"""Set up the test environment."""
# Wait for synapse and the bot to answer
self.assertTrue(
all(await asyncio.gather(
wait_available(f'{MATRIX_URL}/_matrix/client/r0/login', 'flows'),
wait_available(BOT_URL, 'status'),
)))
# Try to register an user for the bot. Don't worry if it already exists.
with open('/srv/homeserver.yaml') as f:
secret = yaml.safe_load(f.read()).get("registration_shared_secret", None)
request_registration(MATRIX_ID, MATRIX_PW, MATRIX_URL, secret, admin=False, user_type=None, exit=lambda x: x)
async def check_json(session: aiohttp.ClientSession, url: str, key: str) -> bool:
"""Ensure a service at a given url answers with valid json containing a certain key."""
try:
async with session.get(url) as response:
data = await response.json()
return key in data
except aiohttp.client_exceptions.ClientConnectorError:
return False
async def wait_available(url: str, key: str, timeout: int = 60) -> bool:
"""Wait until a service answer correctly or timeout."""
start = time.time()
async with aiohttp.ClientSession() as session:
while True:
if await check_json(session, url, key):
return True
if time.time() > start + timeout:
return False