blob: 09eb7afe5385519f7b8cec08816766cb36588cf9 [file] [log] [blame]
Mitja Nikolaus03e412b2018-09-18 17:50:15 +02001"""Tests for the logfiles REST API."""
2
3import os
Mitja Nikolausc2da2852018-10-04 15:09:11 +02004import zipfile
Mitja Nikolaus03e412b2018-09-18 17:50:15 +02005
6from django.urls import reverse
7
8from rest_framework import status
9
Mitja Nikolausc2da2852018-10-04 15:09:11 +020010from crashreports.models import crashreport_file_name, Device
Mitja Nikolaus03e412b2018-09-18 17:50:15 +020011from crashreports.tests.utils import HiccupCrashreportsAPITestCase, Dummy
12
13
14class LogfileUploadTest(HiccupCrashreportsAPITestCase):
15 """Test cases for upload of log files."""
16
17 LIST_CREATE_URL = "api_v1_crashreports"
18 PUT_LOGFILE_URL = "api_v1_putlogfile_for_device_id"
19
Mitja Nikolaus188bca62018-10-04 15:17:48 +020020 def setUp(self):
21 """Call the super setup method and register a device."""
22 super().setUp()
23 self.device_uuid, self.user, _ = self._register_device()
24
Mitja Nikolaus03e412b2018-09-18 17:50:15 +020025 def _upload_crashreport(self, user, uuid):
26 """
27 Upload dummy crashreport data.
28
29 Args:
30 user: The user which should be used for uploading the report
31 uuid: The uuid of the device to which the report should be uploaded
32
33 Returns: The local id of the device for which the report was uploaded.
34
35 """
36 data = Dummy.crashreport_data(uuid=uuid)
37 response = user.post(reverse(self.LIST_CREATE_URL), data)
38 self.assertEqual(status.HTTP_201_CREATED, response.status_code)
39 self.assertTrue("device_local_id" in response.data)
40 device_local_id = response.data["device_local_id"]
41
42 return device_local_id
43
Mitja Nikolausc2da2852018-10-04 15:09:11 +020044 def _assert_zip_file_contents_equal(self, file1, file2):
45 """Assert that the files within two zip files are equal."""
46 zip_file_1 = zipfile.ZipFile(file1)
47 zip_file_2 = zipfile.ZipFile(file2)
48 for file_name_1, file_name_2 in zip(
49 zip_file_1.filelist, zip_file_2.filelist
50 ):
51 file_1 = zip_file_1.open(file_name_1)
52 file_2 = zip_file_2.open(file_name_2)
53
54 self.assertEqual(file_1.read(), file_2.read())
55
Mitja Nikolaus03e412b2018-09-18 17:50:15 +020056 def _test_logfile_upload(self, user, uuid):
57 # Upload crashreport
58 device_local_id = self._upload_crashreport(user, uuid)
59
60 # Upload a logfile for the crashreport
Mitja Nikolaus6e118472018-10-04 11:15:29 +020061 logfile = open(Dummy.DEFAULT_DUMMY_LOG_FILE_PATH, "rb")
62
Mitja Nikolausc2da2852018-10-04 15:09:11 +020063 logfile_name = os.path.basename(logfile.name)
Mitja Nikolaus03e412b2018-09-18 17:50:15 +020064 response = user.post(
65 reverse(
Mitja Nikolausc2da2852018-10-04 15:09:11 +020066 self.PUT_LOGFILE_URL, args=[uuid, device_local_id, logfile_name]
Mitja Nikolaus03e412b2018-09-18 17:50:15 +020067 ),
68 {"file": logfile},
69 format="multipart",
70 )
Mitja Nikolaus6e118472018-10-04 11:15:29 +020071 logfile.close()
Mitja Nikolaus03e412b2018-09-18 17:50:15 +020072 self.assertEqual(status.HTTP_201_CREATED, response.status_code)
73
Mitja Nikolausc2da2852018-10-04 15:09:11 +020074 logfile_instance = (
75 Device.objects.get(uuid=uuid)
76 .crashreports.get(device_local_id=device_local_id)
77 .logfiles.last()
78 )
79 uploaded_logfile_path = crashreport_file_name(
80 logfile_instance, logfile_name
81 )
82
83 self.assertTrue(os.path.isfile(uploaded_logfile_path))
84 # The files are not 100% equal, because the server adds some extra
85 # bytes. However, we mainly care that the contents are equal:
86 self._assert_zip_file_contents_equal(
87 uploaded_logfile_path, Dummy.DEFAULT_DUMMY_LOG_FILE_PATH
88 )
89
Mitja Nikolaus03e412b2018-09-18 17:50:15 +020090 def test_logfile_upload_as_user(self):
91 """Test upload of logfiles as device owner."""
Mitja Nikolaus188bca62018-10-04 15:17:48 +020092 self._test_logfile_upload(self.user, self.device_uuid)
Mitja Nikolaus03e412b2018-09-18 17:50:15 +020093
94 def test_logfile_upload_as_admin(self):
95 """Test upload of logfiles as admin user."""
Mitja Nikolaus188bca62018-10-04 15:17:48 +020096 self._test_logfile_upload(self.admin, self.device_uuid)
97
98 def tearDown(self):
99 """Remove the file and directories that were created for the test."""
100 device = Device.objects.get(uuid=self.device_uuid)
101 for crashreport_instance in device.crashreports.all():
102 for logfile_instance in crashreport_instance.logfiles.all():
103 uploaded_logfile_path = crashreport_file_name(
104 logfile_instance,
105 os.path.basename(Dummy.DEFAULT_DUMMY_LOG_FILE_PATH),
106 )
107 try:
108 os.remove(uploaded_logfile_path)
109 os.removedirs(os.path.dirname(uploaded_logfile_path))
110 except (FileNotFoundError, OSError):
111 pass