diff --git a/.coveragerc b/.coveragerc index 02b787e9..bd4aa6c5 100644 --- a/.coveragerc +++ b/.coveragerc @@ -7,5 +7,7 @@ omit = **/tests/*.py env* settings.py + conftest.py local_settings.py /home/travis/virtualenv* + manage.py diff --git a/.gitignore b/.gitignore index e047ef4a..b6abcfbc 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ env/ # coverage .coverage +htmlcov diff --git a/.travis.yml b/.travis.yml index 03bb6f46..ec4afab7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,12 @@ language: python python: - "3.7" cache: pip -install: "pip install -r requirements.txt && pip install coveralls pylint" +install: "pip install -r requirements.txt && pip install -r requirements_test.txt" script: - - python manage.py collectstatic --noinput - - coverage run --rcfile .coveragerc manage.py test - - pylint devel main mirrors news packages releng templates todolists visualize *.py + - make collectstatic + - make lint + - make coverage after_success: - coveralls diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..1e244ded --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +PYTHON>=python +PYTEST?=pytest +PYTEST_OPTIONS+= +PYTEST_INPUT?=. +PYTEST_COVERAGE_OPTIONS+=--cov-report=term-missing --cov-report=html:htmlcov --cov=. +PYTEST_PDB?=0 +PYTEST_PDB_OPTIONS?=--pdb --pdbcls=IPython.terminal.debugger:TerminalPdb + + +ifeq (${PYTEST_PDB},1) +PYTEST_OPTIONS+= ${PYTEST_PDB_OPTIONS} +else +test-pdb: PYTEST_OPTIONS+= ${PYTEST_PDB_OPTIONS} +endif +test-pdb: test + + +.PHONY: test lint coverage + +lint: + pylint devel main mirrors news packages releng templates todolists visualize *.py + +collectstatic: + python manage.py collectstatic --noinput + +test: test-py + +test-py coverage: + DJANGO_SETTINGS_MODULE=settings ${PYTEST} ${PYTEST_OPTIONS} ${PYTEST_COVERAGE_OPTIONS} ${PYTEST_INPUT} + +open-coverage: coverage + ${BROWSER} htmlcov/index.html diff --git a/README.md b/README.md index 2f3c050a..faab8c17 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,6 @@ packages, you will probably want the following: ./manage.py loaddata main/fixtures/*.json ./manage.py loaddata devel/fixtures/*.json ./manage.py loaddata mirrors/fixtures/*.json - ./manage.py loaddata releng/fixtures/*.json 6. Use the following commands to start a service instance @@ -96,6 +95,10 @@ In local\_settings.py add entries to set EMAIL\_HOST to 'localhost' and EMAIL\_P # Running tests and coverage +Install the test dependencies: + + pip install -r requirements_text.txt + To the unittests execute the following commands: ./manage.py collectstatic --noinput @@ -103,7 +106,6 @@ To the unittests execute the following commands: Running coverage: - pip install coverage coverage run --omit='env*' --source='.' manage.py test coverage report diff --git a/conftest.py b/conftest.py new file mode 100644 index 00000000..064f0e17 --- /dev/null +++ b/conftest.py @@ -0,0 +1,60 @@ +import pytest + +from django.contrib.auth.models import Group +from django.core.management import call_command + +from devel.models import UserProfile + + +USERNAME = 'joeuser' +FIRSTNAME = 'Joe' +LASTNAME = 'User' +EMAIL = 'user1@example.com' + + +@pytest.fixture +def arches(db): + call_command('loaddata', 'main/fixtures/arches.json') + + +@pytest.fixture +def repos(db): + call_command('loaddata', 'main/fixtures/repos.json') + + +@pytest.fixture +def package(db, arches, repos): + # TODO: convert to create_package with standard parameters + call_command('loaddata', 'main/fixtures/package.json') + + +@pytest.fixture +def groups(db): + call_command('loaddata', 'main/fixtures/groups.json') + + +@pytest.fixture +def staff_groups(db): + call_command('loaddata', 'devel/fixtures/staff_groups.json') + + +@pytest.fixture +def user(django_user_model): + user = django_user_model.objects.create_user(username=USERNAME, password=USERNAME) + yield user + user.delete() + + +@pytest.fixture +def userprofile(user): + profile = UserProfile.objects.create(user=user, + public_email=f'{user.username}@archlinux.org') + yield profile + profile.delete() + + +@pytest.fixture +def user_client(client, user, userprofile, groups): + user.groups.add(Group.objects.get(name='Developers')) + client.login(username=USERNAME, password=USERNAME) + return client diff --git a/devel/tests/test_devel.py b/devel/tests/test_devel.py index c8a28c1a..6835456b 100644 --- a/devel/tests/test_devel.py +++ b/devel/tests/test_devel.py @@ -1,42 +1,14 @@ -from django.test import TransactionTestCase -from django.contrib.auth.models import User, Group -from devel.models import UserProfile +def test_clock(user_client): + response = user_client.get('/devel/clock/') + assert response.status_code == 200 -class DevelView(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] +def test_profile(user_client): + response = user_client.get('/devel/profile/') + assert response.status_code == 200 + # Test changing - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - for name in ['Developers', 'Retired Developers']: - Group.objects.create(name=name) - self.user.groups.add(Group.objects.get(name='Developers')) - self.user.save() - self.profile = UserProfile.objects.create(user=self.user, - public_email="{}@awesome.com".format(self.user.username)) - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - def tearDown(self): - self.profile.delete() - self.user.delete() - Group.objects.all().delete() - - def test_clock(self): - response = self.client.get('/devel/clock/') - self.assertEqual(response.status_code, 200) - - def test_profile(self): - response = self.client.get('/devel/profile/') - self.assertEqual(response.status_code, 200) - # Test changing - - def test_stats(self): - response = self.client.get('/devel/stats/') - self.assertEqual(response.status_code, 200) +def test_stats(user_client): + response = user_client.get('/devel/stats/') + assert response.status_code == 200 diff --git a/devel/tests/test_pgp_import.py b/devel/tests/test_pgp_import.py index f01e73a3..f7f4e67b 100644 --- a/devel/tests/test_pgp_import.py +++ b/devel/tests/test_pgp_import.py @@ -1,8 +1,9 @@ from unittest.mock import patch +import pytest + from django.core.management import call_command from django.core.management.base import CommandError -from django.test import TransactionTestCase CREATED = 1541685162 @@ -19,28 +20,26 @@ ] -class PGPImportTest(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json'] - - def test_pgp_import_error(self): - with self.assertRaises(CommandError) as e: - call_command('pgp_import') - self.assertIn('keyring_path', str(e.exception)) - - @patch('devel.management.commands.pgp_import.call_gpg') - def test_pgp_import_garbage_data(self, mock_call_gpg): - mock_call_gpg.return_value = 'barf' - with patch('devel.management.commands.pgp_import.logger') as logger: - call_command('pgp_import', '/tmp') - logger.info.assert_called() - logger.info.assert_any_call('created %d, updated %d signatures', 0, 0) - logger.info.assert_any_call('created %d, updated %d keys', 0, 0) - - @patch('devel.management.commands.pgp_import.call_gpg') - def test_pgp_import(self, mock_call_gpg): - mock_call_gpg.return_value = '\n'.join(SIG_DATA) - with patch('devel.management.commands.pgp_import.logger') as logger: - call_command('pgp_import', '/tmp') - logger.info.assert_called() - logger.info.assert_any_call('created %d, updated %d signatures', 0, 0) - logger.info.assert_any_call('created %d, updated %d keys', 1, 0) +def test_pgp_import_error(arches, repos): + with pytest.raises(CommandError) as e: + call_command('pgp_import') + assert 'keyring_path' in str(e.value) + + +@patch('devel.management.commands.pgp_import.call_gpg') +def test_pgp_import_garbage_data(mock_call_gpg, arches, repos): + mock_call_gpg.return_value = 'barf' + with patch('devel.management.commands.pgp_import.logger') as logger: + call_command('pgp_import', '/tmp') + logger.info.assert_called() + logger.info.assert_any_call('created %d, updated %d signatures', 0, 0) + logger.info.assert_any_call('created %d, updated %d keys', 0, 0) + +@patch('devel.management.commands.pgp_import.call_gpg') +def test_pgp_import(mock_call_gpg, arches, repos): + mock_call_gpg.return_value = '\n'.join(SIG_DATA) + with patch('devel.management.commands.pgp_import.logger') as logger: + call_command('pgp_import', '/tmp') + logger.info.assert_called() + logger.info.assert_any_call('created %d, updated %d signatures', 0, 0) + logger.info.assert_any_call('created %d, updated %d keys', 1, 0) diff --git a/devel/tests/test_rematch_developers.py b/devel/tests/test_rematch_developers.py index 07daf50f..8dbbdfdf 100644 --- a/devel/tests/test_rematch_developers.py +++ b/devel/tests/test_rematch_developers.py @@ -1,14 +1,9 @@ from unittest.mock import patch - from django.core.management import call_command -from django.test import TransactionTestCase - -class RematchDeveloperTest(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json'] - def test_rematch_developers(self): - with patch('devel.management.commands.rematch_developers.logger') as logger: - call_command('rematch_developers') - logger.info.assert_called() +def test_rematch_developers(arches, repos): + with patch('devel.management.commands.rematch_developers.logger') as logger: + call_command('rematch_developers') + logger.info.assert_called() diff --git a/devel/tests/test_reporead.py b/devel/tests/test_reporead.py index 0ffe3a17..d6eefd86 100644 --- a/devel/tests/test_reporead.py +++ b/devel/tests/test_reporead.py @@ -2,10 +2,10 @@ from unittest.mock import patch from datetime import datetime +import pytest from django.core.management import call_command from django.core.management.base import CommandError -from django.test import TransactionTestCase from django.utils import timezone @@ -13,82 +13,95 @@ from packages.models import FlagRequest -# Django's TestCase is wrapped in transaction, therefore use TransactionTestCase -class RepoReadTest(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json'] +@pytest.fixture +def create_pkg(arches, repos): + packages = [] - def create_pkg(self, repo=None, pkgver='4.10.1', pkgrel='1'): + def _create_pkg(repo=None, pkgver='4.10.1', pkgrel='1'): if not repo: repo = Repo.objects.get(name__iexact='core') arch = Arch.objects.get(name__iexact='any') now = datetime.now(tz=timezone.utc) - return Package.objects.create(arch=arch, repo=repo, pkgname='systemd', - pkgbase='systemd', pkgver=pkgver, - pkgrel=pkgrel, pkgdesc='Linux kernel', - compressed_size=10, installed_size=20, - last_update=now, created=now) - - def test_invalid_args(self): - with self.assertRaises(CommandError) as e: - call_command('reporead') - self.assertIn('missing arch and file.', str(e.exception)) - - with self.assertRaises(CommandError) as e: - call_command('reporead', 'x86_64') - self.assertIn('Package database file is required.', str(e.exception)) - - with self.assertRaises(CommandError) as e: - call_command('reporead', 'x86_64', 'nothing.db.tar.gz') - self.assertIn('Specified package database file does not exist.', str(e.exception)) - - def test_invalid_arch(self): - with self.assertRaises(CommandError) as e: - call_command('reporead', 'armv64', 'devel/fixtures/core.db.tar.gz') - self.assertEqual('Specified architecture armv64 is not currently known.', str(e.exception)) - - def test_read_packages(self): - with patch('devel.management.commands.reporead.logger') as logger: - call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') - logger.info.assert_called() - - # Verify contents - with tarfile.open('devel/fixtures/core.db.tar.gz') as tar: - files = [name.replace('core.db/', '') for name in tar.getnames() if name != 'core.db' and not 'desc' in name] - - packages = Package.objects.all() - import_packages = ["{}-{}-{}".format(pkg.pkgname, pkg.pkgver, pkg.pkgrel) for pkg in packages] - self.assertCountEqual(files, import_packages) - - def test_flagoutofdate(self): - pkg = self.create_pkg() - FlagRequest.objects.create(pkgbase=pkg.pkgbase, repo=pkg.repo, - pkgver=pkg.pkgver, epoch=pkg.epoch, - ip_address='1.1.1.1') - - with patch('devel.management.commands.reporead.logger') as logger: - call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') - logger.info.assert_called() - - self.assertEqual(len(FlagRequest.objects.all()), 0) - - def test_flagoutofdate_staging(self): - staging = Repo.objects.get(name__iexact='staging') - - pkg = self.create_pkg() - staging_pkg = self.create_pkg(repo=staging, pkgrel='2') - - FlagRequest.objects.create(pkgbase=pkg.pkgbase, repo=pkg.repo, - pkgver=pkg.pkgver, epoch=pkg.epoch, - ip_address='1.1.1.1') - FlagRequest.objects.create(pkgbase=staging_pkg.pkgbase, repo=staging_pkg.repo, - pkgver=staging_pkg.pkgver, epoch=staging_pkg.epoch, - ip_address='1.1.1.1') - - with patch('devel.management.commands.reporead.logger') as logger: - call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') - logger.info.assert_called() - - objects = FlagRequest.objects.all() - self.assertEqual(len(objects), 1) - self.assertEqual(objects[0].pkgver, staging_pkg.pkgver) + package = Package.objects.create(arch=arch, repo=repo, pkgname='systemd', + pkgbase='systemd', pkgver=pkgver, + pkgrel=pkgrel, pkgdesc='Linux kernel', + compressed_size=10, installed_size=20, + last_update=now, created=now) + packages.append(package) + return package + + yield _create_pkg + + for package in packages: + package.delete() + + +def test_invalid_args(): + with pytest.raises(CommandError) as excinfo: + call_command('reporead') + assert 'missing arch and file.' in str(excinfo) + + with pytest.raises(CommandError) as excinfo: + call_command('reporead', 'x86_64') + assert 'Package database file is required.' in str(excinfo) + + with pytest.raises(CommandError) as excinfo: + call_command('reporead', 'x86_64', 'nothing.db.tar.gz') + assert 'Specified package database file does not exist.' in str(excinfo) + + +def test_invalid_arch(transactional_db, arches, repos): + with pytest.raises(CommandError) as excinfo: + call_command('reporead', 'armv64', 'devel/fixtures/core.db.tar.gz') + assert 'Specified architecture armv64 is not currently known.' in str(excinfo) + + +# TODO: create pacman repo db with a pytest fixture +def test_read_packages(transactional_db, arches, repos): + with patch('devel.management.commands.reporead.logger') as logger: + call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') + logger.info.assert_called() + + # Verify contents + with tarfile.open('devel/fixtures/core.db.tar.gz') as tar: + files = [name.replace('core.db/', '') for name in tar.getnames() if name != 'core.db' and not 'desc' in name] + + packages = Package.objects.all() + import_packages = ["{}-{}-{}".format(pkg.pkgname, pkg.pkgver, pkg.pkgrel) for pkg in packages] + assert len(files) == len(import_packages) + + +def test_flagoutofdate(transactional_db, create_pkg): + pkg = create_pkg() + FlagRequest.objects.create(pkgbase=pkg.pkgbase, repo=pkg.repo, + pkgver=pkg.pkgver, epoch=pkg.epoch, + ip_address='1.1.1.1') + + with patch('devel.management.commands.reporead.logger') as logger: + call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') + logger.info.assert_called() + + assert not len(FlagRequest.objects.all()) + + +def test_flagoutofdate_staging(transactional_db, create_pkg): + staging = Repo.objects.get(name__iexact='staging') + + pkg = create_pkg() + staging_pkg = create_pkg(repo=staging, pkgrel='2') + + FlagRequest.objects.create(pkgbase=pkg.pkgbase, repo=pkg.repo, + pkgver=pkg.pkgver, epoch=pkg.epoch, + ip_address='1.1.1.1') + FlagRequest.objects.create(pkgbase=staging_pkg.pkgbase, repo=staging_pkg.repo, + pkgver=staging_pkg.pkgver, epoch=staging_pkg.epoch, + ip_address='1.1.1.1') + + with patch('devel.management.commands.reporead.logger') as logger: + call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz') + logger.info.assert_called() + + objects = FlagRequest.objects.all() + assert len(objects) == 1 + assert objects[0].pkgver == staging_pkg.pkgver diff --git a/devel/tests/test_reports.py b/devel/tests/test_reports.py index 2906d940..0e37f519 100644 --- a/devel/tests/test_reports.py +++ b/devel/tests/test_reports.py @@ -1,60 +1,61 @@ -from django.test import TransactionTestCase -from django.contrib.auth.models import User - - -class DeveloperReport(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - self.user.delete() - - def test_overview(self): - response = self.client.get('/devel/') - self.assertEqual(response.status_code, 200) - - def test_reports_old(self): - response = self.client.get('/devel/reports/old', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_outofdate(self): - response = self.client.get('/devel/reports/long-out-of-date', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_big(self): - response = self.client.get('/devel/reports/big', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_badcompression(self): - response = self.client.get('/devel/reports/badcompression', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_uncompressed_man(self): - response = self.client.get('/devel/reports/uncompressed-man', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_uncompressed_info(self): - response = self.client.get('/devel/reports/uncompressed-info', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_unneeded_orphans(self): - response = self.client.get('/devel/reports/unneeded-orphans', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_mismatched_signature(self): - response = self.client.get('/devel/reports/mismatched-signature', follow=True) - self.assertEqual(response.status_code, 200) - - def test_reports_signature_time(self): - response = self.client.get('/devel/reports/signature-time', follow=True) - self.assertEqual(response.status_code, 200) +import pytest + + +@pytest.fixture +def report_client(user_client, arches, repos, package): + return user_client + + +def test_overview(report_client): + response = report_client.get('/devel/') + assert response.status_code == 200 + + +def test_reports_old(report_client): + response = report_client.get('/devel/reports/old', follow=True) + assert response.status_code == 200 + + +def test_reports_outofdate(report_client): + response = report_client.get('/devel/reports/long-out-of-date', follow=True) + assert response.status_code == 200 + + +def test_reports_big(report_client): + response = report_client.get('/devel/reports/big', follow=True) + assert response.status_code == 200 + + +def test_reports_badcompression(report_client): + response = report_client.get('/devel/reports/badcompression', follow=True) + assert response.status_code == 200 + + +def test_reports_uncompressed_man(report_client): + response = report_client.get('/devel/reports/uncompressed-man', follow=True) + assert response.status_code == 200 + + +def test_reports_uncompressed_info(report_client): + response = report_client.get('/devel/reports/uncompressed-info', follow=True) + assert response.status_code == 200 + + +def test_reports_unneeded_orphans(report_client): + response = report_client.get('/devel/reports/unneeded-orphans', follow=True) + assert response.status_code == 200 + + +def test_reports_mismatched_signature(report_client): + response = report_client.get('/devel/reports/mismatched-signature', follow=True) + assert response.status_code == 200 + + +def test_reports_signature_time(report_client): + response = report_client.get('/devel/reports/signature-time', follow=True) + assert response.status_code == 200 + + +def test_non_existing_dependencies(report_client): + response = report_client.get('/devel/reports/non-existing-dependencies', follow=True) + assert response.status_code == 200 diff --git a/devel/tests/test_templatetags.py b/devel/tests/test_templatetags.py index e5d9782a..47de68dd 100644 --- a/devel/tests/test_templatetags.py +++ b/devel/tests/test_templatetags.py @@ -1,11 +1,5 @@ -from django.contrib.auth.models import User -from django.test import TestCase - from devel.templatetags.group import in_group -class DevelTemplatetagsTest(TestCase): - def test_in_group(self): - user = User.objects.create(username="joeuser", first_name="Joe", - last_name="User", email="user1@example.com") - self.assertEqual(in_group(user, 'none'), False) +def test_in_group(admin_user): + assert in_group(admin_user, 'none') == False diff --git a/devel/tests/test_user.py b/devel/tests/test_user.py index 91c0b1e6..6f434824 100644 --- a/devel/tests/test_user.py +++ b/devel/tests/test_user.py @@ -1,135 +1,177 @@ -from django.contrib.auth.models import User -from django.test import TestCase +import pytest + +from django.contrib.auth.models import User from devel.utils import UserFinder from devel.models import UserProfile -class DevelTest(TestCase): - def test_index(self): - response = self.client.get('/devel/') - self.assertEqual(response.status_code, 302) - self.assertEqual(response.has_header('Location'), True) - self.assertEqual(response['location'], - '/login/?next=/devel/') - - def test_profile(self): - response = self.client.get('/devel/profile/') - self.assertEqual(response.status_code, 302) - self.assertEqual(response.has_header('Location'), True) - self.assertEqual(response['location'], - '/login/?next=/devel/profile/') - - def test_newuser(self): - response = self.client.get('/devel/newuser/') - self.assertEqual(response.status_code, 302) - self.assertEqual(response.has_header('Location'), True) - self.assertEqual(response['location'], - '/login/?next=/devel/newuser/') - - def test_mirrors(self): - response = self.client.get('/mirrors/') - self.assertEqual(response.status_code, 200) - - def test_admin_log(self): - User.objects.create_superuser('admin', 'admin@archlinux.org', 'admin') - response = self.client.post('/login/', {'username': 'admin', 'password': 'admin'}) - response = self.client.get('/devel/admin_log', follow=True) - self.assertEqual(response.status_code, 200) - -class FindUserTest(TestCase): - - def setUp(self): - self.finder = UserFinder() - - self.user1 = User.objects.create(username="joeuser", first_name="Joe", - last_name="User", email="user1@example.com") - self.user2 = User.objects.create(username="john", first_name="John", - last_name="", email="user2@example.com") - self.user3 = User.objects.create(username="bjones", first_name="Bob", - last_name="Jones", email="user3@example.com") - - for user in (self.user1, self.user2, self.user3): - email_addr = "%s@awesome.com" % user.username - UserProfile.objects.create(user=user, public_email=email_addr) - - self.user4 = User.objects.create(username="tim1", first_name="Tim", - last_name="One", email="tim@example.com") - self.user5 = User.objects.create(username="tim2", first_name="Tim", - last_name="Two", email="timtwo@example.com") - - def test_not_matching(self): - self.assertIsNone(self.finder.find(None)) - self.assertIsNone(self.finder.find("")) - self.assertIsNone(self.finder.find("Bogus")) - self.assertIsNone(self.finder.find("Bogus ")) - self.assertIsNone(self.finder.find("")) - self.assertIsNone(self.finder.find("bogus@example.com")) - self.assertIsNone(self.finder.find("Unknown Packager")) - - def test_by_email(self): - self.assertEqual(self.user1, - self.finder.find("XXX YYY ")) - self.assertEqual(self.user2, - self.finder.find("YYY ZZZ ")) - - def test_by_profile_email(self): - self.assertEqual(self.user1, - self.finder.find("XXX ")) - self.assertEqual(self.user2, - self.finder.find("YYY ")) - self.assertEqual(self.user3, - self.finder.find("ZZZ ")) - - def test_by_name(self): - self.assertEqual(self.user1, - self.finder.find("Joe User ")) - self.assertEqual(self.user1, - self.finder.find("Joe User")) - self.assertEqual(self.user2, - self.finder.find("John ")) - self.assertEqual(self.user2, - self.finder.find("John")) - self.assertEqual(self.user3, - self.finder.find("Bob Jones ")) - - def test_by_invalid(self): - self.assertEqual(self.user1, - self.finder.find("Joe User ")) - self.assertEqual(self.user3, - self.finder.find("Bob Jones ")) - - def test_ambiguous(self): - self.assertEqual(self.user4, - self.finder.find("Tim One ")) - self.assertEqual(self.user5, - self.finder.find("Tim Two ")) - self.assertIsNone(self.finder.find("Tim ")) - - def test_find_by_username(self): - self.assertEqual(self.finder.find_by_username(None), None) - self.assertEqual(self.finder.find_by_username('noone'), None) - self.assertEqual(self.finder.find_by_username(self.user1.username), self.user1) - # Test cache - self.assertEqual(self.finder.find_by_username(self.user1.username), self.user1) - - def test_find_by_email(self): - self.assertEqual(self.finder.find_by_email(None), None) - self.assertEqual(self.finder.find_by_email('bar@bar.com'), None) - self.assertEqual(self.finder.find_by_email(self.user1.email), self.user1) - # Test cache - self.assertEqual(self.finder.find_by_email(self.user1.email), self.user1) + +def test_index(client): + response = client.get('/devel/') + assert response.status_code == 302 + assert response.has_header('Location') + assert response['location'] == '/login/?next=/devel/' + + +def test_profile(client): + response = client.get('/devel/profile/') + assert response.status_code == 302 + assert response.has_header('Location') + assert response['location'] == '/login/?next=/devel/profile/' + + +def test_newuser(client): + response = client.get('/devel/newuser/') + assert response.status_code == 302 + assert response.has_header('Location') + assert response['location'] == '/login/?next=/devel/newuser/' + + +def test_mirrors(client, db): + response = client.get('/mirrors/') + assert response.status_code == 200 + + +def test_admin_log(admin_client): + response = admin_client.get('/devel/admin_log', follow=True) + assert response.status_code == 200 + + +@pytest.fixture +def user1(django_user_model): + user1 = django_user_model.objects.create(username="joeuser", first_name="Joe", + last_name="User", email="user1@example.com") + email_addr = "%s@awesome.com" % user1.username + profile = UserProfile.objects.create(user=user1, public_email=email_addr) + yield user1 + profile.delete() + user1.delete() + + +@pytest.fixture +def create_user(django_user_model): + users = [] + + def _create_user(username, firstname, lastname="", email="", public_email=""): + user = User.objects.create(username=username, first_name=firstname, + last_name=lastname, email=email) + profile = None + + if public_email: + profile = UserProfile.objects.create(user=user, public_email=public_email) + + users.append((user, profile)) + return user + + yield _create_user + + for user, prof in users: + if prof: + prof.delete() + user.delete() + + +@pytest.fixture() +def users(create_user): + create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + create_user('john', 'John', '', 'user2@example.com', 'john@awesome.com') + create_user('bjones', 'Bob', 'Jones', 'user3@example.com', 'bjones@awesome.com') + + create_user('tin1', 'Tim', 'One', 'tim@example.com') + create_user('tin2', 'Tim', 'Two', 'timtwo@example.com') + + +@pytest.fixture() +def finder(): + return UserFinder() + + +def test_not_matching(finder, users): + + assert not finder.find(None) + assert not finder.find("") + assert not finder.find("Bogus") + assert not finder.find("Bogus ") + assert not finder.find("") + assert not finder.find("bogus@example.com") + assert not finder.find("Unknown Packager") + + +def test_by_email(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + user2 = create_user('john', 'John', '', 'user2@example.com', 'john@example.com') + + assert user1 == finder.find("XXX YYY ") + assert user2 == finder.find("YYY ZZZ ") + + +def test_by_profile_email(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + user2 = create_user('john', 'John', '', 'user2@example.com', 'john@awesome.com') + user3 = create_user('bjones', 'Bob', 'Jones', 'user3@example.com', 'bjones@awesome.com') + + assert user1 == finder.find("XXX ") + assert user2 == finder.find("YYY ") + assert user3 == finder.find("ZZZ ") + + +def test_by_name(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + user2 = create_user('john', 'John', '', 'user2@example.com', 'john@awesome.com') + user3 = create_user('bjones', 'Bob', 'Jones', 'user3@example.com', 'bjones@awesome.com') + + assert user1 == finder.find("Joe User ") + assert user1 == finder.find("Joe User") + assert user2 == finder.find("John ") + assert user2 == finder.find("John") + assert user3 == finder.find("Bob Jones ") + + +def test_by_invalid(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + + assert user1 == finder.find("Joe User ") + assert user3 == finder.find("Bob Jones ") + + +def test_ambiguous(finder, create_user): + user4 = create_user('tin1', 'Tim', 'One', 'tim@example.com') + user5 = create_user('tin2', 'Tim', 'Two', 'timtwo@example.com') + assert user4 == finder.find("Tim One ") + assert user5 == finder.find("Tim Two ") + assert not finder.find("Tim ") + + +def test_find_by_username(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + + assert not finder.find_by_username(None) + assert not finder.find_by_username('noone') + assert user1 == finder.find_by_username(user1.username) + # Test cache + assert user1 == finder.find_by_username(user1.username) + + +def test_find_by_email(finder, create_user): + user1 = create_user('joeuser', 'Joe', 'User', 'user1@example.com', 'joeuser@awesome.com') + + assert not finder.find_by_email(None) + assert not finder.find_by_email('bar@bar.com') + assert user1 == finder.find_by_username(user1.username) + # Test cache + assert user1 == finder.find_by_username(user1.username) # vim: set ts=4 sw=4 et: diff --git a/main/tests/test_donor_import.py b/main/tests/test_donor_import.py index 0f27eee7..fbb01572 100644 --- a/main/tests/test_donor_import.py +++ b/main/tests/test_donor_import.py @@ -6,7 +6,8 @@ from tempfile import mkdtemp from shutil import rmtree -from django.test import TransactionTestCase +import pytest + from django.core.management import call_command from django.core.management.base import CommandError @@ -14,67 +15,67 @@ from main.management.commands.donor_import import Command -class DonorImportTest(TransactionTestCase): +command = Command() + + +def test_parse_subject(): + assert command.parse_subject('garbage') is None + + # Valid + valid = 'Receipt [$25.00] By: John Doe [john.doe@archlinux.org]' + output = command.parse_subject(valid) + assert output == 'John Doe' + - def setUp(self): - self.command = Command() +def test_parse_name(): + assert command.sanitize_name('1244') == '' + assert command.sanitize_name('John Doe') == 'John Doe' + assert command.sanitize_name(' John Doe ') == 'John Doe' + assert command.sanitize_name('John Doe 23') == 'John Doe' - def gen_parse_subject(self, data): - return self.command.parse_subject(valid.format(data)) - def test_parse_subject(self): - self.assertIsNone(self.command.parse_subject('garbage')) +def test_decode_subject(): + text = u'メイル' + subject = Header(text, 'utf-8') + assert command.decode_subject(subject) == text - # Valid - valid = u'Receipt [$25.00] By: John Doe [john.doe@archlinux.org]' - output = self.command.parse_subject(valid) - self.assertEqual(output, u'John Doe') - def test_parse_name(self): - self.assertEqual(self.command.sanitize_name(u'1244'), u'') - self.assertEqual(self.command.sanitize_name(u'John Doe'), u'John Doe') - self.assertEqual(self.command.sanitize_name(u' John Doe '), u'John Doe') - self.assertEqual(self.command.sanitize_name(u'John Doe 23'), u'John Doe') +def test_invalid_args(): + with pytest.raises(CommandError) as e: + call_command('donor_import') + assert 'Error: the following arguments are required' in str(e.value) - def test_decode_subject(self): - text = u'メイル' - subject = Header(text, 'utf-8') - self.assertEqual(self.command.decode_subject(subject), text) - def test_invalid_args(self): - with self.assertRaises(CommandError) as e: - call_command('donor_import') - self.assertIn('Error: the following arguments are required', str(e.exception)) +def test_invalid_path(): + with pytest.raises(CommandError) as e: + call_command('donor_import', '/tmp/non-existant') + assert 'Failed to open maildir' in str(e.value) - def test_invalid_path(self): - with self.assertRaises(CommandError) as e: - call_command('donor_import', '/tmp/non-existant') - self.assertIn('Failed to open maildir', str(e.exception)) - def test_maildir(self): - tmpdir = mkdtemp('archweb') - mdir = tmpdir + '/maildir' +def test_maildir(db): + tmpdir = mkdtemp('archweb') + mdir = tmpdir + '/maildir' - maildir = Maildir(mdir) - msg = Message() - msg['subject'] = 'John Doe' - msg['to'] = 'John Doe ' - maildir.add(msg) + maildir = Maildir(mdir) + msg = Message() + msg['subject'] = 'John Doe' + msg['to'] = 'John Doe ' + maildir.add(msg) - # Invalid - call_command('donor_import', mdir) - self.assertEqual(len(Donor.objects.all()), 0) + # Invalid + call_command('donor_import', mdir) + assert len(Donor.objects.all()) == 0 - # Valid - msg = Message() - msg['subject'] = 'Receipt [$25.00] By: David Doe [david@doe.com]' - msg['to'] = 'John Doe ' - maildir.add(msg) - call_command('donor_import', mdir) - self.assertEqual(len(Donor.objects.all()), 1) + # Valid + msg = Message() + msg['subject'] = 'Receipt [$25.00] By: David Doe [david@doe.com]' + msg['to'] = 'John Doe ' + maildir.add(msg) + call_command('donor_import', mdir) + assert len(Donor.objects.all()) == 1 - # Re-running should result in no new donor - call_command('donor_import', mdir) - self.assertEqual(len(Donor.objects.all()), 1) + # Re-running should result in no new donor + call_command('donor_import', mdir) + assert len(Donor.objects.all()) == 1 - rmtree(tmpdir) + rmtree(tmpdir) diff --git a/main/tests/test_templatetags_flags.py b/main/tests/test_templatetags_flags.py index 7ff0406c..ce1ccacc 100644 --- a/main/tests/test_templatetags_flags.py +++ b/main/tests/test_templatetags_flags.py @@ -1,22 +1,11 @@ -from django.test import TestCase - - from main.templatetags.flags import country_flag -from mirrors.models import CheckLocation - - -class FlagsTemplateTest(TestCase): - def setUp(self): - self.checkloc = CheckLocation.objects.create(hostname='arch.org', - source_ip='127.0.0.1', - country='US') +# pylint: disable=W0611 +from mirrors.tests.conftest import checklocation - def tearDown(self): - self.checkloc.delete() - def test_country_flag(self): - flag = country_flag(self.checkloc.country) - self.assertIn(self.checkloc.country.name, flag) - self.assertIn(self.checkloc.country.code.lower(), flag) - self.assertEqual(country_flag(None), '') +def test_country_flag(checklocation): + flag = country_flag(checklocation.country) + assert checklocation.country.name in flag + assert checklocation.country.code.lower() in flag + assert country_flag(None) == '' diff --git a/main/tests/test_templatetags_pgp.py b/main/tests/test_templatetags_pgp.py index 39ace88b..c1dafc74 100644 --- a/main/tests/test_templatetags_pgp.py +++ b/main/tests/test_templatetags_pgp.py @@ -1,74 +1,72 @@ -from django.conf import settings -from django.test import TestCase - from main.templatetags.pgp import pgp_key_link, format_key, pgp_fingerprint -class PGPTemplateTest(TestCase): +def test_format_key(): + # 40 len case + pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' + pgp_key_len = len(pgp_key) + + output = format_key(pgp_key) + spaces = output.count(' ') + output.count('\xa0') # nbsp + assert pgp_key_len + spaces == len(output) + # 21 - 39 len case + pgp_key = '3E2C81117BFB1108D234DAFZ' + pgp_key_len = len(pgp_key) + len('0x') + assert pgp_key_len == len(format_key(pgp_key)) - def test_format_key(self): - # 40 len case - pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' - pgp_key_len = len(pgp_key) + # 8, 20 len case + pgp_key = '3E2C81117BFB1108DEFF' + pgp_key_len = len(pgp_key) + len('0x') + assert pgp_key_len == len(format_key(pgp_key)) - output = format_key(pgp_key) - spaces = output.count(' ') + output.count('\xa0') # nbsp - self.assertEqual(pgp_key_len + spaces, len(output)) + # 0 - 7 len case + pgp_key = 'B1108D' + pgp_key_len = len(pgp_key) + len('0x') + assert pgp_key_len == len(format_key(pgp_key)) - # 21 - 39 len case - pgp_key = '3E2C81117BFB1108D234DAFZ' - pgp_key_len = len(pgp_key) + len('0x') - self.assertEqual(pgp_key_len, len(format_key(pgp_key))) - # 8, 20 len case - pgp_key = '3E2C81117BFB1108DEFF' - pgp_key_len = len(pgp_key) + len('0x') - self.assertEqual(pgp_key_len, len(format_key(pgp_key))) +def assert_pgp_key_link(pgp_key): + output = pgp_key_link(int(pgp_key, 16)) + assert pgp_key[2:] in output + assert "https" in output - # 0 - 7 len case - pgp_key = 'B1108D' - pgp_key_len = len(pgp_key) + len('0x') - self.assertEqual(pgp_key_len, len(format_key(pgp_key))) - def assert_pgp_key_link(self, pgp_key): - output = pgp_key_link(int(pgp_key, 16)) - self.assertIn(pgp_key[2:], output) - self.assertIn("https", output) +def test_pgp_key_link(settings): + assert pgp_key_link("") == "Unknown" - def test_pgp_key_link(self): - self.assertEqual(pgp_key_link(""), "Unknown") + pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' + output = pgp_key_link(pgp_key) + assert pgp_key in output + assert "https" in output - pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' - output = pgp_key_link(pgp_key) - self.assertIn(pgp_key, output) - self.assertIn("https", output) + output = pgp_key_link(pgp_key, "test") + assert "test" in output + assert "https" in output - output = pgp_key_link(pgp_key, "test") - self.assertIn("test", output) - self.assertIn("https", output) + # Numeric key_id <= 8 + assert_pgp_key_link('0x0023BDC7') - # Numeric key_id <= 8 - self.assert_pgp_key_link('0x0023BDC7') + # Numeric key_id <= 16 + assert_pgp_key_link('0xBDC7FF5E34A12F') - # Numeric key_id <= 16 - self.assert_pgp_key_link('0xBDC7FF5E34A12F') + # Numeric key_id <= 40 + assert_pgp_key_link('0xA10E234343EA8BDC7FF5E34A12F') - # Numeric key_id <= 40 - self.assert_pgp_key_link('0xA10E234343EA8BDC7FF5E34A12F') + pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' + server = settings.PGP_SERVER - pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' - server = getattr(settings, 'PGP_SERVER') + settings.PGP_SERVER = '' + assert server not in pgp_key_link(pgp_key) - with self.settings(PGP_SERVER=''): - self.assertNotIn(server, pgp_key_link(pgp_key)) - with self.settings(PGP_SERVER_SECURE=False): - pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' - self.assertNotIn("https", pgp_key_link(pgp_key)) + settings.PGP_SERVER_SECURE = False + settings.PGP_SERVER = server + pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ' + assert not "https" in pgp_key_link(pgp_key) - def test_pgp_fingerprint(self): - self.assertEqual(pgp_fingerprint(None), "") - keyid = '423423fD9004FB063E2C81117BFB1108D234DAFZ' - fingerprint = pgp_fingerprint(keyid) - self.assertTrue(len(fingerprint) > len(keyid)) +def test_pgp_fingerprint(): + assert pgp_fingerprint(None) == "" + keyid = '423423fD9004FB063E2C81117BFB1108D234DAFZ' + fingerprint = pgp_fingerprint(keyid) + assert len(fingerprint) > len(keyid) diff --git a/mirrors/tests/__init__.py b/mirrors/tests/__init__.py index 4ea5e1fb..e69de29b 100644 --- a/mirrors/tests/__init__.py +++ b/mirrors/tests/__init__.py @@ -1,13 +0,0 @@ -from mirrors.models import MirrorUrl, MirrorProtocol, Mirror - - -def create_mirror_url(name='mirror1', country='US', - protocol='http', url='https://archlinux.org/'): - mirror = Mirror.objects.create(name=name, - admin_email='admin@archlinux.org') - mirror_protocol = MirrorProtocol.objects.create(protocol=protocol) - mirror_url = MirrorUrl.objects.create(url=url, - protocol=mirror_protocol, - mirror=mirror, - country=country) - return mirror_url diff --git a/mirrors/tests/conftest.py b/mirrors/tests/conftest.py new file mode 100644 index 00000000..24028d8d --- /dev/null +++ b/mirrors/tests/conftest.py @@ -0,0 +1,65 @@ +import pytest + +from mirrors.models import CheckLocation, MirrorUrl, MirrorProtocol, Mirror + + +NAME = 'mirror1' +ADMIN_EMAIL = 'admin@archlinux.org' +HOSTNAME = 'archlinux.org' +SOURCE_IP = '127.0.0.1' +COUNTRY = 'DE' +PROTOCOL = 'https' +URL = '{}://{}'.format(PROTOCOL, HOSTNAME) + + +@pytest.fixture +def mirror(db, name=NAME, admin_email=ADMIN_EMAIL): + mirror = Mirror.objects.create(name=name, + admin_email=admin_email) + yield mirror + mirror.delete() + + +@pytest.fixture +def checklocation(db, hostname=HOSTNAME, source_ip=SOURCE_IP, country=COUNTRY): + checkloc = CheckLocation.objects.create(hostname=hostname, + source_ip=source_ip, + country=country) + yield checkloc + checkloc.delete() + + +@pytest.fixture +def mirrorprotocol(db, protocol=PROTOCOL): + mirror_protocol = MirrorProtocol.objects.create(protocol=protocol) + yield mirror_protocol + mirror_protocol.delete() + + +@pytest.fixture +def mirrorurl(db, mirror, mirrorprotocol, country=COUNTRY, + url=URL): + mirror_url = MirrorUrl.objects.create(url=url, + protocol=mirrorprotocol, + mirror=mirror, + country=country) + yield mirror_url + mirror_url.delete() + + +@pytest.fixture +def create_mirrorurl(db, mirror, mirrorprotocol): + mirrors = [] + + def _create_mirrorurl(country=COUNTRY, url=URL): + mirror_url = MirrorUrl.objects.create(url=url, + protocol=mirrorprotocol, + mirror=mirror, + country=country) + mirrors.append(mirror_url) + return mirror_url + + yield _create_mirrorurl + + for mirror in mirrors: + mirror.delete() diff --git a/mirrors/tests/test_mirrorcheck.py b/mirrors/tests/test_mirrorcheck.py index c4a6450d..293dc41f 100644 --- a/mirrors/tests/test_mirrorcheck.py +++ b/mirrors/tests/test_mirrorcheck.py @@ -6,150 +6,132 @@ from ssl import CertificateError from socket import timeout, error +import pytest from django.utils.timezone import now from datetime import timedelta - -from django.test import TestCase from django.core.management import call_command - -from mirrors.tests import create_mirror_url -from mirrors.models import MirrorLog, CheckLocation - - -class MirrorCheckTest(TestCase): - def setUp(self): - self.mirror_url = create_mirror_url() - - def tearDown(self): - self.mirror_url.delete() - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_invalid(self, urlopen, Request): - urlopen.return_value.read.return_value = 'data' - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertNotEqual(mirrorlog.error, '') - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_valid(self, urlopen, Request): - urlopen.return_value.read.return_value = str(int(time.time())) - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertEqual(mirrorlog.error, '') - self.assertEqual(mirrorlog.is_success, True) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_valid_olddate(self, urlopen, Request): - urlopen.return_value.read.return_value = str(int(time.time())) - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - date = now() - timedelta(days=600) - MirrorLog.objects.create(url=self.mirror_url, check_time=date) - call_command('mirrorcheck') - self.assertEqual(len(MirrorLog.objects.all()), 1) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_not_found(self, urlopen, Request): - excp = HTTPError('https://archlinux.org/404.txt', 404, 'Not Found', '', None) - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertEqual(mirrorlog.error, str(excp)) - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_not_found_variant(self, urlopen, Request): - excp = BadStatusLine('') - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertIn('Exception in processing', mirrorlog.error) - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_cert_error(self, urlopen, Request): - excp = CertificateError('certificate error') - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertIn('certificate error', mirrorlog.error) - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_general_httpexception(self, urlopen, Request): - excp = URLError('550 No such file', '550.txt') - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertIn(excp.reason, mirrorlog.error) - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_socket_timeout(self, urlopen, Request): - excp = timeout('timeout') - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertEqual('Connection timed out.', mirrorlog.error) - self.assertEqual(mirrorlog.is_success, False) - - @mock.patch('urllib.request.Request') - @mock.patch('urllib.request.urlopen') - def test_socket_error(self, urlopen, Request): - excp = error('error') - urlopen.return_value.read.side_effect = excp - Request.get_host.return_value = 'archlinux.org' - Request.type.return_value = 'https' - - call_command('mirrorcheck') - mirrorlog = MirrorLog.objects.first() - self.assertEqual(str(excp), mirrorlog.error) - self.assertEqual(mirrorlog.is_success, False) - - def test_checklocation(self): - with self.assertRaises(CheckLocation.DoesNotExist) as e: - call_command('mirrorcheck', '-l', '1') - self.assertEqual('CheckLocation matching query does not exist.', str(e.exception)) - - def test_checklocation_model(self): - checkloc = CheckLocation.objects.create(hostname='archlinux.org', - source_ip='1.1.1.1') - with mock.patch('mirrors.management.commands.mirrorcheck.logger') as logger: - call_command('mirrorcheck', '-l', '1') - logger.info.assert_called() - - checkloc.delete() +from mirrors.models import CheckLocation, MirrorLog +from mirrors.tests.conftest import HOSTNAME, PROTOCOL + + +def mocked_request(urlopen, Request, return_value): + urlopen.return_value.read.return_value = return_value + Request.get_host.return_value = HOSTNAME + Request.type.return_value = PROTOCOL + + +def mocked_request_exception(urlopen, Request, excp): + urlopen.return_value.read.side_effect = excp + Request.get_host.return_value = HOSTNAME + Request.type.return_value = PROTOCOL + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_invalid(urlopen, Request, mirrorurl): + mocked_request(urlopen, Request, 'data') + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert mirrorlog.error != '' + assert mirrorlog.is_success == False + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_valid(urlopen, Request, mirrorurl): + mocked_request(urlopen, Request, str(int(time.time()))) + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert mirrorlog.error == '' + assert mirrorlog.is_success == True + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_valid_olddate(urlopen, Request, mirrorurl): + mocked_request(urlopen, Request, str(int(time.time()))) + date = now() - timedelta(days=600) + MirrorLog.objects.create(url=mirrorurl, check_time=date) + call_command('mirrorcheck') + assert len(MirrorLog.objects.all()) == 1 + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_not_found(urlopen, Request, mirrorurl): + excp = HTTPError('https://archlinux.org/404.txt', 404, 'Not Found', '', None) + mocked_request_exception(urlopen, Request, excp) + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert mirrorlog.error == str(excp) + assert mirrorlog.is_success == False + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_not_found_variant(urlopen, Request, mirrorurl): + excp = BadStatusLine('') + mocked_request_exception(urlopen, Request, excp) + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert 'Exception in processing' in mirrorlog.error + assert mirrorlog.is_success == False + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_cert_error(urlopen, Request, mirrorurl): + excp = CertificateError('certificate error') + mocked_request_exception(urlopen, Request, excp) + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert 'certificate error' in mirrorlog.error + assert mirrorlog.is_success == False + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_general_httpexception(urlopen, Request, mirrorurl): + excp = URLError('550 No such file', '550.txt') + mocked_request_exception(urlopen, Request, excp) + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert excp.reason in mirrorlog.error + assert mirrorlog.is_success == False + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_socket_timeout(urlopen, Request, mirrorurl): + excp = timeout('timeout') + mocked_request_exception(urlopen, Request, excp) + + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert 'Connection timed out.' in mirrorlog.error + assert mirrorlog.is_success == False + + +@mock.patch('urllib.request.Request') +@mock.patch('urllib.request.urlopen') +def test_socket_error(urlopen, Request, mirrorurl): + excp = error('error') + mocked_request_exception(urlopen, Request, excp) + + call_command('mirrorcheck') + mirrorlog = MirrorLog.objects.first() + assert str(excp) in mirrorlog.error + assert mirrorlog.is_success == False + + +def test_checklocation_fail(db): + with pytest.raises(CheckLocation.DoesNotExist) as e: + call_command('mirrorcheck', '-l', '1') + assert 'CheckLocation matching query does not exist.' == str(e.value) + +def test_checklocation_model(checklocation): + with mock.patch('mirrors.management.commands.mirrorcheck.logger') as logger: + call_command('mirrorcheck', '-l', '1') + logger.info.assert_called() diff --git a/mirrors/tests/test_mirrorlist.py b/mirrors/tests/test_mirrorlist.py index abff0e97..03f0f8f6 100644 --- a/mirrors/tests/test_mirrorlist.py +++ b/mirrors/tests/test_mirrorlist.py @@ -1,66 +1,55 @@ -from django.test import TestCase - -from mirrors.tests import create_mirror_url from mirrors.models import Mirror +# TODO(jelle): add test for https/rsync mirrors + + +def test_mirrorlist(client, mirrorurl): + response = client.get('/mirrorlist/') + assert response.status_code == 200 + + +def test_mirrorlist_tier_last(client, mirrorurl): + last_tier = Mirror.TIER_CHOICES[-1][0] + response = client.get('/mirrorlist/tier/{}/'.format(last_tier + 1)) + assert response.status_code == 404 + + +def test_mirrorlist_all(client, mirrorurl): + response = client.get('/mirrorlist/all/') + assert response.status_code == 200 + assert mirrorurl.hostname in response.content.decode() + + +def test_mirrorlist_all_https(client, mirrorurl): + response = client.get('/mirrorlist/all/https/') + assert response.status_code == 200 + assert mirrorurl.hostname in response.content.decode() + + +def test_mirrorlist_all_http(client, mirrorurl): + # First test that without any http mirrors, we get a 404. + response = client.get('/mirrorlist/all/http/') + assert response.status_code == 404 + + +def test_mirrorlist_all_smart(client, mirrorurl): + response = client.get('/mirrorlist/all/smart/', follow=True) + assert response.status_code == 404 + + +def test_mirrorlist_status(client, mirrorurl): + response = client.get('/mirrorlist/?country=all&use_mirror_status=on') + assert response.status_code == 200 + + +def test_mirrorlist_filter(client, create_mirrorurl): + mirror1 = create_mirrorurl('JP', 'https://jp.org') + mirror2 = create_mirrorurl() + + # First test that we correctly see the above mirror. + response = client.get('/mirrorlist/?country=JP&protocol=https') + assert response.status_code == 200 + assert mirror1.hostname in response.content.decode() -class MirrorListTest(TestCase): - def setUp(self): - self.mirror_url = create_mirror_url() - - def tearDown(self): - self.mirror_url.delete() - - def test_mirrorlist(self): - response = self.client.get('/mirrorlist/') - self.assertEqual(response.status_code, 200) - - def test_mirrorlist_tier_last(self): - last_tier = Mirror.TIER_CHOICES[-1][0] - response = self.client.get('/mirrorlist/tier/{}/'.format(last_tier + 1)) - self.assertEqual(response.status_code, 404) - - def test_mirrorlist_all(self): - response = self.client.get('/mirrorlist/all/') - self.assertEqual(response.status_code, 200) - self.assertIn(self.mirror_url.hostname, response.content.decode()) - - def test_mirrorlist_all_http(self): - response = self.client.get('/mirrorlist/all/http/') - self.assertEqual(response.status_code, 200) - self.assertIn(self.mirror_url.hostname, response.content.decode()) - - def test_mirrorlist_all_https(self): - # First test that without any https mirrors, we get a 404. - response = self.client.get('/mirrorlist/all/https/') - self.assertEqual(response.status_code, 404) - - # Now, after adding an HTTPS mirror, we expect to succeed. - https_mirror_url = create_mirror_url( - name='https_mirror', - protocol='https', - url='https://wikipedia.org') - response = self.client.get('/mirrorlist/all/https/') - self.assertEqual(response.status_code, 200) - https_mirror_url.delete() - - def test_mirrorlist_filter(self): - jp_mirror_url = create_mirror_url( - name='jp_mirror', - country='JP', - protocol='https', - url='https://wikipedia.jp') - - # First test that we correctly see the above mirror. - response = self.client.get('/mirrorlist/?country=JP&protocol=https') - self.assertEqual(response.status_code, 200) - self.assertIn(jp_mirror_url.hostname, response.content.decode()) - - # Now confirm that the US mirror did not show up. - self.assertNotIn(self.mirror_url.hostname, response.content.decode()) - - jp_mirror_url.delete() - - def test_mirrorlist_status(self): - response = self.client.get('/mirrorlist/?country=all&use_mirror_status=on') - self.assertEqual(response.status_code, 200) + # Now confirm that the US mirror did not show up. + assert not mirror2.hostname in response.content.decode() diff --git a/mirrors/tests/test_mirrorlocations.py b/mirrors/tests/test_mirrorlocations.py index d065e2ef..576da0a7 100644 --- a/mirrors/tests/test_mirrorlocations.py +++ b/mirrors/tests/test_mirrorlocations.py @@ -1,18 +1,9 @@ -from django.test import TestCase - -from mirrors.models import CheckLocation - - -class MirrorLocationsTest(TestCase): - def setUp(self): - self.checklocation = CheckLocation.objects.create(hostname='arch.org', - source_ip='8.8.8.8', - country='US') - - def test_mirrorlocations_json(self): - response = self.client.get('/mirrors/locations/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(1, data['version']) - location = data['locations'][0]['country_code'] - self.assertEqual('US', location) +from mirrors.tests.conftest import COUNTRY + +def test_mirrorlocations_json(client, checklocation): + response = client.get('/mirrors/locations/json/') + assert response.status_code == 200 + data = response.json() + assert 1 == data['version'] + location = data['locations'][0]['country_code'] + assert COUNTRY == location diff --git a/mirrors/tests/test_mirrorresolv.py b/mirrors/tests/test_mirrorresolv.py index eb7f3e32..e84838eb 100644 --- a/mirrors/tests/test_mirrorresolv.py +++ b/mirrors/tests/test_mirrorresolv.py @@ -1,44 +1,37 @@ from unittest import mock -from django.test import TestCase from django.core.management import call_command -from mirrors.tests import create_mirror_url - - -class MirrorCheckTest(TestCase): - def setUp(self): - self.mirror_url = create_mirror_url() - - def tearDown(self): - self.mirror_url.delete() - - @mock.patch('socket.getaddrinfo') - def test_ip4_ip6(self, getaddrinfo): - getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0)), (10, 1, 6, '', ('1a01:3f8:132:1d96::1', 0, 0, 0))] - call_command('mirrorresolv') - self.mirror_url.refresh_from_db() - self.assertEqual(self.mirror_url.has_ipv4, True) - self.assertEqual(self.mirror_url.has_ipv6, True) - - @mock.patch('socket.getaddrinfo') - def test_ip4_only(self, getaddrinfo): - getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0))] - call_command('mirrorresolv') - self.mirror_url.refresh_from_db() - self.assertEqual(self.mirror_url.has_ipv4, True) - self.assertEqual(self.mirror_url.has_ipv6, False) - - @mock.patch('socket.getaddrinfo') - def test_running_twice(self, getaddrinfo): - getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0)), (10, 1, 6, '', ('1a01:3f8:132:1d96::1', 0, 0, 0))] - - # Check if values changed - with mock.patch('mirrors.management.commands.mirrorresolv.logger') as logger: - call_command('mirrorresolv', '-v3') - self.assertEqual(logger.debug.call_count, 4) - - # running again does not change any values. - with mock.patch('mirrors.management.commands.mirrorresolv.logger') as logger: - call_command('mirrorresolv', '-v3') - self.assertEqual(logger.debug.call_count, 3) + +@mock.patch('socket.getaddrinfo') +def test_ip4_ip6(getaddrinfo, db, mirrorurl): + getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0)), (10, 1, 6, '', ('1a01:3f8:132:1d96::1', 0, 0, 0))] + call_command('mirrorresolv') + mirrorurl.refresh_from_db() + + assert mirrorurl.has_ipv4 == True + assert mirrorurl.has_ipv6 == True + + +@mock.patch('socket.getaddrinfo') +def test_ip4_only(getaddrinfo, db, mirrorurl): + getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0))] + call_command('mirrorresolv') + mirrorurl.refresh_from_db() + + assert mirrorurl.has_ipv4 == True + assert mirrorurl.has_ipv6 == False + +@mock.patch('socket.getaddrinfo') +def test_running_twice(getaddrinfo, db, mirrorurl): + getaddrinfo.return_value = [(2, 1, 6, '', ('1.1.1.1', 0)), (10, 1, 6, '', ('1a01:3f8:132:1d96::1', 0, 0, 0))] + + # Check if values changed + with mock.patch('mirrors.management.commands.mirrorresolv.logger') as logger: + call_command('mirrorresolv', '-v3') + assert logger.debug.call_count == 4 + + # running again does not change any values. + with mock.patch('mirrors.management.commands.mirrorresolv.logger') as logger: + call_command('mirrorresolv', '-v3') + assert logger.debug.call_count == 3 diff --git a/mirrors/tests/test_mirrorrsync.py b/mirrors/tests/test_mirrorrsync.py index 31dc325d..9f18fedd 100644 --- a/mirrors/tests/test_mirrorrsync.py +++ b/mirrors/tests/test_mirrorrsync.py @@ -1,30 +1,23 @@ -from django.test import TransactionTestCase +import pytest -from mirrors.models import MirrorRsync, Mirror +from mirrors.models import MirrorRsync -TEST_IPV6 = "2a0b:4342:1a31:410::" -TEST_IPV4 = "8.8.8.8" +def test_invalid(transactional_db, mirror): + with pytest.raises(ValueError) as excinfo: + MirrorRsync.objects.create(ip="8.8.8.8.8", mirror=mirror) + assert 'IPv4 Address with more than 4 bytes' in str(excinfo) -class MirrorRsyncTest(TransactionTestCase): - def setUp(self): - self.mirror = Mirror.objects.create(name='rmirror', - admin_email='foo@bar.com') - def tearDown(self): - self.mirror.delete() +def test_ipv6(transactional_db, mirror): + ipv6 = "2a0b:4342:1a31:410::" + mirrorrsync = MirrorRsync.objects.create(ip=ipv6, mirror=mirror) + assert str(mirrorrsync) == ipv6 + mirrorrsync.delete() - def test_ipv6(self): - mirrorrsync = MirrorRsync.objects.create(ip=TEST_IPV6, mirror=self.mirror) - self.assertEqual(str(mirrorrsync), TEST_IPV6) - mirrorrsync.delete() - def test_ipv4(self): - mirrorrsync = MirrorRsync.objects.create(ip=TEST_IPV4, mirror=self.mirror) - self.assertEqual(str(mirrorrsync), TEST_IPV4) - mirrorrsync.delete() - - def test_invalid(self): - with self.assertRaises(ValueError) as e: - MirrorRsync.objects.create(ip="8.8.8.8.8", mirror=self.mirror) - self.assertIn('IPv4 Address with more than 4 bytes', str(e.exception)) +def test_ipv4(transactional_db, mirror): + ipv4 = "8.8.8.8" + mirrorrsync = MirrorRsync.objects.create(ip=ipv4, mirror=mirror) + assert str(mirrorrsync) == ipv4 + mirrorrsync.delete() diff --git a/mirrors/tests/test_mirrors.py b/mirrors/tests/test_mirrors.py index 558f7ea5..ec5ab3d0 100644 --- a/mirrors/tests/test_mirrors.py +++ b/mirrors/tests/test_mirrors.py @@ -1,37 +1,30 @@ -from django.test import TestCase +def test_details_empty(db, client): + response = client.get('/mirrors/nothing/') + assert response.status_code == 404 -from mirrors.tests import create_mirror_url +def test_details(db, client, mirrorurl): + url = mirrorurl.mirror.get_absolute_url() -class MirrorTest(TestCase): + response = client.get(url) + assert response.status_code == 200 - def test_details(self): - response = self.client.get('/mirrors/nothing/') - self.assertEqual(response.status_code, 404) - mirror_url = create_mirror_url() - url = mirror_url.mirror.get_absolute_url() +def test_details_json_empty(db, client): + response = client.get('/mirrors/nothing/json/') + assert response.status_code == 404 - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - # FIXME: request as mirror admin +def test_details_json(db, client, mirrorurl): + url = mirrorurl.mirror.get_absolute_url() - def test_details_json(self): - response = self.client.get('/mirrors/nothing/json/') - self.assertEqual(response.status_code, 404) + response = client.get(url + 'json/') + assert response.status_code == 200 + data = response.json() + assert data['urls'] != [] - mirror_url = create_mirror_url() - url = mirror_url.mirror.get_absolute_url() - response = self.client.get(url + 'json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertNotEqual(data['urls'], []) - - def test_url_details(self): - mirror_url = create_mirror_url() - url = mirror_url.mirror.get_absolute_url() - - response = self.client.get(url + '{}/'.format(mirror_url.id)) - self.assertEqual(response.status_code, 200) +def test_url_details(db, client, mirrorurl): + url = mirrorurl.mirror.get_absolute_url() + response = client.get(url + '{}/'.format(mirrorurl.id)) + assert response.status_code == 200 diff --git a/mirrors/tests/test_mirrorstatus.py b/mirrors/tests/test_mirrorstatus.py index 503ad280..58f9f6b3 100644 --- a/mirrors/tests/test_mirrorstatus.py +++ b/mirrors/tests/test_mirrorstatus.py @@ -1,49 +1,48 @@ -from django.test import TestCase +def test_mirror_status(db, client): + response = client.get('/mirrors/status/') + assert response.status_code == 200 -from mirrors.tests import create_mirror_url +def test_json_endpoint(client, settings, mirrorurl): + settings.CACHES = {'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}} + # Disables the cache_function's cache -class MirrorStatusTest(TestCase): - def test_status(self): - response = self.client.get('/mirrors/status/') - self.assertEqual(response.status_code, 200) + response = client.get('/mirrors/status/json/') + assert response.status_code == 200 + data = response.json() - def test_json_endpoint(self): - # Disables the cache_function's cache - with self.settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}): - response = self.client.get('/mirrors/status/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['urls'], []) + assert len(data['urls']) == 1 + mirror = data['urls'][0] + assert mirror['url'] == mirrorurl.url - mirror_url = create_mirror_url() - response = self.client.get('/mirrors/status/json/') - self.assertEqual(response.status_code, 200) - data = response.json() +def test_json_endpoint_empty(db, client, settings): + # Disables the cache_function's cache + settings.CACHES = {'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}} - self.assertEqual(len(data['urls']), 1) - mirror = data['urls'][0] - self.assertEqual(mirror['url'], mirror_url.url) + response = client.get('/mirrors/status/json/') + assert response.status_code == 200 + data = response.json() + assert data['urls'] == [] - mirror_url.delete() - def test_json_tier(self): - response = self.client.get('/mirrors/status/tier/99/json/') - self.assertEqual(response.status_code, 404) +def test_json_tier_not_found(db, client, settings): + response = client.get('/mirrors/status/tier/99/json/') + assert response.status_code == 404 - response = self.client.get('/mirrors/status/tier/1/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['urls'], []) - mirror_url = create_mirror_url() +def test_json_tier_empty_cache(db, client, settings): + response = client.get('/mirrors/status/tier/1/json/') + assert response.status_code == 200 + data = response.json() + assert data['urls'] == [] - # Disables the cache_function's cache - with self.settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}): - response = self.client.get('/mirrors/status/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertNotEqual(data['urls'], []) - mirror_url.delete() +def test_json_tier(client, settings, mirrorurl): + # Disables the cache_function's cache + settings.CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}} + + response = client.get('/mirrors/status/json/') + assert response.status_code == 200 + data = response.json() + assert data['urls'] != [] diff --git a/mirrors/tests/test_mirrorurl.py b/mirrors/tests/test_mirrorurl.py index 4fe8f22a..9af3fea6 100644 --- a/mirrors/tests/test_mirrorurl.py +++ b/mirrors/tests/test_mirrorurl.py @@ -1,31 +1,30 @@ -from django.test import TestCase +from mirrors.tests.conftest import HOSTNAME, URL -from mirrors.tests import create_mirror_url +def test_mirrorurl_address_families(mirrorurl): + assert not mirrorurl.address_families() is None -class MirrorUrlTest(TestCase): - def setUp(self): - self.mirror_url = create_mirror_url() +def test_mirrorurl_hostname(mirrorurl): + assert mirrorurl.hostname == HOSTNAME - def testAddressFamilies(self): - self.assertIsNotNone(self.mirror_url.address_families()) +def test_mirrorurl_get_absolute_url(mirrorurl): + absolute_url = mirrorurl.get_absolute_url() + expected = '/mirrors/%s/%d/' % (mirrorurl.mirror.name, mirrorurl.pk) + assert absolute_url == expected - def testHostname(self): - self.assertEqual(self.mirror_url.hostname, 'archlinux.org') +def test_mirrorurl_overview(client, mirrorurl): + response = client.get('/mirrors/') + assert response.status_code == 200 + assert mirrorurl.mirror.name in response.content.decode() - def testGetAbsoluteUrl(self): - absolute_url = self.mirror_url.get_absolute_url() - expected = '/mirrors/%s/%d/' % (self.mirror_url.mirror.name, self.mirror_url.pk) - self.assertEqual(absolute_url, expected) +def test_mirrorurl_get_full_url(mirrorurl): + assert 'mirrors/{}'.format(mirrorurl.mirror.name) in mirrorurl.get_full_url() - def test_mirror_overview(self): - response = self.client.get('/mirrors/') - self.assertEqual(response.status_code, 200) - self.assertIn(self.mirror_url.mirror.name, response.content.decode()) +def test_mirror_url_clean(mirrorurl): + mirrorurl.clean() + # TOOD(jelle): this expects HOSTNAME to resolve, maybe mock + assert mirrorurl.has_ipv4 == True + #assert mirrorurl.has_ipv6 == True - def testClean(self): - # TODO: add test for self.mirror_url.clean() - pass - - def tearDown(self): - self.mirror_url.delete() +def test_mirrorurl_repr(mirrorurl): + assert URL in repr(mirrorurl) diff --git a/mirrors/tests/test_models.py b/mirrors/tests/test_models.py index ea7345ec..3216eda2 100644 --- a/mirrors/tests/test_models.py +++ b/mirrors/tests/test_models.py @@ -1,70 +1,31 @@ -from django.test import TestCase +from mirrors.tests.conftest import NAME, HOSTNAME, PROTOCOL -from mirrors.models import Mirror, CheckLocation -from mirrors.tests import create_mirror_url +def test_mirror_get_full_url(mirror): + assert mirror.get_absolute_url() in mirror.get_full_url() + assert 'http' in mirror.get_full_url('http') -class MirrorUrlTest(TestCase): - def setUp(self): - self.mirror_url = create_mirror_url() +def test_mirror_downstream(mirror): + assert list(mirror.downstream()) == [] - def testAddressFamilies(self): - self.assertIsNotNone(self.mirror_url.address_families()) +def test_mirror_get_absolute_url(mirror): + absolute_url = mirror.get_absolute_url() + expected = '/mirrors/{}/'.format(mirror.name) + assert absolute_url == expected - def testHostname(self): - self.assertEqual(self.mirror_url.hostname, 'archlinux.org') +def test_mirror_rer(mirror): + assert NAME in repr(mirror) - def testGetAbsoluteUrl(self): - absolute_url = self.mirror_url.get_absolute_url() - expected = '/mirrors/%s/%d/' % (self.mirror_url.mirror.name, self.mirror_url.pk) - self.assertEqual(absolute_url, expected) - def test_mirror_overview(self): - response = self.client.get('/mirrors/') - self.assertEqual(response.status_code, 200) - self.assertIn(self.mirror_url.mirror.name, response.content.decode()) +def test_checklocation_family(checklocation): + assert isinstance(checklocation.family, int) - def testClean(self): - # TODO: add test for self.mirror_url.clean() - pass +def test_checklocation_ip_version(checklocation): + assert isinstance(checklocation.ip_version, int) - def tearDown(self): - self.mirror_url.delete() +def test_checklocation_repr(checklocation): + assert HOSTNAME in repr(checklocation) -class MirrorTest(TestCase): - def setUp(self): - self.mirror = Mirror.objects.create(name='mirror1', - admin_email='admin@archlinux.org') - - def tearDown(self): - self.mirror.delete() - - def test_downstream(self): - self.assertEqual(list(self.mirror.downstream()), []) - - def test_get_absolute_url(self): - absolute_url = self.mirror.get_absolute_url() - expected = '/mirrors/{}/'.format(self.mirror.name) - self.assertEqual(absolute_url, expected) - - def test_get_full_url(self): - self.assertIn(self.mirror.get_absolute_url(), self.mirror.get_full_url()) - self.assertIn('http', self.mirror.get_full_url('http')) - - -class CheckLocationTest(TestCase): - def setUp(self): - self.checkloc = CheckLocation.objects.create(hostname='arch.org', - source_ip='127.0.0.1', - country='US') - - def tearDown(self): - self.checkloc.delete() - - def test_family(self): - # TODO: mock socket.getaddrinfo in CheckLocation.family - self.assertIsInstance(self.checkloc.family, int) - - def test_ip_version(self): - self.assertIsInstance(self.checkloc.ip_version, int) +def test_mirrorprotocol_repr(mirrorprotocol): + assert PROTOCOL in repr(mirrorprotocol) diff --git a/mirrors/tests/test_templatetags.py b/mirrors/tests/test_templatetags.py index ec9b61bd..453a4c5d 100644 --- a/mirrors/tests/test_templatetags.py +++ b/mirrors/tests/test_templatetags.py @@ -1,27 +1,27 @@ from datetime import timedelta -from django.test import SimpleTestCase - from mirrors.templatetags.mirror_status import duration, hours, percentage -class MirrorTemplateTagTest(SimpleTestCase): - def test_duration(self): - self.assertEqual(duration(None), u'') +def test_duration(): + assert duration(None) == '' + + assert duration(timedelta(hours=5)) == '5:00' + assert duration(timedelta(hours=5, seconds=61)) == '5:01' + + # Microseconds are skipped + assert duration(timedelta(microseconds=9999)) == '0:00' + - self.assertEqual(duration(timedelta(hours=5)), '5:00') - self.assertEqual(duration(timedelta(hours=5, seconds=61)), '5:01') - # Microseconds are skipped - self.assertEqual(duration(timedelta(microseconds=9999), ), '0:00') +def test_hours(): + assert hours(None) == '' - def test_hours(self): - self.assertEqual(hours(None), u'') + assert hours(timedelta(hours=5)) == '5 hours' + assert hours(timedelta(hours=1)) == '1 hour' + assert hours(timedelta(seconds=60*60)) == '1 hour' - self.assertEqual(hours(timedelta(hours=5)), '5 hours') - self.assertEqual(hours(timedelta(hours=1)), '1 hour') - self.assertEqual(hours(timedelta(seconds=60*60)), '1 hour') - def test_percentage(self): - self.assertEqual(percentage(None), u'') - self.assertEqual(percentage(10), '1000.0%') - self.assertEqual(percentage(10, 2), '1000.00%') +def test_percentage(): + assert percentage(None) == '' + assert percentage(10) == '1000.0%' + assert percentage(10, 2) == '1000.00%' diff --git a/news/tests.py b/news/tests.py deleted file mode 100644 index b7cdd2dd..00000000 --- a/news/tests.py +++ /dev/null @@ -1,84 +0,0 @@ -from django.core import mail -from django.test import TestCase, TransactionTestCase -from django.contrib.auth.models import User - - -from news.models import News - - -class NewsTest(TestCase): - - def test_feed(self): - response = self.client.get('/feeds/news/') - self.assertEqual(response.status_code, 200) - - def test_sitemap(self): - response = self.client.get('/sitemap-news.xml') - self.assertEqual(response.status_code, 200) - - def test_news_sitemap(self): - response = self.client.get('/news-sitemap.xml') - self.assertEqual(response.status_code, 200) - - def test_newsitem(self): - response = self.client.get('/news/404', follow=True) - self.assertEqual(response.status_code, 404) - - -class NewsCrud(TransactionTestCase): - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - News.objects.all().delete() - self.user.delete() - - def create(self, title='Bash broken', content='Broken in [testing]', announce=False): - data = { - 'title': title, - 'content': content, - } - if announce: - data['send_announce'] = 'on' - return self.client.post('/news/add/', data, follow=True) - - def testCreateItem(self): - title = 'Bash broken' - response = self.create(title) - self.assertEqual(response.status_code, 200) - - news = News.objects.first() - self.assertEqual(news.author, self.user) - self.assertEqual(news.title, title) - - def testView(self): - self.create() - news = News.objects.first() - - response = self.client.get(news.get_absolute_url()) - self.assertEqual(response.status_code, 200) - - def testRedirectId(self): - self.create() - news = News.objects.first() - - response = self.client.get('/news/{}'.format(news.id), follow=True) - self.assertEqual(response.status_code, 200) - - def testSendAnnounce(self): - title = 'New glibc' - self.create(title, announce=True) - self.assertEqual(len(mail.outbox), 1) - self.assertIn(title, mail.outbox[0].subject) - - def testPreview(self): - response = self.client.post('/news/preview/', {'data': '**body**'}, follow=True) - self.assertEqual(response.status_code, 200) - self.assertEqual('

body

', response.content.decode()) diff --git a/news/tests/test_crud.py b/news/tests/test_crud.py new file mode 100644 index 00000000..07294769 --- /dev/null +++ b/news/tests/test_crud.py @@ -0,0 +1,53 @@ +from news.models import News + +from django.core import mail + + +def create(admin_client, title='Bash broken', content='Broken in [testing]', announce=False): + data = { + 'title': title, + 'content': content, + } + if announce: + data['send_announce'] = 'on' + return admin_client.post('/news/add/', data, follow=True) + + +def test_create_item(db, admin_client, admin_user): + title = 'Bash broken' + response = create(admin_client, title) + assert response.status_code == 200 + + news = News.objects.first() + + assert news.author == admin_user + assert news.title == title + + +def test_view(db, admin_client): + create(admin_client) + news = News.objects.first() + + response = admin_client.get(news.get_absolute_url()) + assert response.status_code == 200 + + +def test_redirect_id(db, admin_client): + create(admin_client) + news = News.objects.first() + + response = admin_client.get('/news/{}'.format(news.id), follow=True) + assert response.status_code == 200 + + +def test_send_announce(db, admin_client): + title = 'New glibc' + create(admin_client, title, announce=True) + assert len(mail.outbox) == 1 + assert title in mail.outbox[0].subject + + +def test_preview(db, admin_client): + response = admin_client.post('/news/preview/', {'data': '**body**'}, follow=True) + assert response.status_code == 200 + assert '

body

' == response.content.decode() diff --git a/news/tests/test_models.py b/news/tests/test_models.py new file mode 100644 index 00000000..5a4178bc --- /dev/null +++ b/news/tests/test_models.py @@ -0,0 +1,18 @@ +def test_feed(db, client): + response = client.get('/feeds/news/') + assert response.status_code == 200 + + +def test_sitemap(db, client): + response = client.get('/sitemap-news.xml') + assert response.status_code == 200 + + +def test_news_sitemap(db, client): + response = client.get('/news-sitemap.xml') + assert response.status_code == 200 + + +def test_newsitem(db, client): + response = client.get('/news/404', follow=True) + assert response.status_code == 404 diff --git a/packages/tests.py b/packages/tests.py deleted file mode 100644 index f2dae8cb..00000000 --- a/packages/tests.py +++ /dev/null @@ -1,465 +0,0 @@ -import unittest - -from django.core import mail -from django.test import TestCase, TransactionTestCase -from django.contrib.auth.models import User - -from main.models import Package, Repo -from packages.models import PackageRelation -from devel.models import UserProfile - -from .alpm import AlpmAPI - - -alpm = AlpmAPI() - - -class AlpmTestCase(unittest.TestCase): - - @unittest.skipUnless(alpm.available, "ALPM is unavailable") - def test_version(self): - version = alpm.version() - self.assertIsNotNone(version) - version = version.split(b'.') - # version is a 3-tuple, e.g., '7.0.2' - self.assertEqual(3, len(version)) - - @unittest.skipUnless(alpm.available, "ALPM is unavailable") - def test_vercmp(self): - self.assertEqual(0, alpm.vercmp("1.0", "1.0")) - self.assertEqual(1, alpm.vercmp("1.1", "1.0")) - - @unittest.skipUnless(alpm.available, "ALPM is unavailable") - def test_compare_versions(self): - self.assertTrue(alpm.compare_versions("1.0", "<=", "2.0")) - self.assertTrue(alpm.compare_versions("1.0", "<", "2.0")) - self.assertFalse(alpm.compare_versions("1.0", ">=", "2.0")) - self.assertFalse(alpm.compare_versions("1.0", ">", "2.0")) - self.assertTrue(alpm.compare_versions("1:1.0", ">", "2.0")) - self.assertFalse(alpm.compare_versions("1.0.2", ">=", "2.1.0")) - - self.assertTrue(alpm.compare_versions("1.0", "=", "1.0")) - self.assertTrue(alpm.compare_versions("1.0", "=", "1.0-1")) - self.assertFalse(alpm.compare_versions("1.0", "!=", "1.0")) - - def test_behavior_when_unavailable(self): - mock_alpm = AlpmAPI() - mock_alpm.available = False - - self.assertIsNone(mock_alpm.version()) - self.assertIsNone(mock_alpm.vercmp("1.0", "1.0")) - self.assertIsNone(mock_alpm.compare_versions("1.0", "=", "1.0")) - - -class PackagesTest(TestCase): - - def test_feed(self): - response = self.client.get('/feeds/packages/') - self.assertEqual(response.status_code, 200) - - def test_sitemap(self): - for sitemap in ['packages', 'package-groups', 'package-files', 'split-packages']: - response = self.client.get('/sitemap-{}.xml'.format(sitemap)) - self.assertEqual(response.status_code, 200) - - -class PackageSearchJson(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_invalid(self): - response = self.client.get('/packages/search/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['limit'], 250) - self.assertEqual(data['results'], []) - self.assertEqual(data['valid'], False) - - def test_reponame(self): - response = self.client.get('/packages/search/json/?repository=core') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(len(data['results']), 5) - self.assertEqual(set([r['pkgname'] for r in data['results']]), - {"coreutils", "glibc", "linux", "pacman", "systemd"}) - - def test_packagename(self): - response = self.client.get('/packages/search/json/?name=linux') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(len(data['results']), 1) - - def test_no_results(self): - response = self.client.get('/packages/search/json/?name=none') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(len(data['results']), 0) - - def test_limit_four(self): - response = self.client.get('/packages/search/json/?limit=4') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['page'], 1) - self.assertEqual(data['num_pages'], 2) - self.assertEqual(data['limit'], 4) - self.assertEqual(len(data['results']), 4) - - def test_second_page(self): - response = self.client.get('/packages/search/json/?limit=4&page=2') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['page'], 2) - self.assertEqual(data['num_pages'], 2) - self.assertEqual(len(data['results']), 1) - - -class PackageSearch(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_invalid(self): - response = self.client.get('/packages/?q=test') - self.assertEqual(response.status_code, 200) - self.assertIn('0 matching packages found', response.content.decode()) - - def test_exact_match(self): - response = self.client.get('/packages/?q=linux') - self.assertEqual(response.status_code, 200) - self.assertIn('1 matching package found', response.content.decode()) - - def test_filter_name(self): - response = self.client.get('/packages/?name=name') - self.assertEqual(response.status_code, 200) - self.assertIn('0 matching packages found', response.content.decode()) - - def test_filter_repo(self): - response = self.client.get('/packages/?repo=Core') - self.assertEqual(response.status_code, 200) - self.assertIn('5 matching packages found', response.content.decode()) - - def test_filter_desc(self): - response = self.client.get('/packages/?desc=kernel') - self.assertEqual(response.status_code, 200) - self.assertIn('1 matching package found', response.content.decode()) - - def test_filter_flagged(self): - response = self.client.get('/packages/?flagged=Flagged') - self.assertEqual(response.status_code, 200) - self.assertIn('0 matching packages found', response.content.decode()) - - def test_filter_not_flagged(self): - response = self.client.get('/packages/?flagged=Not Flagged') - self.assertEqual(response.status_code, 200) - self.assertIn('5 matching packages found', response.content.decode()) - - def test_filter_arch(self): - response = self.client.get('/packages/?arch=any') - self.assertEqual(response.status_code, 200) - self.assertIn('0 matching packages found', response.content.decode()) - - def test_filter_maintainer_orphan(self): - response = self.client.get('/packages/?maintainer=orphan') - self.assertEqual(response.status_code, 200) - self.assertIn('5 matching packages found', response.content.decode()) - - def test_filter_packager_unknown(self): - response = self.client.get('/packages/?packager=unknown') - self.assertEqual(response.status_code, 200) - self.assertIn('5 matching packages found', response.content.decode()) - - def test_sort(self): - response = self.client.get('/packages/?sort=pkgname') - self.assertEqual(response.status_code, 200) - self.assertIn('5 matching packages found', response.content.decode()) - - def test_head(self): - response = self.client.head('/packages/?q=unknown') - self.assertEqual(response.status_code, 200) - - -class OpenSearch(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_packages(self): - response = self.client.get('/opensearch/packages/') - self.assertEqual(response.status_code, 200) - - def test_packages_suggest(self): - response = self.client.get('/opensearch/packages/suggest') - self.assertEqual(response.status_code, 200) - - def test_packages_suggest_lowercase(self): - response = self.client.get('/opensearch/packages/suggest?q=linux') - self.assertEqual(response.status_code, 200) - self.assertIn('linux', response.content.decode()) - - def test_packages_suggest_uppercase(self): - response = self.client.get('/opensearch/packages/suggest?q=LINUX') - self.assertEqual(response.status_code, 200) - self.assertIn('linux', response.content.decode()) - - response = self.client.get('/opensearch/packages/suggest?q=LINux') - self.assertEqual(response.status_code, 200) - self.assertIn('linux', response.content.decode()) - - -class PackageViews(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_arch_differences(self): - response = self.client.get('/packages/differences/') - self.assertEqual(response.status_code, 200) - - -class PackageDisplay(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_packages_detail(self): - response = self.client.get('/packages/core/x86_64/linux/') - self.assertEqual(response.status_code, 200) - - response = self.client.get('/packages/core/x86_64/nope/') - self.assertEqual(response.status_code, 404) - - # Redirect to search - response = self.client.get('/packages/core/x86_64/') - self.assertEqual(response.status_code, 302) - - def test_packages_json(self): - response = self.client.get('/packages/core/x86_64/linux/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['pkgbase'], 'linux') - # TODO verify more of the structure - - def test_packages_files(self): - response = self.client.get('/packages/core/x86_64/linux/files/') - self.assertEqual(response.status_code, 200) - - def test_packages_files_json(self): - response = self.client.get('/packages/core/x86_64/linux/files/json/') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['pkgname'], 'linux') - # TODO verify more of the structure - - def test_packages_download(self): - response = self.client.get('/packages/core/x86_64/linux/download/') - self.assertEqual(response.status_code, 404) - # TODO: Figure out how to fake a mirror - - def test_head(self): - response = self.client.head('/packages/core/x86_64/linux/') - self.assertEqual(response.status_code, 200) - - def test_groups(self): - response = self.client.get('/groups/') - self.assertEqual(response.status_code, 200) - - def test_groups_arch(self): - response = self.client.get('/groups/x86_64/') - self.assertEqual(response.status_code, 200) - - def test_groups_details(self): - response = self.client.get('/groups/x86_64/base/') - self.assertEqual(response.status_code, 404) - # FIXME: add group fixtures. - - -class FlagPackage(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_flag_package(self): - data = { - 'website': '', - 'email': 'nobody@archlinux.org', - 'message': 'new linux version', - } - response = self.client.post('/packages/core/x86_64/linux/flag/', - data, - follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('Package Flagged - linux', response.content.decode()) - self.assertEqual(len(mail.outbox), 1) - self.assertIn('package [linux] marked out-of-date', mail.outbox[0].subject) - - # Flag again, should fail - response = self.client.post('/packages/core/x86_64/linux/flag/', - data, - follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('has already been flagged out-of-date.', response.content.decode()) - - def test_flag_package_invalid(self): - data = { - 'website': '', - 'email': 'nobody@archlinux.org', - 'message': 'a', - } - response = self.client.post('/packages/core/x86_64/linux/flag/', - data, - follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('Enter a valid and useful out-of-date message', response.content.decode()) - self.assertEqual(len(mail.outbox), 0) - - def test_flag_help(self): - response = self.client.get('/packages/flaghelp/') - self.assertEqual(response.status_code, 200) - - -class UnFlagPackage(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - self.profile = UserProfile.objects.create(user=self.user, - public_email="{}@awesome.com".format(self.user.username)) - self.profile.allowed_repos.add(Repo.objects.get(name='Core')) - self.profile.save() - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - self.profile.delete() - self.user.delete() - PackageRelation.objects.all().delete() - - def flag_package(self): - data = { - 'website': '', - 'email': 'nobody@archlinux.org', - 'message': 'new linux version', - } - response = self.client.post('/packages/core/x86_64/linux/flag/', - data, - follow=True) - self.assertEqual(response.status_code, 200) - - def test_unflag_package_404(self): - response = self.client.get('/packages/core/x86_64/fooobar/unflag/') - self.assertEqual(response.status_code, 404) - - response = self.client.get('/packages/core/x86_64/fooobar/unflag/all/') - self.assertEqual(response.status_code, 404) - - def test_unflag_package(self): - self.flag_package() - response = self.client.get('/packages/core/x86_64/linux/unflag/', follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('Flag linux as out-of-date', response.content.decode()) - - def test_unflag_all_package(self): - self.flag_package() - response = self.client.get('/packages/core/x86_64/linux/unflag/all/', follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('Flag linux as out-of-date', response.content.decode()) - - -class AdoptOrphanPackage(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - self.profile = UserProfile.objects.create(user=self.user, - public_email="{}@awesome.com".format(self.user.username)) - self.profile.allowed_repos.add(Repo.objects.get(name='Core')) - self.profile.save() - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - self.profile.delete() - self.user.delete() - PackageRelation.objects.all().delete() - - def request(self, pkgid, adopt=True): - data = { - 'pkgid': pkgid, - } - if adopt: - data['adopt'] = 'adopt' - else: - data['disown'] = 'disown' - return self.client.post('/packages/update/', data, follow=True) - - def test_adopt_package(self): - pkg = Package.objects.first() - response = self.request(pkg.id) - self.assertEqual(response.status_code, 200) - self.assertEqual(len(PackageRelation.objects.all()), 1) - - response = self.request(pkg.id, False) - self.assertEqual(response.status_code, 200) - self.assertEqual(len(PackageRelation.objects.all()), 0) - - def test_no_permissions(self): - self.profile.allowed_repos.set([]) - self.profile.save() - pkg = Package.objects.first() - - response = self.request(pkg.id) - self.assertEqual(response.status_code, 200) - self.assertEqual(len(PackageRelation.objects.all()), 0) - - def test_wrong_request(self): - pkg = Package.objects.first() - response = self.client.post('/packages/update/', {'pkgid': pkg.id, }, follow=True) - self.assertEqual(response.status_code, 200) - self.assertIn('Are you trying to adopt or disown', response.content.decode()) - - def test_stale_relations(self): - response = self.client.get('/packages/stale_relations/') - self.assertEqual(response.status_code, 200) - - -class SignOffTest(TransactionTestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser('admin', - 'admin@archlinux.org', - password) - self.profile = UserProfile.objects.create(user=self.user, - public_email="{}@awesome.com".format(self.user.username)) - self.profile.allowed_repos.add(Repo.objects.get(name='Core')) - self.profile.save() - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - self.profile.delete() - self.user.delete() - PackageRelation.objects.all().delete() - - def test_signoffs(self): - response = self.client.get('/packages/signoffs/') - self.assertEqual(response.status_code, 200) - - def test_signoffs_json(self): - response = self.client.get('/packages/signoffs/json/') - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json()['signoff_groups'], []) - - -# vim: set ts=4 sw=4 et: diff --git a/packages/tests/__init__.py b/packages/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/tests/test_adoptorphan_packages.py b/packages/tests/test_adoptorphan_packages.py new file mode 100644 index 00000000..8d9bda9b --- /dev/null +++ b/packages/tests/test_adoptorphan_packages.py @@ -0,0 +1,46 @@ +from main.models import Package, Repo +from packages.models import PackageRelation + + +def request(client, pkgid, adopt=True): + data = { + 'pkgid': pkgid, + } + if adopt: + data['adopt'] = 'adopt' + else: + data['disown'] = 'disown' + return client.post('/packages/update/', data, follow=True) + + +def test_wrong_request(admin_client, arches, repos, package): + # TODO(jelle): fix + pkg = Package.objects.first() + response = admin_client.post('/packages/update/', {'pkgid': pkg.id, }, follow=True) + assert response.status_code == 200 + assert 'Are you trying to adopt or disown' in response.content.decode() + + +def test_stale_relations(user_client, arches, repos, package): + response = user_client.get('/packages/stale_relations/') + assert response.status_code == 200 + + +def test_no_permissions(user_client, arches, repos, package): + pkg = Package.objects.first() + + response = request(user_client, pkg.id) + assert response.status_code == 200 + assert len(PackageRelation.objects.all()) == 0 + + +def test_adopt_package(user_client, userprofile, arches, repos, package): + userprofile.allowed_repos.add(Repo.objects.get(name='Core')) + pkg = Package.objects.first() + response = request(user_client, pkg.id) + assert response.status_code == 200 + assert len(PackageRelation.objects.all()) == 1 + + response = request(user_client, pkg.id, False) + assert response.status_code == 200 + assert len(PackageRelation.objects.all()) == 0 diff --git a/packages/tests/test_alpm.py b/packages/tests/test_alpm.py new file mode 100644 index 00000000..74111d06 --- /dev/null +++ b/packages/tests/test_alpm.py @@ -0,0 +1,43 @@ +import unittest + +from packages.alpm import AlpmAPI + + +alpm = AlpmAPI() + + +@unittest.skipUnless(alpm.available, "ALPM is unavailable") +def test_version(): + version = alpm.version() + assert version is not None + version = version.split(b'.') + # version is a 3-tuple, e.g., '7.0.2' + assert 3 == len(version) + + +@unittest.skipUnless(alpm.available, "ALPM is unavailable") +def test_vercmp(): + assert 0 == alpm.vercmp("1.0", "1.0") + assert 1 == alpm.vercmp("1.1", "1.0") + + +@unittest.skipUnless(alpm.available, "ALPM is unavailable") +def test_compare_versions(): + assert alpm.compare_versions("1.0", "<=", "2.0") == True + assert alpm.compare_versions("1.0", "<", "2.0") == True + assert alpm.compare_versions("1.0", ">=", "2.0") == False + assert alpm.compare_versions("1.0", ">", "2.0") == False + assert alpm.compare_versions("1:1.0", ">", "2.0") == True + assert alpm.compare_versions("1.0.2", ">=", "2.1.0") == False + assert alpm.compare_versions("1.0", "=", "1.0") == True + assert alpm.compare_versions("1.0", "=", "1.0-1") == True + assert alpm.compare_versions("1.0", "!=", "1.0") == False + + +def test_behavior_when_unavailable(): + mock_alpm = AlpmAPI() + mock_alpm.available = False + + assert mock_alpm.version() is None + assert mock_alpm.vercmp("1.0", "1.0") is None + assert mock_alpm.compare_versions("1.0", "=", "1.0") is None diff --git a/packages/tests/test_opensearch.py b/packages/tests/test_opensearch.py new file mode 100644 index 00000000..2a3b66ad --- /dev/null +++ b/packages/tests/test_opensearch.py @@ -0,0 +1,24 @@ +def test_packages(client, arches, repos, package): + response = client.get('/opensearch/packages/') + assert response.status_code == 200 + + +def test_packages_suggest(client, arches, repos, package): + response = client.get('/opensearch/packages/suggest') + assert response.status_code == 200 + + +def test_packages_suggest_lowercase(client, arches, repos, package): + response = client.get('/opensearch/packages/suggest?q=linux') + assert response.status_code == 200 + assert 'linux' in response.content.decode() + + +def test_packages_suggest_uppercase(client, arches, repos, package): + response = client.get('/opensearch/packages/suggest?q=LINUX') + assert response.status_code == 200 + assert 'linux' in response.content.decode() + + response = client.get('/opensearch/packages/suggest?q=LINux') + assert response.status_code == 200 + assert 'linux' in response.content.decode() diff --git a/packages/tests/test_package_flag.py b/packages/tests/test_package_flag.py new file mode 100644 index 00000000..df9e15ab --- /dev/null +++ b/packages/tests/test_package_flag.py @@ -0,0 +1,42 @@ +from django.core import mail + + +def test_flag_package(client, arches, repos, package): + data = { + 'website': '', + 'email': 'nobody@archlinux.org', + 'message': 'new linux version', + } + response = client.post('/packages/core/x86_64/linux/flag/', + data, + follow=True) + assert response.status_code == 200 + assert 'Package Flagged - linux' in response.content.decode() + assert len(mail.outbox) == 1 + assert 'package [linux] marked out-of-date' in mail.outbox[0].subject + + # Flag again, should fail + response = client.post('/packages/core/x86_64/linux/flag/', + data, + follow=True) + assert response.status_code == 200 + assert 'has already been flagged out-of-date.' in response.content.decode() + + +def test_flag_package_invalid(client, arches, repos, package): + data = { + 'website': '', + 'email': 'nobody@archlinux.org', + 'message': 'a', + } + response = client.post('/packages/core/x86_64/linux/flag/', + data, + follow=True) + assert response.status_code == 200 + assert 'Enter a valid and useful out-of-date message' in response.content.decode() + assert len(mail.outbox) == 0 + + +def test_flag_help(client, arches, repos, package): + response = client.get('/packages/flaghelp/') + assert response.status_code == 200 diff --git a/packages/tests/test_package_search.py b/packages/tests/test_package_search.py new file mode 100644 index 00000000..2ef30731 --- /dev/null +++ b/packages/tests/test_package_search.py @@ -0,0 +1,69 @@ +def test_invalid(client, arches, repos, package): + response = client.get('/packages/?q=test') + assert response.status_code == 200 + assert '0 matching packages found' in response.content.decode() + + +def test_exact_match(client, arches, repos, package): + response = client.get('/packages/?q=linux') + assert response.status_code == 200 + assert '1 matching package found' in response.content.decode() + + +def test_filter_name(client, arches, repos, package): + response = client.get('/packages/?name=name') + assert response.status_code == 200 + assert '0 matching packages found' in response.content.decode() + + +def test_filter_repo(client, arches, repos, package): + response = client.get('/packages/?repo=Core') + assert response.status_code == 200 + assert '5 matching packages found' in response.content.decode() + + +def test_filter_desc(client, arches, repos, package): + response = client.get('/packages/?desc=kernel') + assert response.status_code == 200 + assert '1 matching package found' in response.content.decode() + + +def test_filter_flagged(client, arches, repos, package): + response = client.get('/packages/?flagged=Flagged') + assert response.status_code == 200 + assert '0 matching packages found' in response.content.decode() + + +def test_filter_not_flagged(client, arches, repos, package): + response = client.get('/packages/?flagged=Not Flagged') + assert response.status_code == 200 + assert '5 matching packages found' in response.content.decode() + + +def test_filter_arch(client, arches, repos, package): + response = client.get('/packages/?arch=any') + assert response.status_code == 200 + assert '0 matching packages found' in response.content.decode() + + +def test_filter_maintainer_orphan(client, arches, repos, package): + response = client.get('/packages/?maintainer=orphan') + assert response.status_code == 200 + assert '5 matching packages found' in response.content.decode() + + +def test_filter_packager_unknown(client, arches, repos, package): + response = client.get('/packages/?packager=unknown') + assert response.status_code == 200 + assert '5 matching packages found' in response.content.decode() + + +def test_sort(client, arches, repos, package): + response = client.get('/packages/?sort=pkgname') + assert response.status_code == 200 + assert '5 matching packages found' in response.content.decode() + + +def test_head(client, arches, repos, package): + response = client.head('/packages/?q=unknown') + assert response.status_code == 200 diff --git a/packages/tests/test_packagedisplay.py b/packages/tests/test_packagedisplay.py new file mode 100644 index 00000000..c11750ea --- /dev/null +++ b/packages/tests/test_packagedisplay.py @@ -0,0 +1,58 @@ +def test_packages_detail(client, arches, repos, package): + response = client.get('/packages/core/x86_64/linux/') + assert response.status_code == 200 + + response = client.get('/packages/core/x86_64/nope/') + assert response.status_code == 404 + + # Redirect to search + response = client.get('/packages/core/x86_64/') + assert response.status_code == 302 + + +def test_packages_json(client, arches, repos, package): + response = client.get('/packages/core/x86_64/linux/json/') + assert response.status_code == 200 + data = response.json() + assert data['pkgbase'] == 'linux' + # TODO verify more of the structure + + +def test_packages_files(client, arches, repos, package): + response = client.get('/packages/core/x86_64/linux/files/') + assert response.status_code == 200 + + +def test_packages_files_json(client, arches, repos, package): + response = client.get('/packages/core/x86_64/linux/files/json/') + assert response.status_code == 200 + data = response.json() + assert data['pkgname'] == 'linux' + # TODO verify more of the structure + + +def test_packages_download(client, arches, repos, package): + response = client.get('/packages/core/x86_64/linux/download/') + assert response.status_code == 404 + # TODO: Figure out how to fake a mirror + + +def test_head(client, arches, repos, package): + response = client.head('/packages/core/x86_64/linux/') + assert response.status_code == 200 + + +def test_groups(client, arches, repos, package): + response = client.get('/groups/') + assert response.status_code == 200 + + +def test_groups_arch(client, arches, repos, package): + response = client.get('/groups/x86_64/') + assert response.status_code == 200 + + +def test_groups_details(client, arches, repos, package): + response = client.get('/groups/x86_64/base/') + assert response.status_code == 404 + # FIXME: add group fixtures. diff --git a/packages/tests/test_search_json.py b/packages/tests/test_search_json.py new file mode 100644 index 00000000..a6735eb5 --- /dev/null +++ b/packages/tests/test_search_json.py @@ -0,0 +1,47 @@ +def test_invalid(client, arches, repos, package): + response = client.get('/packages/search/json/') + assert response.status_code == 200 + data = response.json() + assert data['limit'] == 250 + assert data['results'] == [] + assert data['valid'] == False + + +def test_reponame(client, arches, repos, package): + response = client.get('/packages/search/json/?repository=core') + assert response.status_code == 200 + data = response.json() + assert len(data['results']) == 5 + assert set([r['pkgname'] for r in data['results']]) == {"coreutils", "glibc", "linux", "pacman", "systemd"} + +def test_packagename(client, arches, repos, package): + response = client.get('/packages/search/json/?name=linux') + assert response.status_code == 200 + data = response.json() + assert len(data['results']) == 1 + + +def test_no_results(client, arches, repos, package): + response = client.get('/packages/search/json/?name=none') + assert response.status_code == 200 + data = response.json() + assert len(data['results']) == 0 + + +def test_limit_four(client, arches, repos, package): + response = client.get('/packages/search/json/?limit=4') + assert response.status_code == 200 + data = response.json() + assert data['page'] == 1 + assert data['num_pages'] == 2 + assert data['limit'] == 4 + assert len(data['results']) == 4 + + +def test_second_page(client, arches, repos, package): + response = client.get('/packages/search/json/?limit=4&page=2') + assert response.status_code == 200 + data = response.json() + assert data['page'] == 2 + assert data['num_pages'] == 2 + assert len(data['results']) == 1 diff --git a/packages/tests/test_signoff.py b/packages/tests/test_signoff.py new file mode 100644 index 00000000..1085570e --- /dev/null +++ b/packages/tests/test_signoff.py @@ -0,0 +1,9 @@ +def test_signoffs(admin_client, arches, repos, package): + response = admin_client.get('/packages/signoffs/') + assert response.status_code == 200 + + +def test_signoffs_json(admin_client, arches, repos, package): + response = admin_client.get('/packages/signoffs/json/') + assert response.status_code == 200 + assert response.json()['signoff_groups'] == [] diff --git a/packages/tests/test_unflag.py b/packages/tests/test_unflag.py new file mode 100644 index 00000000..16724bb1 --- /dev/null +++ b/packages/tests/test_unflag.py @@ -0,0 +1,32 @@ +def assert_flag_package(client): + data = { + 'website': '', + 'email': 'nobody@archlinux.org', + 'message': 'new linux version', + } + + # TODO: hardcoded package name + response = client.post('/packages/core/x86_64/linux/flag/', data, follow=True) + assert response.status_code == 200 + + +def test_unflag_package_404(user_client): + response = user_client.get('/packages/core/x86_64/fooobar/unflag/') + assert response.status_code == 404 + + response = user_client.get('/packages/core/x86_64/fooobar/unflag/all/') + assert response.status_code == 404 + + +def test_unflag_package(user_client, package): + assert_flag_package(user_client) + response = user_client.get('/packages/core/x86_64/linux/unflag/', follow=True) + assert response.status_code == 200 + assert 'Flag linux as out-of-date' in response.content.decode() + + +def test_unflag_all_package(user_client, package): + assert_flag_package(user_client) + response = user_client.get('/packages/core/x86_64/linux/unflag/all/', follow=True) + assert response.status_code == 200 + assert 'Flag linux as out-of-date' in response.content.decode() diff --git a/packages/tests/test_views.py b/packages/tests/test_views.py new file mode 100644 index 00000000..a5452311 --- /dev/null +++ b/packages/tests/test_views.py @@ -0,0 +1,14 @@ +def test_feed(db, client): + response = client.get('/feeds/packages/') + assert response.status_code == 200 + + +def test_sitemap(db, client): + for sitemap in ['packages', 'package-groups', 'package-files', 'split-packages']: + response = client.get('/sitemap-{}.xml'.format(sitemap)) + assert response.status_code == 200 + + +def test_arch_differences(client, arches, repos, package): + response = client.get('/packages/differences/') + assert response.status_code == 200 diff --git a/planet/tests/test_command.py b/planet/tests/test_command.py index e93ce51a..ce4b70a1 100644 --- a/planet/tests/test_command.py +++ b/planet/tests/test_command.py @@ -1,7 +1,7 @@ import time from unittest import mock -from django.test import TestCase +import pytest from planet.models import Feed, FeedItem from planet.management.commands.update_planet import Command @@ -14,6 +14,7 @@ class Result(dict): def get(self, value): return getattr(self, value) + class Entry(dict): title = 'title' description = 'lorem ipsum' @@ -26,58 +27,82 @@ def get(self, value): return getattr(self, value) -class UpdatePlanetTest(TestCase): +@pytest.fixture +def command(): + yield Command() + + +@pytest.fixture +def feed(db): + return Feed(title='test', website='http://archlinux.org', + website_rss='http://archlinux.org/feed.rss') + + +class MockParse: + @staticmethod + def parse(): + return {} + + +@pytest.fixture +def mock_parse(monkeypatch): + def mock_get(*args, **kwargs): + return MockParse() - def setUp(self): - self.command = Command() - self.feed = Feed(title='test', website='http://archlinux.org', - website_rss='http://archlinux.org/feed.rss') + monkeypatch.setattr(feedparser, "parse", mock_get) - # Test when feedparser receives an exception and returns no status - @mock.patch('feedparser.parse') - def test_parse_feed_wrong(self, parse): + +# Test when feedparser receives an exception and returns no status +def test_parse_feed_wrong(feed, command): + with mock.patch('feedparser.parse') as parse: parse.return_value = {} - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 0 - @mock.patch('feedparser.parse') - def test_parse_feed_304(self, parse): + +def test_parse_feed_304(feed, command): + with mock.patch('feedparser.parse') as parse: parse.return_value = {'status': 304} - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 0 - @mock.patch('feedparser.parse') - def test_parse_feed_unknown(self, parse): + +def test_parse_feed_unknown(feed, command): + with mock.patch('feedparser.parse') as parse: parse.return_value = {'status': 201} - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 0 - @mock.patch('feedparser.parse') - def test_parse_entries_empty(self, parse): + +def test_parse_entries_empty(feed, command): + with mock.patch('feedparser.parse') as parse: parse.return_value = Result() - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 0 - @mock.patch('feedparser.parse') - def test_parse_entries_not_published(self, parse): + +def test_parse_entries_not_published(feed, command): + with mock.patch('feedparser.parse') as parse: value = Result() entry = Entry() entry.published_parsed = None value.entries = [entry] parse.return_value = value - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 0 - @mock.patch('feedparser.parse') - def test_parse_entries(self, parse): + +def test_parse_entries(feed, command): + with mock.patch('feedparser.parse') as parse: value = Result() value.entries = [Entry()] parse.return_value = value - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 1 - @mock.patch('feedparser.parse') - def test_parse_entries_atom(self, parse): + +def test_parse_entries_atom(feed, command): + with mock.patch('feedparser.parse') as parse: value = Result() entry = Entry() entry.published_parsed = None @@ -85,5 +110,5 @@ def test_parse_entries_atom(self, parse): value.entries = [entry] parse.return_value = value - self.command.parse_feed(self.feed) + command.parse_feed(feed) assert FeedItem.objects.count() == 1 diff --git a/planet/tests/test_views.py b/planet/tests/test_views.py index b09c9e6b..864ff583 100644 --- a/planet/tests/test_views.py +++ b/planet/tests/test_views.py @@ -1,12 +1,8 @@ -from django.test import TestCase +def test_feed(db, client): + response = client.get('/feeds/planet/') + assert response.status_code == 200 -class PlanetTest(TestCase): - - def test_feed(self): - response = self.client.get('/feeds/planet/') - self.assertEqual(response.status_code, 200) - - def test_planet(self): - response = self.client.get('/planet/') - self.assertEqual(response.status_code, 200) +def test_planet(db, client): + response = client.get('/planet/') + assert response.status_code == 200 diff --git a/public/tests.py b/public/tests.py deleted file mode 100644 index b826ee53..00000000 --- a/public/tests.py +++ /dev/null @@ -1,54 +0,0 @@ -from django.test import TestCase - - -class PublicTest(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json', 'main/fixtures/groups.json', - 'devel/fixtures/staff_groups.json'] - - def test_index(self): - response = self.client.get('/') - self.assertEqual(response.status_code, 200) - - def test_about(self): - response = self.client.get('/about/') - self.assertEqual(response.status_code, 200) - - def test_art(self): - response = self.client.get('/art/') - self.assertEqual(response.status_code, 200) - - def test_svn(self): - response = self.client.get('/svn/') - self.assertEqual(response.status_code, 200) - - def test_donate(self): - response = self.client.get('/donate/') - self.assertEqual(response.status_code, 200) - - def test_download(self): - response = self.client.get('/download/') - self.assertEqual(response.status_code, 200) - - def test_master_keys(self): - response = self.client.get('/master-keys/') - self.assertEqual(response.status_code, 200) - - def test_master_keys_json(self): - response = self.client.get('/master-keys/json/') - self.assertEqual(response.status_code, 200) - - def test_feeds(self): - response = self.client.get('/feeds/') - self.assertEqual(response.status_code, 200) - - def test_people(self): - response = self.client.get('/people/developers/') - self.assertEqual(response.status_code, 200) - - def test_sitemap(self): - sitemaps = ['sitemap', 'sitemap-base'] - for sitemap in sitemaps: - response = self.client.get('/{}.xml'.format(sitemap)) - self.assertEqual(response.status_code, 200) - diff --git a/public/tests/test_views.py b/public/tests/test_views.py new file mode 100644 index 00000000..4c82ceac --- /dev/null +++ b/public/tests/test_views.py @@ -0,0 +1,60 @@ +def test_index(client, arches, repos, package, groups, staff_groups): + response = client.get('/') + assert response.status_code == 200 + + +def test_index_logged_in(admin_client, arches, repos, package, groups, staff_groups): + response = admin_client.get('/') + assert response.status_code == 200 + + +def test_about(client, arches, repos, package, groups, staff_groups): + response = client.get('/about/') + assert response.status_code == 200 + + +def test_art(client, arches, repos, package, groups, staff_groups): + response = client.get('/art/') + assert response.status_code == 200 + + +def test_svn(client, arches, repos, package, groups, staff_groups): + response = client.get('/svn/') + assert response.status_code == 200 + + +def test_donate(client, arches, repos, package, groups, staff_groups): + response = client.get('/donate/') + assert response.status_code == 200 + + +def test_download(client, arches, repos, package, groups, staff_groups): + response = client.get('/download/') + assert response.status_code == 200 + + +def test_master_keys(client, arches, repos, package, groups, staff_groups): + response = client.get('/master-keys/') + assert response.status_code == 200 + + +def test_master_keys_json(client, arches, repos, package, groups, staff_groups): + response = client.get('/master-keys/json/') + assert response.status_code == 200 + + +def test_feeds(client, arches, repos, package, groups, staff_groups): + response = client.get('/feeds/') + assert response.status_code == 200 + + +def test_people(client, arches, repos, package, groups, staff_groups): + response = client.get('/people/developers/') + assert response.status_code == 200 + + +def test_sitemap(client, arches, repos, package, groups, staff_groups): + sitemaps = ['sitemap', 'sitemap-base'] + for sitemap in sitemaps: + response = client.get('/{}.xml'.format(sitemap)) + assert response.status_code == 200 diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..4e22ea20 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +DJANGO_SETTINGS_MODULE = settings diff --git a/releng/fixtures/release.json b/releng/fixtures/release.json deleted file mode 100644 index 94a4dd5e..00000000 --- a/releng/fixtures/release.json +++ /dev/null @@ -1,17 +0,0 @@ -[ - { - "fields": { - "available": true, - "created": "2017-06-07T19:36:49.569Z", - "info": "public information", - "kernel_version": "4.12", - "last_modified": "2017-06-11T16:53:53.723Z", - "md5_sum": "f029d6004e63464b1b26c62058c4e37e", - "release_date": "2017-06-11", - "sha1_sum": "2c2c8ce676e891ac354cf4a8bac3824a4aae0c90", - "version": "juni" - }, - "model": "releng.release", - "pk": 1 - } -] diff --git a/releng/models.py b/releng/models.py index a9019792..aad75f11 100644 --- a/releng/models.py +++ b/releng/models.py @@ -11,6 +11,7 @@ from django.utils.safestring import mark_safe from main.utils import set_created_field, parse_markdown +from devel.fields import PGPKeyField class Release(models.Model): @@ -19,12 +20,13 @@ class Release(models.Model): kernel_version = models.CharField(max_length=50, blank=True) md5_sum = models.CharField('MD5 digest', max_length=32, blank=True) sha1_sum = models.CharField('SHA1 digest', max_length=40, blank=True) + pgp_key = PGPKeyField(max_length=40, verbose_name="PGP key fingerprint", null=True, blank=True, + help_text="consists of 40 hex digits; use `gpg --fingerprint`") created = models.DateTimeField(editable=False) last_modified = models.DateTimeField(editable=False) available = models.BooleanField(default=True) info = models.TextField('Public information', blank=True) - torrent_data = models.TextField(blank=True, - help_text="base64-encoded torrent file") + torrent_data = models.TextField(blank=True, help_text="base64-encoded torrent file") class Meta: get_latest_by = 'release_date' @@ -79,7 +81,7 @@ def torrent(self): 'info_hash': None, } if 'creation date' in data: - created= datetime.utcfromtimestamp(data['creation date']) + created = datetime.utcfromtimestamp(data['creation date']) metadata['creation_date'] = created.replace(tzinfo=utc) if info: metadata['info_hash'] = hashlib.sha1(bencode(info)).hexdigest() diff --git a/releng/tests/conftest.py b/releng/tests/conftest.py new file mode 100644 index 00000000..3731ab0f --- /dev/null +++ b/releng/tests/conftest.py @@ -0,0 +1,18 @@ +from datetime import datetime + +import pytest + +from releng.models import Release + + +VERSION = '1.0' +KERNEL_VERSION = '4.18' + + +@pytest.fixture +def release(db): + release = Release.objects.create(release_date=datetime.now(), + version=VERSION, + kernel_version=KERNEL_VERSION) + yield release + release.delete() diff --git a/releng/tests/test_models.py b/releng/tests/test_models.py index 0ed5f1fe..314e8e1f 100644 --- a/releng/tests/test_models.py +++ b/releng/tests/test_models.py @@ -1,34 +1,28 @@ -from django.test import TestCase +def test_feed(client, release): + response = client.get('/feeds/releases/') + assert response.status_code == 200 -from releng.models import Release +def test_absolute_url(release): + assert release.version in release.get_absolute_url() -class RelengTest(TestCase): - fixtures = ['releng/fixtures/release.json'] - def setUp(self): - self.release = Release.objects.first() +def test_iso_url(release): + url = release.iso_url() + ver = release.version + expected = 'iso/{}/archlinux-{}-x86_64.iso'.format(ver, ver) + assert url == expected - def test_feed(self): - response = self.client.get('/feeds/releases/') - self.assertEqual(response.status_code, 200) - def test_absolute_url(self): - self.assertIn(self.release.version, self.release.get_absolute_url()) +def test_info_html(release): + assert release.info in release.info_html() - def test_iso_url(self): - url = self.release.iso_url() - ver = self.release.version - expected = 'iso/{}/archlinux-{}-x86_64.iso'.format(ver, ver) - self.assertEqual(url, expected) - def test_info_html(self): - self.assertIn(self.release.info, self.release.info_html()) +def test_dir_path(release): + dir_path = u'iso/{}/'.format(release.version) + assert dir_path == release.dir_path() - def test_dir_path(self): - dir_path = u'iso/{}/'.format(self.release.version) - self.assertEqual(dir_path, self.release.dir_path()) - def test_sitemap(self): - response = self.client.get('/sitemap-releases.xml') - self.assertEqual(response.status_code, 200) +def test_sitemap(client, release): + response = client.get('/sitemap-releases.xml') + assert response.status_code == 200 diff --git a/releng/tests/test_views.py b/releng/tests/test_views.py index d6e5f59c..b18be30a 100644 --- a/releng/tests/test_views.py +++ b/releng/tests/test_views.py @@ -1,40 +1,31 @@ -from django.test import TestCase +def test_release_json(client, release): + version = release.version + response = client.get('/releng/releases/json/') + assert response.status_code == 200 -from releng.models import Release + data = response.json() + assert data['version'] == 1 + release = data['releases'][0] + assert release['version'] == version -class RelengViewTest(TestCase): - fixtures = ['releng/fixtures/release.json'] +def test_netboot_page(db, client): + response = client.get('/releng/netboot/') + assert response.status_code == 200 - def setUp(self): - self.release = Release.objects.first() - def test_release_json(self): - version = self.release.version - response = self.client.get('/releng/releases/json/') - self.assertEqual(response.status_code, 200) - data = response.json() +def test_netboot_config(db, client): + response = client.get('/releng/netboot/archlinux.ipxe') + assert response.status_code == 200 - self.assertEqual(data['version'], 1) - release = data['releases'][0] - self.assertEqual(release['version'], version) - def test_netboot_page(self): - response = self.client.get('/releng/netboot/') - self.assertEqual(response.status_code, 200) +def test_release_torrent_not_found(client, release): + # TODO: Add torrent data to release fixture + response = client.get('/releng/releases/{}/torrent/'.format(release.version)) + assert response.status_code == 404 - def test_netboot_config(self): - response = self.client.get('/releng/netboot/archlinux.ipxe') - self.assertEqual(response.status_code, 200) - def test_release_torrent_not_found(self): - # TODO: Add torrent data to release fixture - version = self.release.version - response = self.client.get('/releng/releases/{}/torrent/'.format(version)) - self.assertEqual(response.status_code, 404) - - def test_release_details(self): - version = self.release.version - response = self.client.get('/releng/releases/{}/'.format(version)) - self.assertEqual(response.status_code, 200) - self.assertIn(version, response.content.decode('utf-8')) +def test_release_details(client, release): + response = client.get('/releng/releases/{}/'.format(release.version)) + assert response.status_code == 200 + assert release.version in response.content.decode() diff --git a/requirements_test.txt b/requirements_test.txt new file mode 100644 index 00000000..ff768e2f --- /dev/null +++ b/requirements_test.txt @@ -0,0 +1,6 @@ +coveralls +pylint +pytest +pytest-cov +pytest-django + diff --git a/templates/public/download.html b/templates/public/download.html index 944fe96d..15c31a90 100644 --- a/templates/public/download.html +++ b/templates/public/download.html @@ -2,6 +2,7 @@ {% load cache %} {% load static %} {% load flags %} +{% load pgp %} {% block title %}Arch Linux - Downloads{% endblock %} @@ -98,6 +99,7 @@

Checksums

  • PGP signature
  • + {% if release.pgp_key %}
  • PGP fingerprint: {% pgp_key_link release.pgp_key %}
  • {% endif %} {% if release.md5_sum %}
  • MD5: {{ release.md5_sum }}
  • {% endif %} {% if release.sha1_sum %}
  • SHA1: {{ release.sha1_sum }}
  • {% endif %}
diff --git a/todolists/tests/conftest.py b/todolists/tests/conftest.py new file mode 100644 index 00000000..dba17410 --- /dev/null +++ b/todolists/tests/conftest.py @@ -0,0 +1,32 @@ +import pytest + +from main.models import Package +from todolists.models import Todolist, TodolistPackage + + +NAME = 'Boost rebuild' +SLUG = 'boost-rebuild' +DESCRIPTION = 'Boost 1.66 rebuild' +RAW = 'linux' + + +@pytest.fixture +def todolist(admin_user, arches, repos, package): + todolist = Todolist.objects.create(name=NAME, + description=DESCRIPTION, + slug=SLUG, + creator=admin_user, + raw=RAW) + yield todolist + todolist.delete() + + +@pytest.fixture +def todolistpackage(admin_user, todolist): + pkg = Package.objects.first() + todopkg = TodolistPackage.objects.create(pkg=pkg, pkgname=pkg.pkgname, + pkgbase=pkg.pkgbase, arch=pkg.arch, + repo=pkg.repo, user=admin_user, + todolist=todolist) + yield todopkg + todopkg.delete() diff --git a/todolists/tests/test_models.py b/todolists/tests/test_models.py index 4e629f37..61ed458d 100644 --- a/todolists/tests/test_models.py +++ b/todolists/tests/test_models.py @@ -1,45 +1,34 @@ -from django.contrib.auth.models import User -from django.test import TestCase - - -from main.models import Package -from todolists.models import Todolist, TodolistPackage - - -class TestTodolist(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - self.user = User.objects.create(username="joeuser", first_name="Joe", - last_name="User", email="user1@example.com") - self.todolist = Todolist.objects.create(name='Boost rebuild', - description='Boost 1.66 rebuid', - creator=self.user, - raw='linux') - - def tearDown(self): - self.todolist.delete() - self.user.delete() - - def test_stripped_description(self): - self.todolist.description = 'Boost rebuild ' - desc = self.todolist.stripped_description - self.assertFalse(desc.endswith(' ')) - - def test_get_absolute_url(self): - self.assertIn('/todo/', self.todolist.get_absolute_url()) - - def test_get_full_url(self): - url = self.todolist.get_full_url() - self.assertIn('https://example.com/todo/', url) - - def test_packages(self): - pkg = Package.objects.first() - todopkg = TodolistPackage.objects.create(pkg=pkg, pkgname=pkg.pkgname, - pkgbase=pkg.pkgbase, arch=pkg.arch, - repo=pkg.repo, user=self.user, - todolist=self.todolist) - pkgs = self.todolist.packages() - self.assertEqual(len(pkgs), 1) - self.assertEqual(pkgs[0], todopkg) +from todolists.tests.conftest import NAME + + +def test_stripped_description(todolist): + todolist.description = 'Boost rebuild ' + desc = todolist.stripped_description + assert not desc.endswith(' ') + + +def test_get_absolute_url(todolist): + assert '/todo/' in todolist.get_absolute_url() + + +def test_get_full_url(todolist): + url = todolist.get_full_url() + assert 'https://example.com/todo/' in url + + +def test_packages(admin_user, todolist, todolistpackage): + pkgs = todolist.packages() + assert len(pkgs) == 1 + assert pkgs[0] == todolistpackage + + +def test_str(admin_user, todolist): + assert NAME in str(todolist) + + +def test_todolist_str(admin_user, todolist, todolistpackage): + assert todolistpackage.pkgname in str(todolistpackage) + + +def test_status_css_class(admin_user, todolist, todolistpackage): + assert todolistpackage.status_css_class() == 'incomplete' diff --git a/todolists/tests/test_templatetags_todolists.py b/todolists/tests/test_templatetags_todolists.py index 93cdbf94..cb547425 100644 --- a/todolists/tests/test_templatetags_todolists.py +++ b/todolists/tests/test_templatetags_todolists.py @@ -1,29 +1,6 @@ -from django.contrib.auth.models import User -from django.test import TestCase - - -from main.models import Package -from todolists.models import Todolist, TodolistPackage from todolists.templatetags.todolists import todopkg_details_link -class TestTodolist(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - self.user = User.objects.create(username="joeuser", first_name="Joe", - last_name="User", email="user1@example.com") - self.todolist = Todolist.objects.create(name='Boost rebuild', - description='Boost 1.66 rebuid', - creator=self.user, - raw='linux') - - def test_details_link(self): - pkg = Package.objects.first() - todopkg = TodolistPackage.objects.create(pkg=pkg, pkgname=pkg.pkgname, - pkgbase=pkg.pkgbase, arch=pkg.arch, - repo=pkg.repo, user=self.user, - todolist=self.todolist) - link = todopkg_details_link(todopkg) - self.assertIn('View package details for {}'.format(todopkg.pkg.pkgname), link) +def test_details_link(todolistpackage): + link = todopkg_details_link(todolistpackage) + assert 'View package details for {}'.format(todolistpackage.pkg.pkgname) in link diff --git a/todolists/tests/test_views.py b/todolists/tests/test_views.py index 8c605bc3..1b886901 100644 --- a/todolists/tests/test_views.py +++ b/todolists/tests/test_views.py @@ -1,103 +1,76 @@ -from django.contrib.auth.models import User -from django.test import TestCase +from todolists.models import Todolist, TodolistPackage -from todolists.models import Todolist, TodolistPackage +def assert_create_todo(client): + response = client.post('/todo/add/', { + 'name': 'Foo rebuild', + 'description': 'The Foo Rebuild, please read the instructions', + 'raw': 'linux', + }, follow=True) + assert response.status_code == 200 + + +def test_todolist_overview(user_client, todolist): + response = user_client.get('/todo/') + assert response.status_code == 200 + assert todolist.name in response.content.decode() + + +def test_todolist_detail(todolist, user_client): + response = user_client.get(todolist.get_absolute_url()) + assert response.status_code == 200 + assert todolist.name in response.content.decode() + + +def test_todolist_json(todolist, user_client): + response = user_client.get(todolist.get_absolute_url() + 'json') + assert response.status_code == 200 + data = response.json() + assert data['name'] == todolist.name + + +def test_create_todolist(user_client): + assert_create_todo(user_client) + assert Todolist.objects.count() == 1 + Todolist.objects.all().delete() + + +def test_flag_pkg(user_client, arches, repos, package): + assert_create_todo(user_client) + + todolist = Todolist.objects.first() + package = todolist.packages().first() + assert package.status == TodolistPackage.INCOMPLETE + + response = user_client.get('/todo/{}/flag/{}/'.format(todolist.slug, package.id)) + assert response.status_code == 302 + + package = todolist.packages().first() + assert package.status == TodolistPackage.COMPLETE + + Todolist.objects.all().delete() + +def test_edit(user_client, arches, repos, package): + assert_create_todo(user_client) + + todolist = Todolist.objects.first() + assert todolist.packages().count() == 1 + + response = user_client.post('/todo/{}/edit/'.format(todolist.slug), { + 'name': 'Foo rebuild', + 'description': 'The Foo Rebuild, please read the instructions', + 'raw': 'linux\nglibc', + }) + assert response.status_code == 302 + todolist = Todolist.objects.first() + assert todolist.packages().count() == 2 + + Todolist.objects.all().delete() +def test_delete(user_client, arches, repos, package): + assert_create_todo(user_client) -class TestTodolist(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - self.user = User.objects.create(username="joeuser", first_name="Joe", - last_name="User", email="user1@example.com") - self.todolist = Todolist.objects.create(name='Boost rebuild', - description='Boost 1.66 rebuid', - creator=self.user, - slug='boost-rebuild', - raw='linux') - - def test_todolist_overview(self): - response = self.client.get('/todo/') - self.assertEqual(response.status_code, 200) - self.assertIn(self.todolist.name, response.content.decode()) - - def test_todolist_detail(self): - response = self.client.get(self.todolist.get_absolute_url()) - self.assertEqual(response.status_code, 200) - self.assertIn(self.todolist.name, response.content.decode()) - - def test_todolist_json(self): - response = self.client.get(self.todolist.get_absolute_url() + 'json') - self.assertEqual(response.status_code, 200) - data = response.json() - self.assertEqual(data['name'], self.todolist.name) - - -class TestTodolistAdmin(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def setUp(self): - password = 'test' - self.user = User.objects.create_superuser("admin", - "admin@archlinux.org", - password) - - self.client.post('/login/', { - 'username': self.user.username, - 'password': password - }) - - def tearDown(self): - Todolist.objects.all().delete() - self.user.delete() - - def create_todo(self): - return self.client.post('/todo/add/', { - 'name': 'Foo rebuild', - 'description': 'The Foo Rebuild, please read the instructions', - 'raw': 'linux', - }) - - def test_create_todolist(self): - response = self.create_todo() - self.assertEqual(response.status_code, 302) - self.assertEqual(len(Todolist.objects.all()), 1) - - def test_flag_pkg(self): - response = self.create_todo() - self.assertEqual(response.status_code, 302) - - todolist = Todolist.objects.first() - package = todolist.packages().first() - self.assertEqual(package.status, TodolistPackage.INCOMPLETE) - - response = self.client.get('/todo/{}/flag/{}/'.format(todolist.slug, package.id)) - self.assertEqual(response.status_code, 302) - - package = todolist.packages().first() - self.assertEqual(package.status, TodolistPackage.COMPLETE) - - def test_edit(self): - response = self.create_todo() - self.assertEqual(response.status_code, 302) - todolist = Todolist.objects.first() - self.assertEqual(len(todolist.packages().all()), 1) - - response = self.client.post('/todo/{}/edit/'.format(todolist.slug), { - 'name': 'Foo rebuild', - 'description': 'The Foo Rebuild, please read the instructions', - 'raw': 'linux\nglibc', - }) - self.assertEqual(response.status_code, 302) - todolist = Todolist.objects.first() - self.assertEqual(len(todolist.packages().all()), 2) - - def test_delete(self): - response = self.create_todo() - self.assertEqual(response.status_code, 302) - todolist = Todolist.objects.first() - response = self.client.post('/todo/{}/delete'.format(todolist.slug)) - self.assertEqual(response.status_code, 301) + todolist = Todolist.objects.first() + response = user_client.post('/todo/{}/delete'.format(todolist.slug)) + assert response.status_code == 301 + Todolist.objects.all().delete() diff --git a/urls.py b/urls.py index 1bfbc7f4..034e1640 100644 --- a/urls.py +++ b/urls.py @@ -110,7 +110,7 @@ ]) # django-toolbar -if settings.DEBUG_TOOLBAR: +if settings.DEBUG_TOOLBAR: # pragma: no cover import debug_toolbar urlpatterns.extend([ path('__debug__/', include(debug_toolbar.urls)), diff --git a/visualize/tests.py b/visualize/tests.py deleted file mode 100644 index 30289c89..00000000 --- a/visualize/tests.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.test import TestCase - - -class VisualeTest(TestCase): - fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json', - 'main/fixtures/package.json'] - - def test_urls(self): - for url in ['', 'by_repo/', 'by_arch/']: - response = self.client.get('/visualize/{}'.format(url)) - self.assertEqual(response.status_code, 200) diff --git a/visualize/tests/test_urls.py b/visualize/tests/test_urls.py new file mode 100644 index 00000000..ec9ab1a1 --- /dev/null +++ b/visualize/tests/test_urls.py @@ -0,0 +1,4 @@ +def test_urls(client, arches, repos, package): + for url in ['', 'by_repo/', 'by_arch/']: + response = client.get('/visualize/{}'.format(url)) + assert response.status_code == 200