Merge common code of dummy testing classes
Move all shared functionality to crashreports/tests/utils.py and make
the dummy in crashreport_stats/tests/test_rest_endpoints.py inherit from
the crashreports dummy class to prevent code duplication.
Issue: HIC-269
Change-Id: I69ce569c13169ded5857638c466bea8a650f38fd
diff --git a/crashreport_stats/tests/test_rest_endpoints.py b/crashreport_stats/tests/test_rest_endpoints.py
index b24d71e..a3bd2d1 100644
--- a/crashreport_stats/tests/test_rest_endpoints.py
+++ b/crashreport_stats/tests/test_rest_endpoints.py
@@ -15,7 +15,6 @@
from crashreport_stats.tests.utils import Dummy, HiccupStatsAPITestCase
from crashreports.models import Crashreport, HeartBeat, LogFile
-from crashreports.tests.utils import DEFAULT_DUMMY_LOG_FILE_DIRECTORY
# pylint: disable=too-many-public-methods
@@ -344,7 +343,7 @@
return Dummy.create_dummy_daily_radio_version(version, **kwargs)
-@override_settings(MEDIA_ROOT=DEFAULT_DUMMY_LOG_FILE_DIRECTORY)
+@override_settings(MEDIA_ROOT=Dummy.DEFAULT_DUMMY_LOG_FILE_DIRECTORY)
class DeviceStatsTestCase(HiccupStatsAPITestCase):
"""Test the single device stats REST endpoints."""
diff --git a/crashreport_stats/tests/utils.py b/crashreport_stats/tests/utils.py
index 8db1d0f..491839b 100644
--- a/crashreport_stats/tests/utils.py
+++ b/crashreport_stats/tests/utils.py
@@ -1,7 +1,6 @@
"""Utility functions shared by all crashreport stats tests."""
-from datetime import datetime, date
-import zipfile
+from datetime import datetime
import pytz
from django.contrib.auth.models import Group
@@ -17,208 +16,38 @@
StatsMetadata,
)
-from crashreports.models import Crashreport, Device, HeartBeat, LogFile, User
+from crashreports.models import User
+from crashreports.tests.utils import Dummy as CrashreportsDummy
from hiccup.allauth_adapters import FP_STAFF_GROUP_NAME
-class Dummy:
+class Dummy(CrashreportsDummy):
"""Class for creating dummy instances for testing."""
- # Valid unique entries
- BUILD_FINGERPRINTS = [
- (
- "Fairphone/FP2/FP2:5.1/FP2/r4275.1_FP2_gms76_1.13.0"
- ":user/release-keys"
- ),
- (
- "Fairphone/FP2/FP2:5.1.1/FP2-gms75.1.13.0/FP2-gms75.1.13.0"
- ":user/release-keys"
- ),
- (
- "Fairphone/FP2/FP2:6.0.1/FP2-gms-18.04.1/FP2-gms-18.04.1"
- ":user/release-keys"
- ),
- ("Fairphone/FP2/FP2:7.1.2/18.07.2/gms-7480c31d:user/release-keys"),
- ]
- RADIO_VERSIONS = [
- "4437.1-FP2-0-07",
- "4437.1-FP2-0-08",
- "4437.1-FP2-0-09",
- "4437.1-FP2-0-10",
- ]
- UUIDs = ["e1c0cc95-ab8d-461a-a768-cb8d9d7fdb04"]
-
- USERNAMES = ["testuser1", "testuser2", "testuser3"]
-
- DATES = [date(2018, 3, 19), date(2018, 3, 26), date(2018, 5, 1)]
-
DEFAULT_DUMMY_VERSION_VALUES = {
- "build_fingerprint": BUILD_FINGERPRINTS[0],
- "first_seen_on": DATES[1],
- "released_on": DATES[0],
+ "build_fingerprint": CrashreportsDummy.BUILD_FINGERPRINTS[0],
+ "first_seen_on": CrashreportsDummy.DATES[1],
+ "released_on": CrashreportsDummy.DATES[0],
"is_beta_release": False,
"is_official_release": True,
}
- DEFAULT_DUMMY_VERSION_DAILY_VALUES = {"date": DATES[1]}
+ DEFAULT_DUMMY_VERSION_DAILY_VALUES = {"date": CrashreportsDummy.DATES[1]}
DEFAULT_DUMMY_RADIO_VERSION_VALUES = {
- "radio_version": RADIO_VERSIONS[0],
- "first_seen_on": DATES[1],
- "released_on": DATES[0],
+ "radio_version": CrashreportsDummy.RADIO_VERSIONS[0],
+ "first_seen_on": CrashreportsDummy.DATES[1],
+ "released_on": CrashreportsDummy.DATES[0],
}
- DEFAULT_DUMMY_RADIO_VERSION_DAILY_VALUES = {"date": DATES[1]}
+ DEFAULT_DUMMY_RADIO_VERSION_DAILY_VALUES = {
+ "date": CrashreportsDummy.DATES[1]
+ }
DEFAULT_DUMMY_STATSMETADATA_VALUES = {
"updated_at": datetime(2018, 6, 15, 2, 12, 24, tzinfo=pytz.utc)
}
- DEFAULT_DUMMY_DEVICE_VALUES = {
- "board_date": datetime(2015, 12, 15, 1, 23, 45, tzinfo=pytz.utc),
- "chipset": "Qualcomm MSM8974PRO-AA",
- "token": "64111c62d521fb4724454ca6dea27e18f93ef56e",
- }
-
- DEFAULT_DUMMY_USER_VALUES = {"username": USERNAMES[0]}
-
- DEFAULT_DUMMY_HEARTBEAT_VALUES = {
- "app_version": 10100,
- "uptime": (
- "up time: 16 days, 21:49:56, idle time: 5 days, 20:55:04, "
- "sleep time: 10 days, 20:46:27"
- ),
- "build_fingerprint": BUILD_FINGERPRINTS[0],
- "radio_version": RADIO_VERSIONS[0],
- "date": datetime(2018, 3, 19, 12, 0, 0, tzinfo=pytz.utc),
- }
-
- DEFAULT_DUMMY_CRASHREPORT_VALUES = DEFAULT_DUMMY_HEARTBEAT_VALUES.copy()
- DEFAULT_DUMMY_CRASHREPORT_VALUES.update(
- {
- "is_fake_report": 0,
- "boot_reason": Crashreport.BOOT_REASON_UNKOWN,
- "power_on_reason": "it was powered on",
- "power_off_reason": "something happened and it went off",
- }
- )
-
- DEFAULT_DUMMY_LOG_FILE_VALUES = {
- "logfile_type": "last_kmsg",
- "logfile": "test_logfile.zip",
- }
-
- DEFAULT_DUMMY_LOG_FILE_NAME = "dmesg.log"
-
- @staticmethod
- def update_copy(original, update):
- """Merge fields of update into a copy of original."""
- data = original.copy()
- data.update(update)
- return data
-
- @staticmethod
- def create_dummy_user(**kwargs):
- """Create a dummy user instance.
-
- The dummy instance is created and saved to the database.
- Args:
- **kwargs:
- Optional arguments to extend/overwrite the default values.
-
- Returns: The created user instance.
-
- """
- entity = User(
- **Dummy.update_copy(Dummy.DEFAULT_DUMMY_USER_VALUES, kwargs)
- )
- entity.save()
- return entity
-
- @staticmethod
- def create_dummy_device(user, **kwargs):
- """Create a dummy device instance.
-
- The dummy instance is created and saved to the database.
- Args:
- user: The user instance that the device should relate to
- **kwargs:
- Optional arguments to extend/overwrite the default values.
-
- Returns: The created device instance.
-
- """
- entity = Device(
- user=user,
- **Dummy.update_copy(Dummy.DEFAULT_DUMMY_DEVICE_VALUES, kwargs)
- )
- entity.save()
- return entity
-
- @staticmethod
- def create_dummy_report(report_type, device, **kwargs):
- """Create a dummy report instance of the given report class type.
-
- The dummy instance is created and saved to the database.
- Args:
- report_type: The class of the report type to be created.
- user: The device instance that the heartbeat should relate to
- **kwargs:
- Optional arguments to extend/overwrite the default values.
-
- Returns: The created report instance.
-
- """
- if report_type == HeartBeat:
- entity = HeartBeat(
- device=device,
- **Dummy.update_copy(
- Dummy.DEFAULT_DUMMY_HEARTBEAT_VALUES, kwargs
- )
- )
- elif report_type == Crashreport:
- entity = Crashreport(
- device=device,
- **Dummy.update_copy(
- Dummy.DEFAULT_DUMMY_CRASHREPORT_VALUES, kwargs
- )
- )
- else:
- raise RuntimeError(
- "No dummy report instance can be created for {}".format(
- report_type.__name__
- )
- )
- entity.save()
- return entity
-
- @staticmethod
- def create_dummy_log_file(crashreport, **kwargs):
- """Create a dummy log file instance.
-
- The dummy instance is created and saved to the database.
-
- Args:
- crashreport: The crashreport that the log file belongs to.
- **kwargs: Optional arguments to extend/overwrite the default values.
-
- Returns: The created log file instance.
-
- """
- entity = LogFile(
- crashreport=crashreport,
- **Dummy.update_copy(Dummy.DEFAULT_DUMMY_LOG_FILE_VALUES, kwargs)
- )
-
- entity.save()
- return entity
-
- @staticmethod
- def read_logfile_contents(path_to_zipfile, logfile_name):
- """Read bytes of a zipped logfile."""
- archive = zipfile.ZipFile(path_to_zipfile, "r")
- return archive.read(logfile_name)
-
@staticmethod
def create_dummy_version(version_type=Version, **kwargs):
"""Create a dummy version instance.
@@ -237,11 +66,11 @@
"""
if version_type == Version:
entity = Version(
- **Dummy.update_copy(Dummy.DEFAULT_DUMMY_VERSION_VALUES, kwargs)
+ **Dummy._update_copy(Dummy.DEFAULT_DUMMY_VERSION_VALUES, kwargs)
)
elif version_type == RadioVersion:
entity = RadioVersion(
- **Dummy.update_copy(
+ **Dummy._update_copy(
Dummy.DEFAULT_DUMMY_RADIO_VERSION_VALUES, kwargs
)
)
@@ -268,7 +97,7 @@
"""
entity = VersionDaily(
version=version,
- **Dummy.update_copy(
+ **Dummy._update_copy(
Dummy.DEFAULT_DUMMY_VERSION_DAILY_VALUES, kwargs
)
)
@@ -289,7 +118,7 @@
"""
entity = RadioVersionDaily(
version=version,
- **Dummy.update_copy(
+ **Dummy._update_copy(
Dummy.DEFAULT_DUMMY_RADIO_VERSION_DAILY_VALUES, kwargs
)
)
@@ -309,7 +138,7 @@
"""
entity = StatsMetadata(
- **Dummy.update_copy(
+ **Dummy._update_copy(
Dummy.DEFAULT_DUMMY_STATSMETADATA_VALUES, kwargs
)
)
diff --git a/crashreports/tests/test_rest_api_heartbeats.py b/crashreports/tests/test_rest_api_heartbeats.py
index c4e72d3..cd1ccec 100644
--- a/crashreports/tests/test_rest_api_heartbeats.py
+++ b/crashreports/tests/test_rest_api_heartbeats.py
@@ -70,7 +70,8 @@
def test_create_as_fp_staff_not_existing_device(self):
"""Test creation of heartbeat on non-existing device."""
response = self.fp_staff_client.post(
- reverse(self.LIST_CREATE_URL), self._create_dummy_data()
+ reverse(self.LIST_CREATE_URL),
+ self._create_dummy_data(uuid=Dummy.UUIDs[0]),
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
diff --git a/crashreports/tests/utils.py b/crashreports/tests/utils.py
index 1202fce..9ee316a 100644
--- a/crashreports/tests/utils.py
+++ b/crashreports/tests/utils.py
@@ -1,18 +1,19 @@
"""Utility functions shared by all crashreports tests."""
import os
+import zipfile
+from datetime import date, datetime
from typing import Optional
+import pytz
from django.contrib.auth.models import User, Group
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase, APIClient
-from crashreports.models import Crashreport
+from crashreports.models import Crashreport, Device, HeartBeat, LogFile
from hiccup.allauth_adapters import FP_STAFF_GROUP_NAME
-DEFAULT_DUMMY_LOG_FILE_DIRECTORY = os.path.join("resources", "test")
-
class InvalidCrashTypeError(BaseException):
"""Invalid crash type encountered.
@@ -40,42 +41,82 @@
class Dummy:
"""Dummy values for devices, heartbeats and crashreports."""
+ # Valid unique entries
+ BUILD_FINGERPRINTS = [
+ (
+ "Fairphone/FP2/FP2:5.1/FP2/r4275.1_FP2_gms76_1.13.0"
+ ":user/release-keys"
+ ),
+ (
+ "Fairphone/FP2/FP2:5.1.1/FP2-gms75.1.13.0/FP2-gms75.1.13.0"
+ ":user/release-keys"
+ ),
+ (
+ "Fairphone/FP2/FP2:6.0.1/FP2-gms-18.04.1/FP2-gms-18.04.1"
+ ":user/release-keys"
+ ),
+ ("Fairphone/FP2/FP2:7.1.2/18.07.2/gms-7480c31d:user/release-keys"),
+ ]
+ RADIO_VERSIONS = [
+ "4437.1-FP2-0-07",
+ "4437.1-FP2-0-08",
+ "4437.1-FP2-0-09",
+ "4437.1-FP2-0-10",
+ ]
+ UUIDs = ["e1c0cc95-ab8d-461a-a768-cb8d9d7fdb04"]
+
+ USERNAMES = ["testuser1", "testuser2", "testuser3"]
+
+ DATES = [date(2018, 3, 19), date(2018, 3, 26), date(2018, 5, 1)]
+
+ DEFAULT_DUMMY_USER_VALUES = {"username": USERNAMES[0]}
+
DEFAULT_DUMMY_DEVICE_REGISTER_VALUES = {
- "board_date": "2015-12-15T01:23:45Z",
+ "board_date": datetime(2015, 12, 15, 1, 23, 45, tzinfo=pytz.utc),
"chipset": "Qualcomm MSM8974PRO-AA",
}
+ DEFAULT_DUMMY_DEVICE_VALUES = DEFAULT_DUMMY_DEVICE_REGISTER_VALUES.copy()
+ DEFAULT_DUMMY_DEVICE_VALUES.update(
+ {"token": "64111c62d521fb4724454ca6dea27e18f93ef56e"}
+ )
+
DEFAULT_DUMMY_HEARTBEAT_VALUES = {
- "uuid": None,
"app_version": 10100,
"uptime": (
"up time: 16 days, 21:49:56, idle time: 5 days, 20:55:04, "
"sleep time: 10 days, 20:46:27"
),
- "build_fingerprint": (
- "Fairphone/FP2/FP2:6.0.1/FP2-gms-18.03.1/FP2-gms-18.03.1:user/"
- "release-keys"
- ),
- "radio_version": "4437.1-FP2-0-08",
- "date": "2018-03-19T09:58:30.386Z",
+ "build_fingerprint": BUILD_FINGERPRINTS[0],
+ "radio_version": RADIO_VERSIONS[0],
+ "date": datetime(2018, 3, 19, 12, 0, 0, tzinfo=pytz.utc),
}
- DEFAULT_DUMMY_CRASHREPORTS_VALUES = DEFAULT_DUMMY_HEARTBEAT_VALUES.copy()
- DEFAULT_DUMMY_CRASHREPORTS_VALUES.update(
+ DEFAULT_DUMMY_CRASHREPORT_VALUES = DEFAULT_DUMMY_HEARTBEAT_VALUES.copy()
+ DEFAULT_DUMMY_CRASHREPORT_VALUES.update(
{
"is_fake_report": 0,
- "boot_reason": "why?",
+ "boot_reason": Crashreport.BOOT_REASON_UNKOWN,
"power_on_reason": "it was powered on",
"power_off_reason": "something happened and it went off",
}
)
+ DEFAULT_DUMMY_LOG_FILE_VALUES = {
+ "logfile_type": "last_kmsg",
+ "logfile": "test_logfile.zip",
+ }
+
+ DEFAULT_DUMMY_LOG_FILE_NAME = "dmesg.log"
+
CRASH_TYPE_TO_BOOT_REASON_MAP = {
"crash": Crashreport.BOOT_REASON_KEYBOARD_POWER_ON,
"smpl": Crashreport.BOOT_REASON_RTC_ALARM,
"other": "whatever",
}
+ DEFAULT_DUMMY_LOG_FILE_DIRECTORY = os.path.join("resources", "test")
+
DEFAULT_DUMMY_LOG_FILE_PATH = os.path.join(
DEFAULT_DUMMY_LOG_FILE_DIRECTORY, "test_logfile.zip"
)
@@ -121,7 +162,7 @@
keyword arguments already.
"""
data = Dummy._update_copy(
- Dummy.DEFAULT_DUMMY_CRASHREPORTS_VALUES, kwargs
+ Dummy.DEFAULT_DUMMY_CRASHREPORT_VALUES, kwargs
)
if report_type and "boot_reason" not in kwargs:
if report_type not in Dummy.CRASH_TYPE_TO_BOOT_REASON_MAP:
@@ -131,6 +172,111 @@
)
return data
+ @staticmethod
+ def create_dummy_user(**kwargs):
+ """Create a dummy user instance.
+
+ The dummy instance is created and saved to the database.
+ Args:
+ **kwargs:
+ Optional arguments to extend/overwrite the default values.
+
+ Returns: The created user instance.
+
+ """
+ entity = User(
+ **Dummy._update_copy(Dummy.DEFAULT_DUMMY_USER_VALUES, kwargs)
+ )
+ entity.save()
+ return entity
+
+ @staticmethod
+ def create_dummy_device(user, **kwargs):
+ """Create a dummy device instance.
+
+ The dummy instance is created and saved to the database.
+ Args:
+ user: The user instance that the device should relate to
+ **kwargs:
+ Optional arguments to extend/overwrite the default values.
+
+ Returns: The created device instance.
+
+ """
+ entity = Device(
+ user=user,
+ **Dummy._update_copy(Dummy.DEFAULT_DUMMY_DEVICE_VALUES, kwargs)
+ )
+ entity.save()
+ return entity
+
+ @staticmethod
+ def create_dummy_report(report_type, device, **kwargs):
+ """Create a dummy report instance of the given report class type.
+
+ The dummy instance is created and saved to the database.
+ Args:
+ report_type: The class of the report type to be created.
+ user: The device instance that the heartbeat should relate to
+ **kwargs:
+ Optional arguments to extend/overwrite the default values.
+
+ Returns: The created report instance.
+
+ Raises:
+ RuntimeError: If report_type is not a report class type.
+
+ """
+ if report_type == HeartBeat:
+ entity = HeartBeat(
+ device=device,
+ **Dummy._update_copy(
+ Dummy.DEFAULT_DUMMY_HEARTBEAT_VALUES, kwargs
+ )
+ )
+ elif report_type == Crashreport:
+ entity = Crashreport(
+ device=device,
+ **Dummy._update_copy(
+ Dummy.DEFAULT_DUMMY_CRASHREPORT_VALUES, kwargs
+ )
+ )
+ else:
+ raise RuntimeError(
+ "No dummy report instance can be created for {}".format(
+ report_type.__name__
+ )
+ )
+ entity.save()
+ return entity
+
+ @staticmethod
+ def create_dummy_log_file(crashreport, **kwargs):
+ """Create a dummy log file instance.
+
+ The dummy instance is created and saved to the database.
+
+ Args:
+ crashreport: The crashreport that the log file belongs to.
+ **kwargs: Optional arguments to extend/overwrite the default values.
+
+ Returns: The created log file instance.
+
+ """
+ entity = LogFile(
+ crashreport=crashreport,
+ **Dummy._update_copy(Dummy.DEFAULT_DUMMY_LOG_FILE_VALUES, kwargs)
+ )
+
+ entity.save()
+ return entity
+
+ @staticmethod
+ def read_logfile_contents(path_to_zipfile, logfile_name):
+ """Read bytes of a zipped logfile."""
+ archive = zipfile.ZipFile(path_to_zipfile, "r")
+ return archive.read(logfile_name)
+
class HiccupCrashreportsAPITestCase(APITestCase):
"""Base class that offers a device registration method."""