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/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."""