Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate autobahn tests with pytest #5809

Merged
merged 28 commits into from
Oct 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ ignore_missing_imports = True

[mypy-uvloop]
ignore_missing_imports = True

[mypy-python_on_whales]
ignore_missing_imports = True
1 change: 1 addition & 0 deletions CHANGES/4247.1.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Automated running autobahn test suite by integrating with pytest.
2 changes: 2 additions & 0 deletions requirements/dev.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
-r test.txt
-r doc.txt
cherry_picker==2.0.0; python_version>="3.6"
python-on-whales==0.19.0
wait-for-it==2.2.0
14 changes: 14 additions & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ click==7.1.2
# cherry-picker
# click-default-group
# towncrier
# typer
# wait-for-it
click-default-group==1.2.2
# via towncrier
coverage[toml]==6.0
Expand Down Expand Up @@ -177,6 +179,8 @@ pycodestyle==2.7.0
# flake8
pycparser==2.20
# via cffi
pydantic==1.8.2
# via python-on-whales
pyflakes==2.3.0
# via
# -r requirements/lint.txt
Expand Down Expand Up @@ -204,6 +208,8 @@ pytest-mock==3.6.1
# via -r requirements/test.txt
python-dateutil==2.8.1
# via freezegun
python-on-whales==0.19.0
# via -r requirements/dev.in
pytz==2020.5
# via babel
pyyaml==5.4.1
Expand All @@ -220,6 +226,7 @@ regex==2020.11.13
requests==2.25.1
# via
# cherry-picker
# python-on-whales
# sphinx
setuptools-git==1.2
# via -r requirements/test.txt
Expand Down Expand Up @@ -272,8 +279,12 @@ towncrier==21.3.0
# via
# -r requirements/doc.txt
# sphinxcontrib-towncrier
tqdm==4.62.2
# via python-on-whales
trustme==0.9.0 ; platform_machine != "i686"
# via -r requirements/test.txt
typer==0.4.0
# via python-on-whales
types-chardet==0.1.3
# via
# -r requirements/lint.txt
Expand All @@ -285,6 +296,7 @@ typing-extensions==3.7.4.3
# async-timeout
# mypy
# proxy.py
# pydantic
uritemplate==3.0.1
# via gidgethub
urllib3==1.26.5
Expand All @@ -293,6 +305,8 @@ virtualenv==20.4.2
# via
# -r requirements/lint.txt
# pre-commit
wait-for-it==2.2.0
# via -r requirements/dev.in
webcolors==1.11.1
# via blockdiag
yarl==1.6.3
Expand Down
1 change: 0 additions & 1 deletion tests/autobahn/.gitignore

This file was deleted.

6 changes: 6 additions & 0 deletions tests/autobahn/Dockerfile.autobahn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM crossbario/autobahn-testsuite:0.8.2

RUN apt-get update && apt-get install python3 python3-pip -y
RUN pip3 install wait-for-it

CMD ["wstest", "--mode", "fuzzingserver", "--spec", "/config/fuzzingserver.json"]
2 changes: 1 addition & 1 deletion tests/autobahn/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ async def run(url: str, name: str) -> None:


if __name__ == "__main__":
asyncio.run(run("http://autobahn:9001", "aiohttp"))
asyncio.run(run("http://localhost:9001", "aiohttp"))
17 changes: 0 additions & 17 deletions tests/autobahn/client/docker-compose.yml

This file was deleted.

6 changes: 0 additions & 6 deletions tests/autobahn/docker-compose.yml

This file was deleted.

12 changes: 0 additions & 12 deletions tests/autobahn/run-tests.sh

This file was deleted.

18 changes: 0 additions & 18 deletions tests/autobahn/server/docker-compose.yml

This file was deleted.

2 changes: 1 addition & 1 deletion tests/autobahn/server/fuzzingclient.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"servers": [
{
"agent": "AutobahnServer",
"url": "ws://aiohttp:9001",
"url": "ws://localhost:9001",
"options": { "version": 18 }
}
],
Expand Down
3 changes: 3 additions & 0 deletions tests/autobahn/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ async def wshandler(request: web.Request) -> web.WebSocketResponse:

await ws.prepare(request)

request.app["websockets"].append(ws)

while True:
msg = await ws.receive()

Expand Down Expand Up @@ -40,6 +42,7 @@ async def on_shutdown(app: web.Application) -> None:
)

app = web.Application()
app["websockets"] = []
app.router.add_route("GET", "/", wshandler)
app.on_shutdown.append(on_shutdown)
try:
Expand Down
132 changes: 132 additions & 0 deletions tests/autobahn/test_autobahn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import json
import subprocess
import sys
from pathlib import Path
from typing import Any, Dict, Generator, List

import pytest
from pytest import TempPathFactory
from python_on_whales import DockerException, docker


@pytest.fixture(scope="session")
def report_dir(tmp_path_factory: TempPathFactory) -> Path:
return tmp_path_factory.mktemp("reports")


@pytest.fixture(scope="session", autouse=True)
def build_autobahn_testsuite() -> Generator[None, None, None]:

try:
docker.build(
file="tests/autobahn/Dockerfile.autobahn",
tags=["autobahn-testsuite"],
context_path=".",
)
except DockerException:
pytest.skip(msg="The docker daemon is not running.")

try:
yield
finally:
docker.image.remove(x="autobahn-testsuite")


def get_failed_tests(report_path: str, name: str) -> List[Dict[str, Any]]:
path = Path(report_path)
result_summary = json.loads((path / "index.json").read_text())[name]
failed_messages = []
PASS = {"OK", "INFORMATIONAL"}
entry_fields = {"case", "description", "expectation", "expected", "received"}
for results in result_summary.values():
if results["behavior"] in PASS and results["behaviorClose"] in PASS:
continue
report = json.loads((path / results["reportfile"]).read_text())
failed_messages.append({field: report[field] for field in entry_fields})
return failed_messages


@pytest.mark.skipif(sys.platform == "darwin", reason="Don't run on macOS")
@pytest.mark.xfail
def test_client(report_dir: Path, request: Any) -> None:
try:
print("Starting autobahn-testsuite server")
autobahn_container = docker.run(
detach=True,
image="autobahn-testsuite",
name="autobahn",
publish=[(9001, 9001)],
remove=True,
volumes=[
(f"{request.fspath.dirname}/client", "/config"),
(f"{report_dir}", "/reports"),
],
)
print("Running aiohttp test client")
client = subprocess.Popen(
["wait-for-it", "-s", "localhost:9001", "--"]
+ [sys.executable]
+ ["tests/autobahn/client/client.py"]
)
client.wait()
finally:
print("Stopping client and server")
client.terminate()
client.wait()
autobahn_container.stop()

failed_messages = get_failed_tests(f"{report_dir}/clients", "aiohttp")

assert not failed_messages, "\n".join(
"\n\t".join(
f"{field}: {msg[field]}"
for field in ("case", "description", "expectation", "expected", "received")
)
for msg in failed_messages
)


@pytest.mark.skipif(sys.platform == "darwin", reason="Don't run on macOS")
@pytest.mark.xfail
def test_server(report_dir: Path, request: Any) -> None:
try:
print("Starting aiohttp test server")
server = subprocess.Popen(
[sys.executable] + ["tests/autobahn/server/server.py"]
)
print("Starting autobahn-testsuite client")
docker.run(
image="autobahn-testsuite",
name="autobahn",
remove=True,
volumes=[
(f"{request.fspath.dirname}/server", "/config"),
(f"{report_dir}", "/reports"),
],
networks=["host"],
command=[
"wait-for-it",
"-s",
"localhost:9001",
"--",
"wstest",
"--mode",
"fuzzingclient",
"--spec",
"/config/fuzzingclient.json",
],
)
finally:
print("Stopping client and server")
server.terminate()
server.wait()

failed_messages = get_failed_tests(f"{report_dir}/servers", "AutobahnServer")

assert not failed_messages, "\n".join(
"\n\t".join(
f"{field}: {msg[field]}"
for field in ("case", "description", "expectation", "expected", "received")
)
for msg in failed_messages
)