From 46934f20aef34cf8fc3faea952d3007d5599cf0b Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jan 23 2019 13:49:44 +0000 Subject: [PATCH 1/4] Move settings all the routes in a dedicate function This way it can be re-used in the tests. Signed-off-by: Pierre-Yves Chibon --- diff --git a/mdapi/__init__.py b/mdapi/__init__.py index 3c56044..df70827 100644 --- a/mdapi/__init__.py +++ b/mdapi/__init__.py @@ -427,12 +427,7 @@ def index(request): charset='utf-8') -@asyncio.coroutine -def init(loop): - logging.basicConfig() - logging.config.dictConfig(CONFIG.get('LOGGING') or {'version': 1}) - - app = web.Application(loop=loop) +def _set_routes(app): routes = [] prefix = CONFIG.get('PREFIX', '') if prefix: @@ -459,6 +454,16 @@ def init(loop): ]) for route in routes: app.router.add_route('GET', prefix + route[0], route[1]) + return app + + +@asyncio.coroutine +def init(loop): + logging.basicConfig() + logging.config.dictConfig(CONFIG.get('LOGGING') or {'version': 1}) + + app = web.Application(loop=loop) + app = _set_routes(app) srv = yield from loop.create_server( app.make_handler(), From 99afefb8ceb4478705f5a1c941c3388c95bebca0 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jan 23 2019 13:49:44 +0000 Subject: [PATCH 2/4] Fix the example to working ones in the front page Signed-off-by: Pierre-Yves Chibon --- diff --git a/mdapi/index.html b/mdapi/index.html index 4d3971c..549af20 100644 --- a/mdapi/index.html +++ b/mdapi/index.html @@ -155,14 +155,14 @@ Few examples: packages conflicting with mariadb in rawhide: rawhide/conflicts/mariadb - packages enhancing vagrant in rawhide: - rawhide/enhances/vagrant + packages enhancing httpd in rawhide: + rawhide/enhances/httpd - packages recommending python3-dateutils in rawhide: - rawhide/recommends/python3-dateutils + packages recommending flac in rawhide: + rawhide/recommends/flac - packages suggesting tag in rawhide: - rawhide/suggests/tar + packages suggesting R-tools in rawhide: + rawhide/suggests/R-tools packages supplementing `(hunspell and langpacks-fr)` in rawhide: rawhide/supplements/(hunspell and langpacks-fr) From 630f599e94c24109d3430b834ec110c54ae00f8a Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jan 23 2019 13:50:02 +0000 Subject: [PATCH 3/4] Add unit-tests to mdapi Signed-off-by: Pierre-Yves Chibon --- diff --git a/tests/__test__.py b/tests/__test__.py new file mode 100644 index 0000000..56fafa5 --- /dev/null +++ b/tests/__test__.py @@ -0,0 +1,2 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- diff --git a/tests/test_mdapi_data.py b/tests/test_mdapi_data.py new file mode 100644 index 0000000..58f7604 --- /dev/null +++ b/tests/test_mdapi_data.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# Copyright © 2019 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions +# of the GNU General Public License v.2, or (at your option) any later +# version. This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. You +# should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Any Red Hat trademarks that are incorporated in the source +# code or documentation are not subject to the GNU General Public +# License and may only be used or replicated with the express permission +# of Red Hat, Inc. +# + +''' +Tests for mdapi. + +''' +import json +import os +import shutil +import subprocess +import sys +import tempfile + +import pytest +from aiohttp import web + +sys.path.insert(0, os.path.join(os.path.dirname( + os.path.abspath(__file__)), '..')) + +import mdapi + +HERE = os.path.join(os.path.dirname(os.path.abspath(__file__))) + +TMPDIR = None + +@pytest.fixture(scope="session", autouse=True) +def set_env(request): + """ + Collects the sqlite database from the mirror to have some data to test + against. + """ + global TMPDIR + TMPDIR = tempfile.mkdtemp(prefix="mdapi-test-") + print("Creating %s" % TMPDIR) + configfile = os.path.join(TMPDIR, "config") + + with open(configfile, "w") as stream: + stream.write("DB_FOLDER = '%s'\n" % TMPDIR) + + print("Downloading the databases...") + subprocess.check_output( + ["../mdapi-get_repo_md", configfile], + cwd=HERE, + ) + assert len(os.listdir(TMPDIR)) > 2 + + def clean_up(): + print("\nRemoving %s" % TMPDIR) + shutil.rmtree(TMPDIR) + request.addfinalizer(clean_up) + + +@pytest.fixture +def tmpdir(): + return TMPDIR + + +@pytest.fixture +def cli(tmpdir, loop, aiohttp_client): + mdapi.CONFIG['DB_FOLDER'] = tmpdir + app = web.Application() + app = mdapi._set_routes(app) + return loop.run_until_complete(aiohttp_client(app)) + + +async def test_view_index_page(cli): + resp = await cli.get('/') + assert resp.status == 200 + header = r""" + _ _ + | | (_) + _ __ ___ __| | __ _ _ __ _ +| '_ ` _ \ / _` |/ _` | '_ \| | +| | | | | | (_| | (_| | |_) | | +|_| |_| |_|\__,_|\__,_| .__/|_| + | | + |_| +""" + output = await resp.text() + assert header in output + + +async def test_view_branches(cli): + resp = await cli.get('/branches') + assert resp.status == 200 + assert '["dist-6E", "dist-6E-epel", "epel7", "f27", "f28", "f29", ' \ + '"koji", "rawhide", "src_dist-6E", "src_dist-6E-epel", ' \ + '"src_epel7", "src_rawhide"]' == await resp.text() + + +async def test_view_pkg_rawhide(cli): + resp = await cli.get('/rawhide/pkg/kernel') + assert resp.status == 200 + json.loads(await resp.text()) + + +async def test_view_pkg_rawhide_invalid(cli): + resp = await cli.get('/rawhide/pkg/invalidpackagename') + assert resp.status == 404 + assert '404: Not Found' == await resp.text() + + +async def test_view_srcpkg_rawhide(cli): + resp = await cli.get('/rawhide/srcpkg/python-natsort') + assert resp.status == 200 + json.loads(await resp.text()) + + +async def test_view_file_list_rawhide(cli): + resp = await cli.get('/rawhide/files/kernel-core') + assert resp.status == 200 + json.loads(await resp.text()) + + +async def test_view_changelog_rawhide(cli): + resp = await cli.get('/rawhide/changelog/kernel') + assert resp.status == 200 + json.loads(await resp.text()) + + +@pytest.mark.parametrize("action, package, status_code", [ + ("requires", "R", 200), + ("provides", "perl(SetupLog)", 200), + ("provides", "R", 200), + ("obsoletes", "cabal2spec", 200), + ("conflicts", "mariadb", 200), + ("enhances", "httpd", 200), + ("recommends", "flac", 200), + ("suggests", "R-tools", 200), + ("supplements", "(hunspell and langpacks-fr)", 200), +]) +async def test_view_property_koji(cli, action, package, status_code): + resp = await cli.get('/koji/%s/%s' % (action, package)) + assert resp.status == status_code + if status_code == 200: + json.loads(await resp.text()) diff --git a/tests/test_mdapi_empty.py b/tests/test_mdapi_empty.py new file mode 100644 index 0000000..171a998 --- /dev/null +++ b/tests/test_mdapi_empty.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# Copyright © 2019 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions +# of the GNU General Public License v.2, or (at your option) any later +# version. This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. You +# should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Any Red Hat trademarks that are incorporated in the source +# code or documentation are not subject to the GNU General Public +# License and may only be used or replicated with the express permission +# of Red Hat, Inc. +# + +''' +Tests for mdapi. + +''' +import os +import shutil +import subprocess +import sys +import tempfile + +import pytest +from aiohttp import web + +sys.path.insert(0, os.path.join(os.path.dirname( + os.path.abspath(__file__)), '..')) + +import mdapi + +HERE = os.path.join(os.path.dirname(os.path.abspath(__file__))) + + +@pytest.fixture +def cli(loop, aiohttp_client): + mdapi.CONFIG['DB_FOLDER'] = '.' + app = web.Application() + app = mdapi._set_routes(app) + return loop.run_until_complete(aiohttp_client(app)) + + +async def test_view_index_page(cli): + resp = await cli.get('/') + assert resp.status == 200 + header = r""" + _ _ + | | (_) + _ __ ___ __| | __ _ _ __ _ +| '_ ` _ \ / _` |/ _` | '_ \| | +| | | | | | (_| | (_| | |_) | | +|_| |_| |_|\__,_|\__,_| .__/|_| + | | + |_| +""" + output = await resp.text() + assert header in output + + +async def test_view_branches(cli): + resp = await cli.get('/branches') + assert resp.status == 200 + assert '[]' == await resp.text() + + +async def test_view_pkg_rawhide(cli): + resp = await cli.get('/rawhide/pkg/kernel') + assert resp.status == 400 + assert '400: Bad Request' == await resp.text() + + +async def test_view_pkg_rawhide_invalid(cli): + resp = await cli.get('/rawhide/pkg/invalidpackagename') + assert resp.status == 400 + assert '400: Bad Request' == await resp.text() + + +async def test_view_srcpkg_rawhide(cli): + resp = await cli.get('/rawhide/srcpkg/python-natsort') + assert resp.status == 400 + assert '400: Bad Request' == await resp.text() + + +async def test_view_file_list_rawhide(cli): + resp = await cli.get('/rawhide/files/kernel-core') + assert resp.status == 400 + assert '400: Bad Request' == await resp.text() + + +async def test_view_changelog_rawhide(cli): + resp = await cli.get('/rawhide/changelog/kernel') + assert resp.status == 400 + assert '400: Bad Request' == await resp.text() + + +@pytest.mark.parametrize("action", [ + "requires", "provides", "obsoletes", "conflicts", + "enhances", "recommends", "suggests", "supplements", +]) +async def test_view_property_koji(cli, action): + resp = await cli.get('/koji/%s/R' % action) + assert resp.status == 400 + assert '400: Bad Request' == await resp.text() From 54bfc6fca9c763b280dc0301f6fce76b716afb43 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jan 23 2019 13:52:33 +0000 Subject: [PATCH 4/4] Add tox as a test executioner Signed-off-by: Pierre-Yves Chibon --- diff --git a/.gitignore b/.gitignore index 6cc902c..bc39beb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ dist/ *~ .coverage alembic.ini +.tox/ +.pytest_cache/ diff --git a/tests/test_mdapi_data.py b/tests/test_mdapi_data.py index 58f7604..3dd140c 100644 --- a/tests/test_mdapi_data.py +++ b/tests/test_mdapi_data.py @@ -32,8 +32,10 @@ import subprocess import sys import tempfile +import mock import pytest from aiohttp import web +from sqlalchemy.exc import SQLAlchemyError sys.path.insert(0, os.path.join(os.path.dirname( os.path.abspath(__file__)), '..')) @@ -44,7 +46,7 @@ HERE = os.path.join(os.path.dirname(os.path.abspath(__file__))) TMPDIR = None -@pytest.fixture(scope="session", autouse=True) +@pytest.fixture(scope="module") def set_env(request): """ Collects the sqlite database from the mirror to have some data to test @@ -77,7 +79,7 @@ def tmpdir(): @pytest.fixture -def cli(tmpdir, loop, aiohttp_client): +def cli(set_env, tmpdir, loop, aiohttp_client): mdapi.CONFIG['DB_FOLDER'] = tmpdir app = web.Application() app = mdapi._set_routes(app) @@ -104,9 +106,9 @@ async def test_view_index_page(cli): async def test_view_branches(cli): resp = await cli.get('/branches') assert resp.status == 200 - assert '["dist-6E", "dist-6E-epel", "epel7", "f27", "f28", "f29", ' \ - '"koji", "rawhide", "src_dist-6E", "src_dist-6E-epel", ' \ - '"src_epel7", "src_rawhide"]' == await resp.text() + output = await resp.text() + assert 'src_rawhide' in output + assert 'rawhide' in output async def test_view_pkg_rawhide(cli): diff --git a/tests/test_mdapi_empty.py b/tests/test_mdapi_empty.py index 171a998..484cb8b 100644 --- a/tests/test_mdapi_empty.py +++ b/tests/test_mdapi_empty.py @@ -38,6 +38,7 @@ sys.path.insert(0, os.path.join(os.path.dirname( os.path.abspath(__file__)), '..')) import mdapi +import mdapi.lib HERE = os.path.join(os.path.dirname(os.path.abspath(__file__))) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..821a3c0 --- /dev/null +++ b/tox.ini @@ -0,0 +1,17 @@ +[tox] +envlist = py3 +skipsdist = True + +[testenv] +usedevelop = True +passenv = HOME +deps = + -rrequirements.txt + pytest + pytest-cov + pytest-aiohttp + mock +setenv = + PYTHONPATH={toxinidir} +commands = + py.test -s -vv --cov=mdapi {posargs}