From 4141e275cca311f4cf41c1f7b9a9cf06971d5961 Mon Sep 17 00:00:00 2001 From: Corey Shields Date: Sun, 16 May 2021 18:54:48 -0400 Subject: [PATCH] Improve testing and handling of telemetry upload API Improved handling of input data for the telemetry API and added tests for such ensure that we return a 400 on an empty frame, station, timestamp return 400 when lat/lng value conversion fails or when the resulting lat/lng is out of range. Fixes #463 Signed-off-by: Corey Shields --- Dockerfile | 2 +- conftest.py | 10 ++++++++++ db/api/tests.py | 40 ++++++++++++++++++++++++++++++++++++++++ db/api/views.py | 23 +++++++++++++---------- db/settings.py | 2 +- requirements-dev.txt | 3 ++- setup.cfg | 1 + tox.ini | 10 +++++----- 8 files changed, 73 insertions(+), 18 deletions(-) create mode 100644 conftest.py diff --git a/Dockerfile b/Dockerfile index 73a8907..089f107 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM python:3.8.7 -MAINTAINER SatNOGS project +LABEL maintainer="SatNOGS project " WORKDIR /workdir/ diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..446e737 --- /dev/null +++ b/conftest.py @@ -0,0 +1,10 @@ +"""pytest configuration file""" +import pytest + + +@pytest.fixture(scope='session') +def celery_config(): + return { + 'broker_url': 'memory://', + 'result_backend': 'rpc', + } diff --git a/db/api/tests.py b/db/api/tests.py index 9210996..02528af 100644 --- a/db/api/tests.py +++ b/db/api/tests.py @@ -87,15 +87,20 @@ class TransmitterViewApiTest(TestCase): @pytest.mark.django_db(transaction=True) +@pytest.mark.usefixtures('celery_session_app') +@pytest.mark.usefixtures('celery_session_worker') class TelemetryViewApiTest(TestCase): """ Tests the Telemetry View API """ datum = None + satellite = None def setUp(self): self.datum = DemodDataFactory() self.datum.save() + self.satellite = SatelliteFactory() + self.satellite.save() def test_list(self): """Test the Telemetry API listing""" @@ -106,3 +111,38 @@ class TelemetryViewApiTest(TestCase): """Test the Telemetry API retrieval""" response = self.client.get('/api/telemetry/{0}/'.format(self.datum.id), format='json') self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + + def test_post(self): + """Test the SiDS posting capability""" + norad = self.satellite.satellite_entry.norad_cat_id + frame = '60A060A0A46E609C8262A6A640E082A0A4A682A86103F02776261C6C201C5' + frame += '3495D41524953532D496E7465726E6174696F6E616C2053706163652053746174696F6E3D0D' + + data = { + 'frame': frame, + 'locator': 'longLat', + 'latitude': '06.12S', + 'longitude': '59.34W', + 'noradID': str(norad), + 'source': 'T3ST', + 'timestamp': '2021-03-15T13:14:04.940Z', + 'version': '1.2.3' + } + response = self.client.post('/api/telemetry/', data=data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + def test_bad_post(self): + """Test the SiDS posting capability with bad data""" + norad = self.satellite.satellite_entry.norad_cat_id + + data = { + 'frame': '', + 'locator': 'longLat', + 'latitude': '206.12S', + 'longitude': '59.34WE', + 'noradID': str(norad), + 'source': '', + 'timestamp': '' + } + response = self.client.post('/api/telemetry/', data=data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) diff --git a/db/api/views.py b/db/api/views.py index 95486e2..3e6f6a7 100644 --- a/db/api/views.py +++ b/db/api/views.py @@ -226,7 +226,7 @@ class LatestTleSetViewSet(viewsets.ReadOnlyModelViewSet): # pylint: disable=R09 ], ), ) -class TelemetryViewSet( # pylint: disable=R0901 +class TelemetryViewSet( # pylint: disable=R0901,R0912,R0915 mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet): """ @@ -241,7 +241,7 @@ class TelemetryViewSet( # pylint: disable=R0901 serializer_class = serializers.TelemetrySerializer filterset_class = filters.TelemetryViewFilter permission_classes = [SafeMethodsWithPermission] - parser_classes = (FormParser, FileUploadParser) + parser_classes = (FormParser, MultiPartParser, FileUploadParser) pagination_class = pagination.LinkedHeaderPageNumberPagination @extend_schema( @@ -291,14 +291,17 @@ class TelemetryViewSet( # pylint: disable=R0901 # Convert coordinates to omit N-S and W-E designators lat = request.data.get('latitude') lng = request.data.get('longitude') - if any(x.isalpha() for x in lat): - data['lat'] = (-float(lat[:-1]) if ('S' in lat) else float(lat[:-1])) - else: - data['lat'] = float(lat) - if any(x.isalpha() for x in lng): - data['lng'] = (-float(lng[:-1]) if ('W' in lng) else float(lng[:-1])) - else: - data['lng'] = float(lng) + try: + if any(x.isalpha() for x in lat): + data['lat'] = (-float(lat[:-1]) if ('S' in lat) else float(lat[:-1])) + else: + data['lat'] = float(lat) + if any(x.isalpha() for x in lng): + data['lng'] = (-float(lng[:-1]) if ('W' in lng) else float(lng[:-1])) + else: + data['lng'] = float(lng) + except ValueError: + return Response(status=status.HTTP_400_BAD_REQUEST) # Network or SiDS submission? if request.data.get('satnogs_network'): diff --git a/db/settings.py b/db/settings.py index e208f3d..1d0c5e7 100644 --- a/db/settings.py +++ b/db/settings.py @@ -243,7 +243,7 @@ LOGGING = { # Sentry SENTRY_ENABLED = config('SENTRY_ENABLED', default=False, cast=bool) if SENTRY_ENABLED: - sentry_sdk.init( + sentry_sdk.init( # pylint: disable=abstract-class-instantiated environment=ENVIRONMENT, dsn=config('SENTRY_DSN', default=''), release='satnogs-db@{}'.format(__version__), diff --git a/requirements-dev.txt b/requirements-dev.txt index a482a19..5a2483d 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -18,10 +18,11 @@ iniconfig==1.1.1 mock==4.0.3 packaging==20.9 pluggy==0.13.1 -pur==5.4.0 +pur==5.4.1 py==1.10.0 pyparsing==2.4.7 pytest==6.2.4 +pytest-celery==0.0.0 pytest-cov==2.12.0 pytest-django==4.2.0 pytest-forked==1.3.0 diff --git a/setup.cfg b/setup.cfg index e3596ab..b5eff01 100644 --- a/setup.cfg +++ b/setup.cfg @@ -84,6 +84,7 @@ install_requires = [options.extras_require] dev = + pytest-celery pytest-cov~=2.12.0 pytest-django~=4.2.0 pytest-forked~=1.3.0 diff --git a/tox.ini b/tox.ini index dec360d..233ca10 100644 --- a/tox.ini +++ b/tox.ini @@ -2,11 +2,11 @@ envlist = flake8,isort,yapf,pylint,build,pytest,docs [depversions] -flake8 = 3.8.4 -isort = 5.7.0 -yapf = 0.30.0 -pylint = 2.6.0 -pylint_django = 2.4.2 +flake8 = 3.9.2 +isort = 5.8.0 +yapf = 0.31.0 +pylint = 2.8.2 +pylint_django = 2.4.4 sphinx_rtd_theme = 0.5.1 twine = 3.3.0