From 0fd19c3d9ae758ad9e791be08e0694bb8d0ae61e Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Fri, 2 Aug 2019 11:47:16 +0200 Subject: [PATCH] python3 fixes plus lots of added tests --- api/tests/test_attributes.py | 56 +++++++++++++- api/tests/test_health.py | 65 +++++++++++++++- api/tests/test_queue.py | 145 ++++++++++++++++++++++++++++++++--- api/tests/test_user_utils.py | 12 +-- api/tests/test_views.py | 117 ++++++++++++++++++++++++++++ api/utils/queue_utils.py | 11 +-- api/utils/user_utils.py | 2 - 7 files changed, 382 insertions(+), 26 deletions(-) diff --git a/api/tests/test_attributes.py b/api/tests/test_attributes.py index 06199df..0157529 100644 --- a/api/tests/test_attributes.py +++ b/api/tests/test_attributes.py @@ -5,7 +5,7 @@ from django.utils import timezone from rest_framework.reverse import reverse from rest_framework.test import APITestCase -from api.models import TokenAuthUser, UserType, Resource, ServiceProvider, Attribute +from api.models import TokenAuthUser, UserType, Resource, ServiceProvider, Attribute, QueueJob class AttributeUpdateTest(APITestCase): @@ -41,6 +41,15 @@ class AttributeUpdateTest(APITestCase): vec_sp=1, vec_idp=0) + TokenAuthUser.objects.create_superuser(username="testservice", + email="testservice@a.edu", + password="a_super", + user_type=UserType.TYPE_SP, + api_url="http://api.a.edu:7000/", + realm="a.edu", + sp=sp, + ) + def test_attribute_update(self): url = reverse('resource_attributes', args=[self.res.uuid]) @@ -58,12 +67,56 @@ class AttributeUpdateTest(APITestCase): } ] + self.assertEqual(0, QueueJob.objects.count()) + response = self.client.put(url, data=data, format='json') + print(response.data) + + self.assertEqual("updated", response.data[0]["Quota"]["status"]) + self.assertEqual(50, self.attrib.value) + + self.assertEqual("non-existent", response.data[1]["cpuTime"]["status"]) + self.assertEqual(1, QueueJob.objects.count()) + + data = [ + { + "name": "Quota", + "value": 23 + } + ] + + response = self.client.put(url, data=data, format='json') + + self.assertEqual("updated", response.data[0]["Quota"]["status"]) + self.assertEqual(23, int(Attribute.objects.get().value)) + self.assertEqual(3, Attribute.objects.get().vec_sp) + self.assertEqual(0, Attribute.objects.get().vec_idp) + self.assertEqual(2, QueueJob.objects.count()) + + def test_attribute_update_as_sp(self): + url = reverse('resource_attributes', args=[self.res.uuid]) + + user = TokenAuthUser.objects.get(username='testservice') + self.client.force_authenticate(user=user, token=user.token()) + + data = [ + { + "name": "Quota", + "value": 23 + }, + { + "name": "cpuTime", + "value": 42 + } + ] + + self.assertEqual(0, QueueJob.objects.count()) response = self.client.put(url, data=data, format='json') self.assertEqual("updated", response.data[0]["Quota"]["status"]) self.assertEqual(50, self.attrib.value) self.assertEqual("non-existent", response.data[1]["cpuTime"]["status"]) + self.assertEqual(1, QueueJob.objects.count()) data = [ { @@ -78,3 +131,4 @@ class AttributeUpdateTest(APITestCase): self.assertEqual(23, int(Attribute.objects.get().value)) self.assertEqual(3, Attribute.objects.get().vec_sp) self.assertEqual(0, Attribute.objects.get().vec_idp) + self.assertEqual(2, QueueJob.objects.count()) diff --git a/api/tests/test_health.py b/api/tests/test_health.py index d0dbfde..2eb115e 100644 --- a/api/tests/test_health.py +++ b/api/tests/test_health.py @@ -1,11 +1,18 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +from dateutil.relativedelta import relativedelta +from django.core.management import call_command +from django.utils import timezone +from django.test import TestCase +import requests +import requests_mock from rest_framework.authtoken.models import Token from rest_framework.reverse import reverse from rest_framework.test import APITestCase +import uuid -from api.models import TokenAuthUser, UserType +from api.models import QueueJob, QueueJobStatus, QueueJobType, TokenAuthUser, UserType class AttributeUpdateTest(APITestCase): @@ -38,3 +45,59 @@ class AttributeUpdateTest(APITestCase): self.client.force_authenticate(user=user, token=token) response = self.client.get(url, format='json') self.assertEqual(response.data, user.username) + + +class TestHealthCommand(TestCase): + def test_no_errors_exit_with_0(self): + with self.assertRaises(SystemExit) as ex: + call_command("check_health") + self.assertEqual(ex.exception.code, 0) + + def test_11_min_old_queuejob_exist_with_1(self): + old = timezone.now() - relativedelta(minutes=11) + print(old) + qj = QueueJob( + added=old, + res_uuid=uuid.uuid4(), + obj="{}", + status=QueueJobStatus.STATUS_READY, + type=QueueJobType.TYPE_RES, + realm="foo.bar" + ) + qj.full_clean() + qj.save() + # added is auto_add_now field. lets fake it. + qj.added = old + qj.save() + print(qj.added) + with self.assertRaises(SystemExit) as ex: + call_command("check_health") + self.assertEqual(ex.exception.code, 1) + + def test_remote_error_fails_with_1(self): + remote_url = 'https://remote.example.org/api' + remote_realm = 'foo.bar' + remote_user = TokenAuthUser(user_type=UserType.TYPE_SYNC, username='foobar', realm=remote_realm, api_url=remote_url) + remote_user.set_unusable_password() + remote_user.full_clean() + remote_user.save() + + with requests_mock.Mocker() as m: + m.register_uri("GET", remote_user.remote_reverse("health"), status_code=500) + with self.assertRaises(SystemExit) as ex: + call_command("check_health") + self.assertEqual(ex.exception.code, 1) + + def test_remote_not_available_fails_with_1(self): + remote_url = 'https://remote.example.org/api' + remote_realm = 'foo.bar' + remote_user = TokenAuthUser(user_type=UserType.TYPE_SYNC, username='foobar', realm=remote_realm, api_url=remote_url) + remote_user.set_unusable_password() + remote_user.full_clean() + remote_user.save() + + with requests_mock.Mocker() as m: + m.register_uri("GET", remote_user.remote_reverse("health"), exc=requests.exceptions.ConnectTimeout) + with self.assertRaises(SystemExit) as ex: + call_command("check_health") + self.assertEqual(ex.exception.code, 1) diff --git a/api/tests/test_queue.py b/api/tests/test_queue.py index 98db9d7..a318da5 100644 --- a/api/tests/test_queue.py +++ b/api/tests/test_queue.py @@ -4,7 +4,6 @@ from __future__ import division, print_function, unicode_literals import requests_mock from django.test import TestCase -from rest_framework.test import APITestCase from api.models import Attribute, QueueJob, QueueJobStatus, QueueJobType, Resource, ServiceProvider, TokenAuthUser, UserType from api.utils import queue_utils @@ -12,12 +11,6 @@ import json import six -class ResourceQueueSyncTest(APITestCase): - def test_remote_answers_with_400(self): - with requests_mock.Mocker() as m: - pass - - class DispatchRessourceSyncTest(TestCase): def test_resource(self): self.assertEqual(QueueJob.objects.count(), 0) @@ -27,10 +20,10 @@ class DispatchRessourceSyncTest(TestCase): remote_user.set_unusable_password() remote_user.full_clean() remote_user.save() - sp = ServiceProvider(realm=remote_realm, name="foo2", expiry_date='2099-01-01') + sp = ServiceProvider(realm=remote_realm, name="foo2", expiry_date='2099-01-01 00:00:00Z') sp.full_clean() sp.save() - r = Resource(sp=sp, eppn='user@foo.bar', expiry_date='2016-01-01 00:00:00', deletion_date='2017-01-01 00:00:00', setup_token='1234') + r = Resource(sp=sp, eppn='user@foo.bar', expiry_date='2016-01-01 00:00:00+01:00', deletion_date='2017-01-01 00:00:00+01:00', setup_token='1234') r.full_clean() r.save() att = Attribute(resource=r, name="foo", value="1234") @@ -39,7 +32,7 @@ class DispatchRessourceSyncTest(TestCase): att2 = Attribute(resource=r, name="bar", value="5678") att2.full_clean() att2.save() - + queue_utils.dispatch_resource_sync(r) self.assertEqual(QueueJob.objects.count(), 1) qj = QueueJob.objects.first() @@ -53,4 +46,134 @@ class DispatchRessourceSyncTest(TestCase): self.assertEqual(len(object_data['attributes']), 2) for a in (att, att2): self.assertTrue({'default_value': '', 'name': a.name, 'value': a.value, 'vec_idp': a.vec_idp, 'vec_sp': a.vec_sp} in object_data['attributes']) - print(object_data) + + +class SyncResourceTest(TestCase): + def setUp(self): + self.remote_url = 'https://remote.example.org/api' + self.remote_realm = 'foo.bar' + self.remote_user = TokenAuthUser(user_type=UserType.TYPE_SYNC, username='foobar', realm=self.remote_realm, api_url=self.remote_url) + self.remote_user.set_unusable_password() + self.remote_user.full_clean() + self.remote_user.save() + + def test_success(self): + """ + Dieser Test testet, ob die Daten remote gepostet werden + """ + transfer_data = '{"foo": "bar"}' + with requests_mock.Mocker() as m: + m.register_uri('POST', self.remote_user.remote_reverse("resource_list"), status_code=201) + queue_utils.sync_resource(self.remote_user, transfer_data) + self.assertTrue(m.called) + # content matches + self.assertEquals(m.last_request.text, transfer_data) + # authenticated + self.assertEquals(m.last_request.headers['Authorization'], "token {}".format(self.remote_user.token())) + + def test_error(self): + """ + Dieser Test testet, ob die Daten remote gepostet werden + """ + transfer_data = '{"foo": "bar"}' + with requests_mock.Mocker() as m: + m.register_uri('POST', self.remote_user.remote_reverse("resource_list"), status_code=500) + with self.assertRaises(queue_utils.SyncException): + queue_utils.sync_resource(self.remote_user, transfer_data) + self.assertTrue(m.called) + + def test_double_post(self): + transfer_data = '{"foo": "bar", "uuid": "12345"}' + uuid = '12345' + with requests_mock.Mocker() as m: + m.register_uri('POST', self.remote_user.remote_reverse("resource_list"), status_code=400) + m.register_uri('GET', self.remote_user.remote_reverse("resource_detail", args=(uuid, )), status_code=200) + queue_utils.sync_resource(self.remote_user, transfer_data) + self.assertTrue(m.called) + + def test_double_post_failed(self): + transfer_data = '{"foo": "bar", "uuid": "12345"}' + uuid = '12345' + with requests_mock.Mocker() as m: + m.register_uri('POST', self.remote_user.remote_reverse("resource_list"), status_code=400) + m.register_uri('GET', self.remote_user.remote_reverse("resource_detail", args=(uuid, )), status_code=404) + with self.assertRaises(queue_utils.SyncException): + queue_utils.sync_resource(self.remote_user, transfer_data) + self.assertTrue(m.called) + + +class SyncAttributesTest(TestCase): + def setUp(self): + self.remote_url = 'https://remote.example.org/api' + self.remote_realm = 'foo.bar' + self.remote_user = TokenAuthUser(user_type=UserType.TYPE_SYNC, username='foobar', realm=self.remote_realm, api_url=self.remote_url) + self.remote_user.set_unusable_password() + self.remote_user.full_clean() + self.remote_user.save() + sp = ServiceProvider(realm=self.remote_realm, name="foo2", expiry_date='2099-01-01 00:00:00Z') + sp.full_clean() + sp.save() + self.r = Resource(sp=sp, eppn='user@foo.bar', expiry_date='2016-01-01 00:00:00+01:00', deletion_date='2017-01-01 00:00:00+01:00', setup_token='1234') + self.r.full_clean() + self.r.save() + self.foo = Attribute(resource=self.r, name="foo", value="1234") + self.foo.full_clean() + self.foo.save() + self.bar = Attribute(resource=self.r, name="bar", value="5678") + self.bar.full_clean() + self.bar.save() + + def test_success(self): + transfer_data = json.dumps({"foo": "bar", "uuid": str(self.r.uuid)}) + answer = json.dumps([ + { + 'foo': {'vec_idp': 2, 'vec_sp': 3, 'status': 'updated'}, + } + ]) + with requests_mock.Mocker() as m: + m.register_uri('PUT', self.remote_user.remote_reverse("resource_attributes", args=(self.r.pk, )), status_code=200, text=answer) + queue_utils.sync_attributes(self.remote_user, transfer_data, str(self.r.pk)) + foo = Attribute.objects.get(pk=self.foo.pk) + self.assertEquals(foo.vec_idp, 2) + self.assertEquals(foo.vec_sp, 3) + + def test_failure(self): + transfer_data = json.dumps({"foo": "bar", "uuid": str(self.r.uuid)}) + answer = json.dumps([ + { + 'foo': {'vec_idp': 2, 'vec_sp': 3, 'status': 'updated'}, + } + ]) + with requests_mock.Mocker() as m: + m.register_uri('PUT', self.remote_user.remote_reverse("resource_attributes", args=(self.r.pk, )), status_code=404, text=answer) + with self.assertRaises(queue_utils.SyncException): + queue_utils.sync_attributes(self.remote_user, transfer_data, str(self.r.pk)) + + +class DeleteResourceTest(TestCase): + def setUp(self): + self.remote_url = 'https://remote.example.org/api' + self.remote_realm = 'foo.bar' + self.remote_user = TokenAuthUser(user_type=UserType.TYPE_SYNC, username='foobar', realm=self.remote_realm, api_url=self.remote_url) + self.remote_user.set_unusable_password() + self.remote_user.full_clean() + self.remote_user.save() + + def test_success(self): + uuid = "12345" + with requests_mock.Mocker() as m: + m.register_uri('DELETE', self.remote_user.remote_reverse("resource_detail", args=(uuid, )), status_code=200) + queue_utils.delete_resource(self.remote_user, uuid) + + def test_not_found(self): + uuid = "12345" + with requests_mock.Mocker() as m: + m.register_uri('DELETE', self.remote_user.remote_reverse("resource_detail", args=(uuid, )), status_code=404) + queue_utils.delete_resource(self.remote_user, uuid) + + def test_failure(self): + uuid = "12345" + with requests_mock.Mocker() as m: + m.register_uri('DELETE', self.remote_user.remote_reverse("resource_detail", args=(uuid, )), status_code=500) + with self.assertRaises(queue_utils.SyncException): + queue_utils.delete_resource(self.remote_user, uuid) diff --git a/api/tests/test_user_utils.py b/api/tests/test_user_utils.py index bc00984..00368a8 100644 --- a/api/tests/test_user_utils.py +++ b/api/tests/test_user_utils.py @@ -56,10 +56,10 @@ class UserUtilTest(TestCase): remote_user.save() # this case: we are service provider, user is from different instance - sp = ServiceProvider(realm=settings.SERVER_REALM, name="foo", expiry_date='2099-01-01') + sp = ServiceProvider(realm=settings.SERVER_REALM, name="foo", expiry_date='2099-01-01 00:00:00Z') sp.full_clean() sp.save() - r = Resource(sp=sp, eppn="user@{}".format(remote_realm), expiry_date='2016-12-16 00:00:00', deletion_date='2016-12-16 00:00:00') + r = Resource(sp=sp, eppn="user@{}".format(remote_realm), expiry_date='2016-12-16 00:00:00+01:00', deletion_date='2016-12-16 00:00:00+01:00') r.save() self.assertEqual(user_utils.get_remote_url_by_res_uuid(r.pk), remote_user.api_url) @@ -67,7 +67,7 @@ class UserUtilTest(TestCase): sp2 = ServiceProvider(realm=remote_realm, name="foo2", expiry_date='2099-01-01') sp2.full_clean() sp2.save() - r = Resource(sp=sp2, eppn="user@{}".format(settings.SERVER_REALM), expiry_date='2016-12-16 00:00:00', deletion_date='2016-12-16 00:00:00') + r = Resource(sp=sp2, eppn="user@{}".format(settings.SERVER_REALM), expiry_date='2016-12-16 00:00:00+01:00', deletion_date='2016-12-16 00:00:00+01:00') r.save() self.assertEqual(user_utils.get_remote_url_by_res_uuid(r.pk), remote_user.api_url) @override_settings( @@ -85,10 +85,10 @@ class UserUtilTest(TestCase): remote_user.save() # this case: we are service provider, user is from different instance - sp = ServiceProvider(realm=settings.SERVER_REALM, name="foo", expiry_date='2099-01-01') + sp = ServiceProvider(realm=settings.SERVER_REALM, name="foo", expiry_date='2099-01-01 00:00:00Z') sp.full_clean() sp.save() - r = Resource(sp=sp, eppn="user@{}".format(remote_realm), expiry_date='2016-12-16 00:00:00', deletion_date='2016-12-16 00:00:00') + r = Resource(sp=sp, eppn="user@{}".format(remote_realm), expiry_date='2016-12-16 00:00:00Z', deletion_date='2016-12-16 00:00:00Z') r.save() self.assertEqual(user_utils.get_remote_token_by_res_uuid(r.pk), remote_user.token()) @@ -96,6 +96,6 @@ class UserUtilTest(TestCase): sp2 = ServiceProvider(realm=remote_realm, name="foo2", expiry_date='2099-01-01') sp2.full_clean() sp2.save() - r = Resource(sp=sp2, eppn="user@{}".format(settings.SERVER_REALM), expiry_date='2016-12-16 00:00:00', deletion_date='2016-12-16 00:00:00') + r = Resource(sp=sp2, eppn="user@{}".format(settings.SERVER_REALM), expiry_date='2016-12-16 00:00:00+01:00', deletion_date='2016-12-16 00:00:00+01:00') r.save() self.assertEqual(user_utils.get_remote_token_by_res_uuid(r.pk), remote_user.token()) diff --git a/api/tests/test_views.py b/api/tests/test_views.py index b2c5b97..6de4756 100644 --- a/api/tests/test_views.py +++ b/api/tests/test_views.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals, print_function import json +import uuid from unittest import skip from django.test import override_settings @@ -179,3 +180,119 @@ class ResourceCreateTest(APITestCase): self._test_create_from_sp(self.sp_user, 201) self.assertEqual(Resource.objects.filter(eppn=self.localResource.eppn, sp=self.local_sp).count(), 1) + +class ResourceGetTest(APITestCase): + def setUp(self): + self.local_sp = ServiceProvider.objects.create( + name="TestService", + expiry_date=timezone.now(), + realm="a.edu" + ) + self.sp_user = TokenAuthUser.objects.create_superuser( + username='sp', + email='foo@bar.com', + password='sp', + user_type=UserType.TYPE_SP, + api_url="http://api.a.edu:7000/", + realm="a.edu", + sp=self.local_sp, + ) + + def test_unauthenticated(self): + invalid_uuid = str(uuid.uuid4()) + url = reverse("resource_detail", args=(invalid_uuid,)) + r = self.client.get(url) + self.assertEqual(r.status_code, 401) + + def test_not_exist(self): + invalid_uuid = str(uuid.uuid4()) + self.client.force_authenticate(self.sp_user) + url = reverse("resource_detail", args=(invalid_uuid,)) + r = self.client.get(url) + self.assertEqual(r.status_code, 404) + + def test_regular(self): + r = Resource(sp=self.local_sp, expiry_date=timezone.now(), deletion_date=timezone.now(), setup_token="1234", eppn="foo@foo.bar") + r.full_clean() + r.save() + self.client.force_authenticate(self.sp_user) + url = reverse("resource_detail", args=(r.pk,)) + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + + +class AttributesTest(APITestCase): + def setUp(self): + self.local_sp = ServiceProvider.objects.create( + name="TestService", + expiry_date=timezone.now(), + realm="a.edu" + ) + self.sp_user = TokenAuthUser.objects.create_superuser( + username='sp', + email='foo@bar.com', + password='sp', + user_type=UserType.TYPE_SP, + api_url="http://api.a.edu:7000/", + realm="a.edu", + sp=self.local_sp, + ) + + def test_unauthenticated(self): + invalid_uuid = str(uuid.uuid4()) + url = reverse("resource_attributes", args=(invalid_uuid,)) + r = self.client.get(url) + self.assertEqual(r.status_code, 401) + + def test_not_exist(self): + invalid_uuid = str(uuid.uuid4()) + self.client.force_authenticate(self.sp_user) + url = reverse("resource_attributes", args=(invalid_uuid,)) + r = self.client.get(url) + self.assertEqual(r.status_code, 404) + + def test_regular(self): + r = Resource(sp=self.local_sp, expiry_date=timezone.now(), deletion_date=timezone.now(), setup_token="1234", eppn="foo@foo.bar") + r.full_clean() + r.save() + self.client.force_authenticate(self.sp_user) + url = reverse("resource_attributes", args=(r.pk,)) + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + + +class ServiceProviderGetTest(APITestCase): + def setUp(self): + self.local_sp = ServiceProvider.objects.create( + name="TestService", + expiry_date=timezone.now(), + realm="a.edu" + ) + self.sp_user = TokenAuthUser.objects.create_superuser( + username='sp', + email='foo@bar.com', + password='sp', + user_type=UserType.TYPE_SP, + api_url="http://api.a.edu:7000/", + realm="a.edu", + sp=self.local_sp, + ) + + def test_unauthenticated(self): + invalid_uuid = str(uuid.uuid4()) + url = reverse("service_detail", args=(invalid_uuid,)) + r = self.client.get(url) + self.assertEqual(r.status_code, 401) + + def test_not_exist(self): + invalid_uuid = str(uuid.uuid4()) + self.client.force_authenticate(self.sp_user) + url = reverse("service_detail", args=(invalid_uuid,)) + r = self.client.get(url) + self.assertEqual(r.status_code, 404) + + def test_regular(self): + self.client.force_authenticate(self.sp_user) + url = reverse("service_detail", args=(self.local_sp.pk,)) + r = self.client.get(url) + self.assertEqual(r.status_code, 200) diff --git a/api/utils/queue_utils.py b/api/utils/queue_utils.py index f714c0d..0a68969 100644 --- a/api/utils/queue_utils.py +++ b/api/utils/queue_utils.py @@ -96,10 +96,11 @@ def sync_attributes(sync_user, attributes_json, res_uuid): res = Resource.objects.get(uuid=res_uuid) for attrib in data: - if attrib.values()[0]["status"] == "updated": - obj = Attribute.objects.get(name=attrib.keys()[0], resource=res) - obj.vec_sp = attrib.values()[0]["vec_sp"] - obj.vec_idp = attrib.values()[0]["vec_idp"] + keys, values = zip(*attrib.items()) + if values[0]["status"] == "updated": + obj = Attribute.objects.get(name=keys[0], resource=res) + obj.vec_sp = values[0]["vec_sp"] + obj.vec_idp = values[0]["vec_idp"] obj.save() @@ -124,6 +125,6 @@ def delete_resource(sync_user, res_uuid): r = requests.delete(url, headers=headers, timeout=5) - if not r.status_code == 200: + if not r.status_code in (200, 404): logger.debug("Unexpected response: {}".format(r.content)) raise SyncException("Sync failed: Host responded with {code}".format(code=r.status_code)) diff --git a/api/utils/user_utils.py b/api/utils/user_utils.py index 238fcf8..bcf4f4a 100644 --- a/api/utils/user_utils.py +++ b/api/utils/user_utils.py @@ -72,8 +72,6 @@ def local_reverse(*args, **kwargs): r = reverse(*args, **kwargs) local_prefix = get_script_prefix() - print("r: {}".format(r)) - if r.startswith(local_prefix): r = r[len(local_prefix):] -- GitLab