blob: 3512a8d3582ae00ebfc59198560b411bf8a1f335 [file] [log] [blame]
Dirk Vogtc9e10ab2016-10-12 13:58:15 +02001from django.contrib.auth.models import User
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +01002from django.urls import reverse
Dirk Vogtf2a33422016-10-11 17:17:26 +02003from rest_framework.test import APITestCase
4from rest_framework.test import APIClient
Dirk Vogt36635692016-10-17 12:19:10 +02005from rest_framework import status
Dirk Vogt36635692016-10-17 12:19:10 +02006import tempfile
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +01007import os
Dirk Vogtf130c752016-08-23 14:45:01 +02008
Borjan Tchakaloffec814a72018-02-28 11:16:53 +04009
10class Dummy(object):
11 DEFAULT_DUMMY_DEVICE_REGISTER_VALUES = {
12 'board_date': '2015-12-15T01:23:45Z',
13 'chipset': 'Qualcomm MSM8974PRO-AA',
14 }
15
16 DEFAULT_DUMMY_HEARTBEAT_VALUES = {
17 'uuid': None,
18 'app_version': 10100,
19 'uptime': (
20 'up time: 16 days, 21:49:56, idle time: 5 days, 20:55:04, '
21 'sleep time: 10 days, 20:46:27'),
22 'build_fingerprint': (
23 'Fairphone/FP2/FP2:6.0.1/FP2-gms-18.03.1/FP2-gms-18.03.1:user/'
24 'release-keys'),
25 'radio_version': '4437.1-FP2-0-08',
26 'date': '2018-03-19T09:58:30.386Z',
27 }
28
29 DEFAULT_DUMMY_CRASHREPORTS_VALUES = DEFAULT_DUMMY_HEARTBEAT_VALUES.copy()
30 DEFAULT_DUMMY_CRASHREPORTS_VALUES.update({
31 'is_fake_report': 0,
32 'boot_reason': 'why?',
33 'power_on_reason': 'it was powered on',
34 'power_off_reason': 'something happened and it went off',
35 })
36
37 @staticmethod
38 def _update_copy(original, update):
39 """Merge fields of update into a copy of original"""
40 data = original.copy()
41 data.update(update)
42 return data
43
44 @staticmethod
45 def device_register_data(**kwargs):
46 """
47 Return the data required to register a device.
48
49 Use the values passed as keyword arguments or default to
50 the ones from `Dummy.DEFAULT_DUMMY_DEVICE_REGISTER_VALUES`.
51 """
52 return Dummy._update_copy(
53 Dummy.DEFAULT_DUMMY_DEVICE_REGISTER_VALUES, kwargs)
54
55 @staticmethod
56 def heartbeat_data(**kwargs):
57 """
58 Return the data required to create a heartbeat.
59
60 Use the values passed as keyword arguments or default to
61 the ones from `Dummy.DEFAULT_DUMMY_HEARTBEAT_VALUES`.
62 """
63 return Dummy._update_copy(Dummy.DEFAULT_DUMMY_HEARTBEAT_VALUES, kwargs)
64
65 @staticmethod
66 def crashreport_data(**kwargs):
67 """
68 Return the data required to create a crashreport.
69
70 Use the values passed as keyword arguments or default to
71 the ones from `Dummy.DEFAULT_DUMMY_CRASHREPORTS_VALUES`.
72 """
73 return Dummy._update_copy(
74 Dummy.DEFAULT_DUMMY_CRASHREPORTS_VALUES, kwargs)
Dirk Vogtf2a33422016-10-11 17:17:26 +020075
76
77class DeviceTestCase(APITestCase):
78
79 def setUp(self):
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +010080 self.url = reverse("api_v1_register_device")
Dirk Vogtf2a33422016-10-11 17:17:26 +020081
82 def test(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +040083 request = self.client.post(self.url, Dummy.device_register_data())
Dirk Vogtf2a33422016-10-11 17:17:26 +020084 self.assertTrue("token" in request.data)
85 self.assertTrue("uuid" in request.data)
Dirk Vogt36635692016-10-17 12:19:10 +020086 self.assertEqual(request.status_code, status.HTTP_200_OK)
Dirk Vogtf2a33422016-10-11 17:17:26 +020087
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +010088 def test_create_missing_fields(self):
89 request = self.client.post(self.url)
90 self.assertEqual(request.status_code, status.HTTP_400_BAD_REQUEST)
91
92 def test_create_missing_board_date(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +040093 data = Dummy.device_register_data()
94 data.pop('board_date')
95 request = self.client.post(self.url, data)
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +010096 self.assertEqual(request.status_code, status.HTTP_400_BAD_REQUEST)
97
98 def test_create_missing_chipset(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +040099 data = Dummy.device_register_data()
100 data.pop('chipset')
101 request = self.client.post(self.url, data)
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +0100102 self.assertEqual(request.status_code, status.HTTP_400_BAD_REQUEST)
103
104 def test_create_invalid_board_date(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400105 data = Dummy.device_register_data()
106 data['board_date'] = 'not_a_valid_date'
107 request = self.client.post(self.url, data)
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +0100108 self.assertEqual(request.status_code, status.HTTP_400_BAD_REQUEST)
109
Borjan Tchakaloff866f75e2018-03-01 12:04:00 +0400110 def test_create_non_existent_time_board_date(self):
111 """
112 Test the resolution of a naive date-time in which the Europe/Amsterdam daylight saving
113 time transition moved the time "forward".
114 """
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400115 data = Dummy.device_register_data()
Borjan Tchakaloff866f75e2018-03-01 12:04:00 +0400116 # In 2017, the Netherlands changed from CET to CEST on March, 26 at 02:00
117 data['board_date'] = '2017-03-26 02:34:56'
118 request = self.client.post(self.url, data)
119 self.assertEqual(request.status_code, status.HTTP_200_OK)
120
121 def test_create_ambiguous_time_board_date(self):
122 """
123 Test the resolution of a naive date-time in which the Europe/Amsterdam daylight saving
124 time transition moved the time "backward".
125 """
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400126 data = Dummy.device_register_data()
Borjan Tchakaloff866f75e2018-03-01 12:04:00 +0400127 # In 2017, the Netherlands changed from CEST to CET on October, 29 at 03:00
128 data['board_date'] = '2017-10-29 02:34:56'
129 request = self.client.post(self.url, data)
130 self.assertEqual(request.status_code, status.HTTP_200_OK)
131
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +0100132
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400133class DeviceRegisterAPITestCase(APITestCase):
134 """Base class that offers device registration as well as base users
Dirk Vogtf2a33422016-10-11 17:17:26 +0200135
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400136 Attributes:
137 number_of_devices_created (int): The number of devices created in the
138 database.
139 """
Dirk Vogtf2a33422016-10-11 17:17:26 +0200140
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100141 REGISTER_DEVICE_URL = "api_v1_register_device"
142
Dirk Vogtf2a33422016-10-11 17:17:26 +0200143 def setUp(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400144 self.number_of_devices_created = 0
145
146 _, response_data = self._register_device()
147 self.uuid = response_data['uuid']
148 self.token = response_data['token']
149 self.user = APIClient()
150 self.user.credentials(HTTP_AUTHORIZATION='Token ' + self.token)
151
152 _, response_data = self._register_device()
153 self.other_uuid = response_data['uuid']
154 self.other_token = response_data['token']
155 self.other_user = APIClient()
156 self.other_user.credentials(
157 HTTP_AUTHORIZATION='Token ' + self.other_token)
158
159 self.noauth_client = APIClient()
160
161 self.admin_user = User.objects.create_superuser(
162 'somebody', 'somebody@example.com', 'thepassword')
163 self.admin = APIClient()
164 self.admin.force_authenticate(self.admin_user)
165
166 def _register_device(self, **kwargs):
167 """Register a new device
168
169 Arguments:
170 **kwargs: The data to pass the dummy data creation
171 method `Dummy.device_register_data`.
172 Returns:
173 (dict(str, str), dict(str, str)): The tuple composed of the device
174 data that was used for the registration and the data returned by
175 the server in return.
176 """
177 data = Dummy.device_register_data(**kwargs)
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100178 response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data)
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400179 self.assertEqual(response.status_code, status.HTTP_200_OK)
180 self.number_of_devices_created += 1
181
182 return (data, response.data)
183
184
185class ListDevicesTestCase(DeviceRegisterAPITestCase):
Dirk Vogtf2a33422016-10-11 17:17:26 +0200186
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100187 LIST_CREATE_URL = "api_v1_list_devices"
188 RETRIEVE_URL = "api_v1_retrieve_device"
189
Dirk Vogtf2a33422016-10-11 17:17:26 +0200190 def test_device_list(self):
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100191 request = self.admin.get(reverse(self.LIST_CREATE_URL), {})
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400192 self.assertIsNot(request.data['results'][1]['uuid'], '')
193 self.assertEqual(
194 len(request.data['results']), self.number_of_devices_created)
Dirk Vogt36635692016-10-17 12:19:10 +0200195 self.assertEqual(request.status_code, status.HTTP_200_OK)
Dirk Vogtf2a33422016-10-11 17:17:26 +0200196
197 def test_device_list_unauth(self):
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100198 request = self.client.get(reverse(self.LIST_CREATE_URL), {})
Dirk Vogt36635692016-10-17 12:19:10 +0200199 self.assertEqual(request.status_code, status.HTTP_401_UNAUTHORIZED)
Dirk Vogtf2a33422016-10-11 17:17:26 +0200200
201 def test_retrieve_device_auth(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400202 request = self.admin.get(
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100203 reverse(self.RETRIEVE_URL, args=[self.uuid]), {})
Dirk Vogt36635692016-10-17 12:19:10 +0200204 self.assertEqual(request.status_code, status.HTTP_200_OK)
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400205 self.assertEqual(request.data['uuid'], str(self.uuid))
206 self.assertEqual(request.data['token'], self.token)
Dirk Vogtf2a33422016-10-11 17:17:26 +0200207
208 def test_retrieve_device_unauth(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400209 request = self.client.get(
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100210 reverse(self.RETRIEVE_URL, args=[self.uuid]), {})
Dirk Vogt36635692016-10-17 12:19:10 +0200211 self.assertEqual(request.status_code, status.HTTP_401_UNAUTHORIZED)
Dirk Vogtf2a33422016-10-11 17:17:26 +0200212
213 def test_delete_device_auth(self):
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100214 url = reverse(self.RETRIEVE_URL, args=[self.other_uuid])
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400215 request = self.admin.delete(url, {})
Dirk Vogt36635692016-10-17 12:19:10 +0200216 self.assertEqual(request.status_code, status.HTTP_204_NO_CONTENT)
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400217 request = self.admin.delete(url, {})
Dirk Vogt36635692016-10-17 12:19:10 +0200218 self.assertEqual(request.status_code, status.HTTP_404_NOT_FOUND)
Dirk Vogtf2a33422016-10-11 17:17:26 +0200219
Dirk Vogtf2a33422016-10-11 17:17:26 +0200220
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400221class HeartbeatListTestCase(DeviceRegisterAPITestCase):
222
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100223 LIST_CREATE_URL = "api_v1_heartbeats"
224 RETRIEVE_URL = "api_v1_heartbeat"
225 LIST_CREATE_BY_UUID_URL = "api_v1_heartbeats_by_uuid"
226 RETRIEVE_BY_UUID_URL = "api_v1_heartbeat_by_uuid"
227
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400228 @staticmethod
229 def _create_dummy_data(**kwargs):
230 return Dummy.heartbeat_data(**kwargs)
231
232 def _post_multiple(self, client, data, count):
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100233 return [
234 client.post(reverse(self.LIST_CREATE_URL), data)
235 for _ in range(count)]
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400236
237 def _retrieve_single(self, user):
238 count = 5
Borjan Tchakaloff3340e482018-03-19 15:16:25 +0400239 requests = self._post_multiple(self.admin, self.data, count)
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400240 self.assertEqual(len(requests), count)
241 self.assertEqual(requests[0].status_code, status.HTTP_201_CREATED)
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100242 url = reverse(self.RETRIEVE_URL, args=[requests[0].data['id']])
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400243 request = user.get(url)
244 return request.status_code
245
246 def _retrieve_single_by_device(self, user):
247 count = 5
248 requests = self._post_multiple(self.user, self.data, count)
249 self.assertEqual(len(requests), count)
250 self.assertEqual(requests[0].status_code, status.HTTP_201_CREATED)
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100251 url = reverse(self.RETRIEVE_BY_UUID_URL, args=[
252 self.uuid, requests[0].data['device_local_id']])
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400253 request = user.get(url)
254 return request.status_code
Dirk Vogtf2a33422016-10-11 17:17:26 +0200255
256 def setUp(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400257 super(HeartbeatListTestCase, self).setUp()
258 self.data = self._create_dummy_data(uuid=self.uuid)
Dirk Vogt67eb1482016-10-13 12:42:56 +0200259
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200260 def test_create_no_auth(self):
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100261 request = self.noauth_client.post(
262 reverse(self.LIST_CREATE_URL), self.data)
Dirk Vogt36635692016-10-17 12:19:10 +0200263 self.assertEqual(request.status_code, status.HTTP_401_UNAUTHORIZED)
Dirk Vogtf2a33422016-10-11 17:17:26 +0200264
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200265 def test_create_as_admin(self):
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100266 request = self.admin.post(reverse(self.LIST_CREATE_URL), self.data)
Dirk Vogt36635692016-10-17 12:19:10 +0200267 self.assertEqual(request.status_code, status.HTTP_201_CREATED)
Dirk Vogt67eb1482016-10-13 12:42:56 +0200268 self.assertTrue(request.data['id'] > 0)
Dirk Vogtf2a33422016-10-11 17:17:26 +0200269
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200270 def test_create_as_admin_not_existing_device(self):
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100271 request = self.admin.post(
272 reverse(self.LIST_CREATE_URL), self._create_dummy_data())
Dirk Vogt36635692016-10-17 12:19:10 +0200273 self.assertEqual(request.status_code, status.HTTP_404_NOT_FOUND)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200274
275 def test_create_as_uuid_owner(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400276 request = self.user.post(
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100277 reverse(self.LIST_CREATE_URL),
278 self._create_dummy_data(uuid=self.uuid))
Dirk Vogt36635692016-10-17 12:19:10 +0200279 self.assertEqual(request.status_code, status.HTTP_201_CREATED)
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400280 self.assertEqual(request.data['id'], -1)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200281
282 def test_create_as_uuid_not_owner(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400283 request = self.user.post(
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100284 reverse(self.LIST_CREATE_URL),
285 self._create_dummy_data(uuid=self.other_uuid))
Dirk Vogt36635692016-10-17 12:19:10 +0200286 self.assertEqual(request.status_code, status.HTTP_403_FORBIDDEN)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200287
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200288 def test_list(self):
289 count = 5
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400290 self._post_multiple(self.user, self.data, count)
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100291 request = self.admin.get(reverse(self.LIST_CREATE_URL))
Dirk Vogt36635692016-10-17 12:19:10 +0200292 self.assertEqual(request.status_code, status.HTTP_200_OK)
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400293 self.assertEqual(len(request.data['results']), count)
Franz-Xaver Geigerd612fd22018-02-28 10:33:08 +0100294
295 def test_retrieve_single_admin(self):
296 self.assertEqual(
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400297 self._retrieve_single(self.admin), status.HTTP_200_OK)
Dirk Vogte1784882016-10-13 16:09:38 +0200298
299 def test_retrieve_single_device_owner(self):
Franz-Xaver Geigerd612fd22018-02-28 10:33:08 +0100300 self.assertEqual(
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400301 self._retrieve_single(self.user), status.HTTP_403_FORBIDDEN)
302
303 def test_retrieve_single_noauth(self):
304 self.assertEqual(
305 self._retrieve_single(self.noauth_client),
Franz-Xaver Geigerd612fd22018-02-28 10:33:08 +0100306 status.HTTP_401_UNAUTHORIZED)
Dirk Vogte1784882016-10-13 16:09:38 +0200307
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400308 def test_retrieve_single_by_device_admin(self):
Franz-Xaver Geigerd612fd22018-02-28 10:33:08 +0100309 self.assertEqual(
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400310 self._retrieve_single_by_device(self.admin), status.HTTP_200_OK)
Dirk Vogt0d9d5d22016-10-13 16:17:57 +0200311
312 def test_retrieve_single_by_device_device_owner(self):
Franz-Xaver Geigerd612fd22018-02-28 10:33:08 +0100313 self.assertEqual(
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400314 self._retrieve_single_by_device(self.user),
315 status.HTTP_403_FORBIDDEN)
316
317 def test_retrieve_single_by_device_noauth(self):
318 self.assertEqual(
319 self._retrieve_single_by_device(self.noauth_client),
Franz-Xaver Geigerd612fd22018-02-28 10:33:08 +0100320 status.HTTP_401_UNAUTHORIZED)
Dirk Vogt0d9d5d22016-10-13 16:17:57 +0200321
Dirk Vogte1784882016-10-13 16:09:38 +0200322 def test_list_by_uuid(self):
323 count = 5
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400324 self._post_multiple(self.user, self.data, count)
325 self._post_multiple(
326 self.admin, self._create_dummy_data(uuid=self.other_uuid), count)
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100327 url = reverse(self.LIST_CREATE_BY_UUID_URL, args=[self.uuid])
Dirk Vogte1784882016-10-13 16:09:38 +0200328 request = self.admin.get(url)
Dirk Vogt36635692016-10-17 12:19:10 +0200329 self.assertEqual(request.status_code, status.HTTP_200_OK)
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400330 self.assertEqual(len(request.data['results']), count)
Dirk Vogte1784882016-10-13 16:09:38 +0200331
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200332 def test_list_noauth(self):
333 count = 5
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400334 self._post_multiple(self.user, self.data, count)
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100335 request = self.noauth_client.get(reverse(self.LIST_CREATE_URL))
Dirk Vogt36635692016-10-17 12:19:10 +0200336 self.assertEqual(request.status_code, status.HTTP_401_UNAUTHORIZED)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200337
338 def test_list_device_owner(self):
339 count = 5
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400340 self._post_multiple(self.user, self.data, count)
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100341 request = self.user.get(reverse(self.LIST_CREATE_URL))
Dirk Vogt36635692016-10-17 12:19:10 +0200342 self.assertEqual(request.status_code, status.HTTP_403_FORBIDDEN)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200343
Borjan Tchakaloff869cf922018-02-19 11:01:16 +0100344 def test_no_radio_version(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400345 data = self._create_dummy_data(uuid=self.uuid)
Borjan Tchakaloff869cf922018-02-19 11:01:16 +0100346 data.pop('radio_version')
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100347 request = self.user.post(reverse(self.LIST_CREATE_URL), data)
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400348 self.assertEqual(request.status_code, status.HTTP_201_CREATED)
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100349 url = reverse(self.LIST_CREATE_BY_UUID_URL, args=[self.uuid])
Borjan Tchakaloff869cf922018-02-19 11:01:16 +0100350 request = self.admin.get(url)
351 self.assertEqual(request.status_code, status.HTTP_200_OK)
352 self.assertEqual(len(request.data['results']), 1)
353 self.assertIsNone(request.data['results'][0]['radio_version'])
354
355 def test_radio_version_field(self):
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100356 request = self.user.post(reverse(self.LIST_CREATE_URL), self.data)
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400357 self.assertEqual(request.status_code, status.HTTP_201_CREATED)
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100358 url = reverse(self.LIST_CREATE_BY_UUID_URL, args=[self.uuid])
Borjan Tchakaloff869cf922018-02-19 11:01:16 +0100359 request = self.admin.get(url)
360 self.assertEqual(request.status_code, status.HTTP_200_OK)
361 self.assertEqual(len(request.data['results']), 1)
362 self.assertEqual(request.data['results'][0]['radio_version'],
363 self.data['radio_version'])
364
Borjan Tchakaloff866f75e2018-03-01 12:04:00 +0400365 def test_send_non_existent_time(self):
366 """
367 Test the resolution of a naive date-time in which the Europe/Amsterdam daylight saving
368 time transition moved the time "forward".
369 """
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400370 data = self._create_dummy_data(uuid=self.uuid)
Borjan Tchakaloff866f75e2018-03-01 12:04:00 +0400371 # In 2017, the Netherlands changed from CET to CEST on March, 26 at 02:00
372 data['date'] = '2017-03-26 02:34:56'
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100373 request = self.user.post(reverse(self.LIST_CREATE_URL), data)
Borjan Tchakaloff866f75e2018-03-01 12:04:00 +0400374 self.assertEqual(request.status_code, status.HTTP_201_CREATED)
375
376 def test_send_ambiguous_time(self):
377 """
378 Test the resolution of a naive date-time in which the Europe/Amsterdam daylight saving
379 time transition moved the time "backward".
380 """
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400381 data = self._create_dummy_data(uuid=self.uuid)
Borjan Tchakaloff866f75e2018-03-01 12:04:00 +0400382 # In 2017, the Netherlands changed from CEST to CET on October, 29 at 03:00
383 data['date'] = '2017-10-29 02:34:56'
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100384 request = self.user.post(reverse(self.LIST_CREATE_URL), data)
Borjan Tchakaloff866f75e2018-03-01 12:04:00 +0400385 self.assertEqual(request.status_code, status.HTTP_201_CREATED)
386
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200387
388class CrashreportListTestCase(HeartbeatListTestCase):
389
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100390 LIST_CREATE_URL = "api_v1_crashreports"
391 RETRIEVE_URL = "api_v1_crashreport"
392 LIST_CREATE_BY_UUID_URL = "api_v1_crashreports_by_uuid"
393 RETRIEVE_BY_UUID_URL = "api_v1_crashreport_by_uuid"
Dirk Vogt67eb1482016-10-13 12:42:56 +0200394
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400395 @staticmethod
396 def _create_dummy_data(**kwargs):
397 return Dummy.crashreport_data(**kwargs)
Dirk Vogt67eb1482016-10-13 12:42:56 +0200398
399
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400400class LogfileUploadTest(DeviceRegisterAPITestCase):
401
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100402 LIST_CREATE_URL = "api_v1_crashreports"
403 PUT_LOGFILE_URL = "api_v1_putlogfile_for_device_id"
404
Dirk Vogt67eb1482016-10-13 12:42:56 +0200405 def setUp(self):
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400406 super(LogfileUploadTest, self).setUp()
Dirk Vogt67eb1482016-10-13 12:42:56 +0200407
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100408 url = reverse(self.LIST_CREATE_URL)
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400409 for uuid in [self.uuid, self.other_uuid]:
410 data = Dummy.crashreport_data(uuid=uuid)
411 for _ in range(2):
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100412 self.user.post(url, data)
Dirk Vogt36635692016-10-17 12:19:10 +0200413
Dirk Vogt67eb1482016-10-13 12:42:56 +0200414 def test_Logfile_upload_as_admin(self):
Dirk Vogt36635692016-10-17 12:19:10 +0200415 f = tempfile.NamedTemporaryFile('w+', suffix=".log", delete=True)
416 f.write(u"blihblahblub")
Borjan Tchakaloffec814a72018-02-28 11:16:53 +0400417 request = self.admin.post(
Franz-Xaver Geiger67504d02018-03-19 15:04:48 +0100418 reverse(self.PUT_LOGFILE_URL, args=[
419 self.uuid, 1, os.path.basename(f.name)
420 ]),
Dirk Vogt36635692016-10-17 12:19:10 +0200421 {'file': f}, format="multipart")
422 self.assertEqual(status.HTTP_201_CREATED, request.status_code)