Add test cases for local ID assignment race conditions
Issue: HIC-251
Change-Id: I9616b786a44bba2621a8a800035ff1189d3d9b19
diff --git a/crashreports/tests/utils.py b/crashreports/tests/utils.py
index 73a479b..e9139df 100644
--- a/crashreports/tests/utils.py
+++ b/crashreports/tests/utils.py
@@ -2,6 +2,7 @@
import os
import shutil
+import threading
import zipfile
from datetime import date, datetime
from typing import Optional
@@ -9,9 +10,10 @@
import pytz
from django.conf import settings
from django.contrib.auth.models import User, Group
+from django.test import TransactionTestCase
from django.urls import reverse
from rest_framework import status
-from rest_framework.test import APITestCase, APIClient
+from rest_framework.test import APIClient, APITestCase
from crashreports.models import (
Crashreport,
@@ -370,7 +372,7 @@
return archive.read(logfile_name)
-class HiccupCrashreportsAPITestCase(APITestCase):
+class HiccupCrashreportsTransactionTestCase(TransactionTestCase):
"""Base class that offers a device registration method."""
REGISTER_DEVICE_URL = "api_v1_register_device"
@@ -410,3 +412,40 @@
user.credentials(HTTP_AUTHORIZATION="Token " + token)
return uuid, user, token
+
+
+class HiccupCrashreportsAPITestCase(
+ HiccupCrashreportsTransactionTestCase, APITestCase
+):
+ """Base class combining device registration methods and API test methods."""
+
+ pass
+
+
+class RaceConditionsTestCase(HiccupCrashreportsTransactionTestCase):
+ """Test cases for race conditions."""
+
+ # Make data from migrations available in the test cases
+ serialized_rollback = True
+
+ def _test_create_multiple(
+ self, report_type, create_function, argslist, local_id_name
+ ):
+ """Test that no race condition occurs when creating instances."""
+ # Create multiple threads which send reports simultaneously
+ threads = []
+ for args in argslist:
+ thread = threading.Thread(target=create_function, args=args)
+ threads.append(thread)
+ thread.start()
+
+ # Wait until the threads have finished
+ for thread in threads:
+ thread.join()
+
+ # Assert that no duplicate local IDs have been assigned
+ reports = report_type.objects.all()
+ self.assertEqual(
+ reports.count(), reports.distinct(local_id_name).count()
+ )
+ self.assertEqual(reports.count(), len(argslist))