def _assert_duplicates_are_deleted(self, object_type): # Create a user, device and two duplicate reports user = Dummy.create_user() device = Dummy.create_device(user) report_1 = Dummy.create_report(object_type, device) Dummy.create_report(object_type, device) # Assert that 2 instances have been created self.assertEqual(object_type.objects.count(), 2) # Run the migration logger = logging.getLogger("crashreports") with self.assertLogs(logger, "DEBUG") as logging_watcher: self.migrate_to_dest() # Assert the correct message is logged self.assertTrue({ "INFO:crashreports.migrations." "0006_add_unique_constraints_and_drop_duplicates:" "Found 1 {} instances that have duplicates. " "These will be removed.".format(object_type.__name__), "DEBUG:crashreports.migrations" ".0006_add_unique_constraints_and_drop_duplicates:Removing " "duplicates: {}".format( str({ "device": device.id, "date": report_1.date, "min_id": report_1.id, "num_duplicates": 2, })), }.issubset(set(logging_watcher.output))) # Assert that only one instance is left in the database self.assertEqual(object_type.objects.count(), 1)
def test_change_of_date_field_type(self): """Test that the 'date' field of heartbeats is changed to a date.""" # Create a user, device and a heartbeat user = Dummy.create_user() device = Dummy.create_device(user) heartbeat_timestamp = datetime(2015, 12, 15, 1, 23, 45, tzinfo=pytz.utc) heartbeat = Dummy.create_report(HeartBeat, device, date=heartbeat_timestamp) # Assert that the date is of type datetime self.assertIsInstance(heartbeat.date, datetime) # Run the migration self.migrate_to_dest() # Assert that the date is now of type date and has the correct value heartbeat = HeartBeat.objects.first() self.assertIsInstance(heartbeat.date, date) self.assertEqual(heartbeat.date, heartbeat_timestamp.date())
def test_register(self): """Test registration of devices.""" response = self.client.post( reverse(self.REGISTER_DEVICE_URL), Dummy.device_register_data() ) self.assertTrue("token" in response.data) self.assertTrue("uuid" in response.data) self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_logfile_deletion(self): """Test deletion of logfile instances.""" # Create a user, device and crashreport with logfile device = Dummy.create_device(Dummy.create_user()) crashreport = Dummy.create_report(Crashreport, device) logfile, logfile_path = Dummy.create_log_file_with_actual_file( crashreport) # Assert that the crashreport and logfile have been created self.assertEqual(Crashreport.objects.count(), 1) self.assertEqual(LogFile.objects.count(), 1) self.assertTrue(os.path.isfile(logfile_path)) # Delete the logfile response = self.fp_staff_client.delete( reverse(self.POST_LOGFILE_URL, args=[logfile.id])) self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code) # Assert that the logfile has been deleted self.assertEqual(LogFile.objects.count(), 0) self.assertFalse(os.path.isfile(logfile_path))
def _assert_duplicate_entries_can_not_be_created(self, object_type): # Create a user, device and a report user = Dummy.create_user() device = Dummy.create_device(user) Dummy.create_report(object_type, device) # Assert creating a duplicate report fails logger = logging.getLogger("crashreports") with self.assertLogs(logger, "DEBUG") as logging_watcher: report = Dummy.create_report(object_type, device) self.assertEqual( logging_watcher.output, [ "DEBUG:crashreports.models:" "Duplicate {} received and dropped: {}".format( object_type.__name__, str(model_to_dict(report)) ) ], ) self.assertEqual(object_type.objects.count(), 1)
def test_delete_duplicate_crashreport_with_logfile(self): """Test deletion of a duplicate crashreport with logfile.""" # Create a user, device and two duplicate reports with logfiles user = Dummy.create_user() device = Dummy.create_device(user) crashreport_1 = Dummy.create_report(Crashreport, device) crashreport_2 = Dummy.create_report(Crashreport, device) _, logfile_1_path = Dummy.create_log_file_with_actual_file( crashreport_1) _, logfile_2_path = Dummy.create_log_file_with_actual_file( crashreport_2, logfile=Dummy.DEFAULT_LOG_FILE_PATHS[1]) # Assert that 2 crashreports and logfiles have been created self.assertEqual(Crashreport.objects.count(), 2) self.assertEqual(LogFile.objects.count(), 2) self.assertTrue(os.path.isfile(logfile_1_path)) self.assertTrue(os.path.isfile(logfile_2_path)) # Run the migration self.migrate_to_dest() # Assert that only one crashreport and one logfile is left in the # database self.assertEqual(Crashreport.objects.count(), 1) self.assertEqual(Crashreport.objects.first().logfiles.count(), 1) self.assertEqual(LogFile.objects.count(), 1) # Assert that the correct log file has been deleted self.assertTrue(os.path.isfile(logfile_1_path)) self.assertFalse(os.path.isfile(logfile_2_path))
def test_create_ambiguous_time_board_date(self): """Test registration with ambiguous time. Test the resolution of a naive date-time in which the Europe/Amsterdam daylight saving time transition moved the time "backward". The server should not crash when receiving a naive date-time that can belong to multiple timezones. """ data = Dummy.device_register_data() # In 2017, the Netherlands changed from CEST to CET on October, # 29 at 03:00 data["board_date"] = "2017-10-29 02:34:56" response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data) self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_create_non_existent_time_board_date(self): """Test registration with non existing time. Test the resolution of a naive date-time in which the Europe/Amsterdam daylight saving time transition moved the time "forward". The server should not crash when receiving a naive date-time which does not exist in the server timezone or locale. """ data = Dummy.device_register_data() # In 2017, the Netherlands changed from CET to CEST on March, # 26 at 02:00 data["board_date"] = "2017-03-26 02:34:56" response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data) self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_create_multiple_heartbeats(self): """Test that no race condition occurs when creating heartbeats.""" uuid, user, _ = self._register_device() def upload_report(client, data): response = client.post(reverse(self.LIST_CREATE_URL), data) self.assertEqual(status.HTTP_201_CREATED, response.status_code) connection.close() data = Dummy.heartbeat_data(uuid=uuid) argslist = [[user, dict(data, date=data["date"] + timedelta(days=i))] for i in range(10)] self._test_create_multiple(HeartBeat, upload_report, argslist, "device_local_id")
def upload_crashreport(self, user, uuid): """ Upload dummy crashreport data. Args: user: The user which should be used for uploading the report uuid: The uuid of the device to which the report should be uploaded Returns: The local id of the device for which the report was uploaded. """ data = Dummy.crashreport_data(uuid=uuid) response = user.post(reverse(LIST_CREATE_URL), data) self.assertEqual(status.HTTP_201_CREATED, response.status_code) self.assertTrue("device_local_id" in response.data) device_local_id = response.data["device_local_id"] return device_local_id
def _create_alternative_dummy_data(**kwargs): return Dummy.alternative_crashreport_data(**kwargs)
def _create_dummy_data(**kwargs): return Dummy.crashreport_data(**kwargs)
def _create_alternative_dummy_data(**kwargs): return Dummy.alternative_heartbeat_data(**kwargs)
def _create_dummy_data(**kwargs): return Dummy.heartbeat_data(**kwargs)
def test_create_invalid_board_date(self): """Test registration with invalid board date.""" data = Dummy.device_register_data() data["board_date"] = "not_a_valid_date" response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_create_missing_chipset(self): """Test registration with missing chipset.""" data = Dummy.device_register_data() data.pop("chipset") response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)