433 lines
15 KiB
Python
433 lines
15 KiB
Python
import random
|
|
from datetime import datetime, timedelta
|
|
|
|
import factory
|
|
from django.contrib.auth.models import Group
|
|
from django.db import transaction
|
|
from django.test import Client, TestCase
|
|
from django.utils.timezone import now
|
|
from factory import fuzzy
|
|
|
|
import pytest
|
|
from network.base.models import ANTENNA_BANDS, ANTENNA_TYPES, \
|
|
OBSERVATION_STATUSES, Antenna, DemodData, Observation, Satellite, \
|
|
Station, Tle
|
|
from network.users.tests import UserFactory
|
|
|
|
ANTENNA_BAND_IDS = [c[0] for c in ANTENNA_BANDS]
|
|
ANTENNA_TYPE_IDS = [c[0] for c in ANTENNA_TYPES]
|
|
OBSERVATION_STATUS_IDS = [c[0] for c in OBSERVATION_STATUSES]
|
|
|
|
|
|
def generate_payload():
|
|
payload = '{0:b}'.format(random.randint(500000000, 510000000))
|
|
digits = 1824
|
|
while digits:
|
|
digit = random.randint(0, 1)
|
|
payload += str(digit)
|
|
digits -= 1
|
|
return payload
|
|
|
|
|
|
def generate_payload_name():
|
|
filename = datetime.strftime(fuzzy.FuzzyDateTime(now() - timedelta(days=10), now()).fuzz(),
|
|
'%Y%m%dT%H%M%SZ')
|
|
return filename
|
|
|
|
|
|
class AntennaFactory(factory.django.DjangoModelFactory):
|
|
"""Antenna model factory."""
|
|
frequency = fuzzy.FuzzyFloat(200, 500)
|
|
frequency_max = fuzzy.FuzzyFloat(500, 800)
|
|
band = fuzzy.FuzzyChoice(choices=ANTENNA_BAND_IDS)
|
|
antenna_type = fuzzy.FuzzyChoice(choices=ANTENNA_TYPE_IDS)
|
|
|
|
class Meta:
|
|
model = Antenna
|
|
|
|
|
|
class StationFactory(factory.django.DjangoModelFactory):
|
|
"""Station model factory."""
|
|
owner = factory.SubFactory(UserFactory)
|
|
name = fuzzy.FuzzyText()
|
|
image = factory.django.ImageField()
|
|
alt = fuzzy.FuzzyInteger(0, 800)
|
|
lat = fuzzy.FuzzyFloat(-20, 70)
|
|
lng = fuzzy.FuzzyFloat(-180, 180)
|
|
featured_date = fuzzy.FuzzyDateTime(now() - timedelta(days=10), now())
|
|
testing = fuzzy.FuzzyChoice(choices=[True, False])
|
|
last_seen = fuzzy.FuzzyDateTime(now() - timedelta(days=3), now())
|
|
horizon = fuzzy.FuzzyInteger(10, 20)
|
|
|
|
@factory.post_generation
|
|
def antennas(self, create, extracted, **kwargs):
|
|
if not create:
|
|
return
|
|
|
|
if extracted:
|
|
for antenna in extracted:
|
|
if random.randint(0, 1):
|
|
self.antenna.add(antenna)
|
|
|
|
class Meta:
|
|
model = Station
|
|
|
|
|
|
class SatelliteFactory(factory.django.DjangoModelFactory):
|
|
"""Sattelite model factory."""
|
|
norad_cat_id = fuzzy.FuzzyInteger(2000, 4000)
|
|
name = fuzzy.FuzzyText()
|
|
|
|
class Meta:
|
|
model = Satellite
|
|
|
|
|
|
class TleFactory(factory.django.DjangoModelFactory):
|
|
"""Tle model factory."""
|
|
tle0 = 'ISS (ZARYA)'
|
|
tle1 = '1 25544U 98067A 17355.27738426 .00002760 00000-0 48789-4 0 9995'
|
|
tle2 = '2 25544 51.6403 185.6460 0002546 270.9261 71.9125 15.54204066 90844'
|
|
updated = fuzzy.FuzzyDateTime(now() - timedelta(days=3), now())
|
|
satellite = factory.SubFactory(SatelliteFactory)
|
|
|
|
class Meta:
|
|
model = Tle
|
|
|
|
|
|
class ObservationFactory(factory.django.DjangoModelFactory):
|
|
"""Observation model factory."""
|
|
satellite = factory.SubFactory(SatelliteFactory)
|
|
tle = factory.SubFactory(TleFactory)
|
|
author = factory.SubFactory(UserFactory)
|
|
start = fuzzy.FuzzyDateTime(now() - timedelta(days=3),
|
|
now() + timedelta(days=3))
|
|
end = factory.LazyAttribute(
|
|
lambda x: x.start + timedelta(hours=random.randint(1, 8))
|
|
)
|
|
ground_station = factory.Iterator(Station.objects.all())
|
|
payload = factory.django.FileField(filename='data.ogg')
|
|
vetted_datetime = factory.LazyAttribute(
|
|
lambda x: x.end + timedelta(hours=random.randint(1, 20))
|
|
)
|
|
vetted_user = factory.SubFactory(UserFactory)
|
|
vetted_status = fuzzy.FuzzyChoice(choices=OBSERVATION_STATUS_IDS)
|
|
transmitter_uuid = fuzzy.FuzzyText(length=20)
|
|
transmitter_description = fuzzy.FuzzyText()
|
|
transmitter_uplink_low = fuzzy.FuzzyInteger(200000000, 500000000, step=10000)
|
|
transmitter_uplink_high = fuzzy.FuzzyInteger(200000000, 500000000, step=10000)
|
|
transmitter_downlink_low = fuzzy.FuzzyInteger(200000000, 500000000, step=10000)
|
|
transmitter_downlink_high = fuzzy.FuzzyInteger(200000000, 500000000, step=10000)
|
|
transmitter_mode = fuzzy.FuzzyText(length=10)
|
|
transmitter_invert = fuzzy.FuzzyChoice(choices=[True, False])
|
|
transmitter_baud = fuzzy.FuzzyInteger(4000, 22000, step=1000)
|
|
transmitter_created = fuzzy.FuzzyDateTime(now() - timedelta(days=100),
|
|
now() - timedelta(days=3))
|
|
|
|
class Meta:
|
|
model = Observation
|
|
|
|
|
|
class DemodDataFactory(factory.django.DjangoModelFactory):
|
|
observation = factory.Iterator(Observation.objects.all())
|
|
payload_demod = factory.django.FileField()
|
|
|
|
class Meta:
|
|
model = DemodData
|
|
|
|
|
|
@pytest.mark.django_db(transaction=True)
|
|
class HomeViewTest(TestCase):
|
|
"""
|
|
Simple test to make sure the home page is working
|
|
"""
|
|
def test_home_page(self):
|
|
response = self.client.get('/')
|
|
self.assertContains(response, 'Crowd-sourced satellite operations')
|
|
|
|
|
|
@pytest.mark.django_db(transaction=True)
|
|
class AboutViewTest(TestCase):
|
|
"""
|
|
Simple test to make sure the about page is working
|
|
"""
|
|
def test_about_page(self):
|
|
response = self.client.get('/about/')
|
|
self.assertContains(response, 'SatNOGS Network is a global management interface')
|
|
|
|
|
|
@pytest.mark.django_db
|
|
class StationListViewTest(TestCase):
|
|
"""
|
|
Test to ensure the station list is generated by Django
|
|
"""
|
|
client = Client()
|
|
stations = []
|
|
|
|
def setUp(self):
|
|
for x in xrange(1, 10):
|
|
self.stations.append(StationFactory())
|
|
|
|
def test_station_list(self):
|
|
response = self.client.get('/stations/')
|
|
for x in self.stations:
|
|
self.assertContains(response, x.owner)
|
|
self.assertContains(response, x.name)
|
|
|
|
|
|
@pytest.mark.django_db(transaction=True)
|
|
class ObservationsListViewTest(TestCase):
|
|
"""
|
|
Test to ensure the observation list is generated by Django
|
|
"""
|
|
client = Client()
|
|
observations = []
|
|
satellites = []
|
|
stations = []
|
|
|
|
def setUp(self):
|
|
# Clear the data and create some new random data
|
|
with transaction.atomic():
|
|
Observation.objects.all().delete()
|
|
Satellite.objects.all().delete()
|
|
self.satellites = []
|
|
self.observations_bad = []
|
|
self.observations_good = []
|
|
self.observations_unvetted = []
|
|
self.observations = []
|
|
with transaction.atomic():
|
|
for x in xrange(1, 10):
|
|
self.satellites.append(SatelliteFactory())
|
|
for x in xrange(1, 10):
|
|
self.stations.append(StationFactory())
|
|
for x in xrange(1, 5):
|
|
obs = ObservationFactory(vetted_status='bad')
|
|
self.observations_bad.append(obs)
|
|
self.observations.append(obs)
|
|
for x in xrange(1, 5):
|
|
obs = ObservationFactory(vetted_status='good')
|
|
self.observations_good.append(obs)
|
|
self.observations.append(obs)
|
|
for x in xrange(1, 5):
|
|
obs = ObservationFactory(vetted_status='unknown')
|
|
self.observations_unvetted.append(obs)
|
|
self.observations.append(obs)
|
|
|
|
def test_observations_list(self):
|
|
response = self.client.get('/observations/')
|
|
for x in self.observations:
|
|
self.assertContains(response, x.transmitter_mode)
|
|
|
|
def test_observations_list_select_bad(self):
|
|
response = self.client.get('/observations/?bad=1')
|
|
|
|
for x in self.observations_bad:
|
|
self.assertContains(response, x.transmitter_mode)
|
|
|
|
def test_observations_list_select_good(self):
|
|
response = self.client.get('/observations/?good=1')
|
|
|
|
for x in self.observations_good:
|
|
self.assertContains(response, x.transmitter_mode)
|
|
|
|
def test_observations_list_select_unvetted(self):
|
|
response = self.client.get('/observations/?unvetted=1')
|
|
|
|
for x in self.observations_unvetted:
|
|
self.assertContains(response, x.transmitter_mode)
|
|
|
|
|
|
class NotFoundErrorTest(TestCase):
|
|
"""
|
|
Test the 404 not found handler
|
|
"""
|
|
client = Client()
|
|
|
|
def test_404_not_found(self):
|
|
response = self.client.get('/blah')
|
|
self.assertEquals(response.status_code, 404)
|
|
|
|
|
|
class RobotsViewTest(TestCase):
|
|
"""
|
|
Test the robots.txt handler
|
|
"""
|
|
client = Client()
|
|
|
|
def test_robots(self):
|
|
response = self.client.get('/robots.txt')
|
|
self.assertContains(response, 'Disallow: /')
|
|
|
|
|
|
@pytest.mark.django_db(transaction=True)
|
|
class ObservationViewTest(TestCase):
|
|
"""
|
|
Test to ensure the observation list is generated by Django
|
|
"""
|
|
client = Client()
|
|
observation = None
|
|
satellites = []
|
|
stations = []
|
|
user = None
|
|
|
|
def setUp(self):
|
|
self.user = UserFactory()
|
|
g = Group.objects.get(name='Moderators')
|
|
g.user_set.add(self.user)
|
|
for x in xrange(1, 10):
|
|
self.satellites.append(SatelliteFactory())
|
|
for x in xrange(1, 10):
|
|
self.stations.append(StationFactory())
|
|
self.observation = ObservationFactory()
|
|
|
|
def test_observation(self):
|
|
response = self.client.get('/observations/%d/' % self.observation.id)
|
|
self.assertContains(response, self.observation.author.username)
|
|
self.assertContains(response, self.observation.transmitter_mode)
|
|
|
|
|
|
@pytest.mark.django_db(transaction=True)
|
|
class ObservationDeleteTest(TestCase):
|
|
"""
|
|
Test to ensure the observation list is generated by Django
|
|
"""
|
|
client = Client()
|
|
user = None
|
|
future_observation = None
|
|
past_observation = None
|
|
satellites = []
|
|
|
|
def setUp(self):
|
|
self.user = UserFactory()
|
|
self.client.force_login(self.user)
|
|
for x in xrange(1, 10):
|
|
self.satellites.append(SatelliteFactory())
|
|
self.future_observation = ObservationFactory()
|
|
self.future_observation.author = self.user
|
|
self.future_observation.start = now() + timedelta(days=1)
|
|
self.future_observation.end = self.future_observation.start + timedelta(minutes=15)
|
|
self.future_observation.save()
|
|
self.past_observation = ObservationFactory()
|
|
self.past_observation.author = self.user
|
|
self.past_observation.start = now() - timedelta(days=1)
|
|
self.past_observation.end = self.past_observation.start + timedelta(minutes=15)
|
|
self.past_observation.save()
|
|
|
|
def test_future_observation_delete_author(self):
|
|
"""Deletion OK when user is the author of the observation and observation is in future"""
|
|
response = self.client.get('/observations/%d/delete/' % self.future_observation.id)
|
|
self.assertRedirects(response, '/observations/')
|
|
response = self.client.get('/observations/')
|
|
with self.assertRaises(Observation.DoesNotExist):
|
|
_lookup = Observation.objects.get(pk=self.future_observation.id) # noqa:F841
|
|
|
|
def test_future_observation_delete_moderator(self):
|
|
"""Deletion OK when user is moderator and observation is in future"""
|
|
self.user = UserFactory()
|
|
g = Group.objects.get(name='Moderators')
|
|
g.user_set.add(self.user)
|
|
self.client.force_login(self.user)
|
|
response = self.client.get('/observations/%d/delete/' % self.future_observation.id)
|
|
self.assertRedirects(response, '/observations/')
|
|
response = self.client.get('/observations/')
|
|
with self.assertRaises(Observation.DoesNotExist):
|
|
_lookup = Observation.objects.get(pk=self.future_observation.id) # noqa:F841
|
|
|
|
def test_past_observation_delete_author(self):
|
|
"""Deletion NOT OK when user is the author of the observation and observation is in past"""
|
|
response = self.client.get('/observations/%d/delete/' % self.past_observation.id)
|
|
self.assertRedirects(response, '/observations/')
|
|
response = self.client.get('/observations/')
|
|
self.assertContains(response, self.past_observation.id)
|
|
|
|
def test_past_observation_delete_moderator(self):
|
|
"""Deletion NOT OK when user is moderator and observation is in past"""
|
|
self.user = UserFactory()
|
|
g = Group.objects.get(name='Moderators')
|
|
g.user_set.add(self.user)
|
|
self.client.force_login(self.user)
|
|
response = self.client.get('/observations/%d/delete/' % self.past_observation.id)
|
|
self.assertRedirects(response, '/observations/')
|
|
response = self.client.get('/observations/')
|
|
self.assertContains(response, self.past_observation.id)
|
|
|
|
|
|
@pytest.mark.django_db(transaction=True)
|
|
class StationViewTest(TestCase):
|
|
"""
|
|
Test to ensure the observation list is generated by Django
|
|
"""
|
|
client = Client()
|
|
station = None
|
|
|
|
def setUp(self):
|
|
self.station = StationFactory()
|
|
|
|
def test_observation(self):
|
|
response = self.client.get('/stations/%d/' % self.station.id)
|
|
self.assertContains(response, self.station.owner.username)
|
|
self.assertContains(response, self.station.alt)
|
|
self.assertContains(response, self.station.horizon)
|
|
|
|
|
|
@pytest.mark.django_db(transaction=True)
|
|
class StationDeleteTest(TestCase):
|
|
"""
|
|
Test to ensure the observation list is generated by Django
|
|
"""
|
|
client = Client()
|
|
station = None
|
|
user = None
|
|
|
|
def setUp(self):
|
|
self.user = UserFactory()
|
|
self.client.force_login(self.user)
|
|
self.station = StationFactory()
|
|
self.station.owner = self.user
|
|
self.station.save()
|
|
|
|
def test_station_delete(self):
|
|
response = self.client.get('/stations/%d/delete/' % self.station.id)
|
|
self.assertRedirects(response, '/users/%s/' % self.user.username)
|
|
with self.assertRaises(Station.DoesNotExist):
|
|
_lookup = Station.objects.get(pk=self.station.id) # noqa:F841
|
|
|
|
|
|
@pytest.mark.django_db(transaction=True)
|
|
class SettingsSiteViewTest(TestCase):
|
|
"""
|
|
Test to ensure the satellite fetch feature works
|
|
"""
|
|
client = Client()
|
|
user = None
|
|
|
|
def setUp(self):
|
|
self.user = UserFactory()
|
|
self.user.is_superuser = True
|
|
self.user.save()
|
|
self.client.force_login(self.user)
|
|
|
|
def test_get(self):
|
|
response = self.client.get('/settings_site/')
|
|
self.assertContains(response, 'Fetch Data')
|
|
|
|
|
|
@pytest.mark.django_db(transaction=True)
|
|
class ObservationModelTest(TestCase):
|
|
"""
|
|
Test various properties of the Observation Model
|
|
"""
|
|
observation = None
|
|
satellites = []
|
|
user = None
|
|
admin = None
|
|
|
|
def setUp(self):
|
|
for x in xrange(1, 10):
|
|
self.satellites.append(SatelliteFactory())
|
|
self.observation = ObservationFactory()
|
|
self.observation.end = now()
|
|
self.observation.save()
|
|
|
|
def test_is_passed(self):
|
|
self.assertTrue(self.observation.is_past)
|