Completed
Push — master ( 9ed73f...7648fa )
by
unknown
01:21
created

LiveStatistics.test_list()   A

Complexity

Conditions 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 6
rs 9.4285
cc 2
1
# coding: utf8
2
3
"""
4
This software is licensed under the Apache 2 license, quoted below.
5
6
Copyright 2014 Crystalnix Limited
7
8
Licensed under the Apache License, Version 2.0 (the "License"); you may not
9
use this file except in compliance with the License. You may obtain a copy of
10
the License at
11
12
    http://www.apache.org/licenses/LICENSE-2.0
13
14
Unless required by applicable law or agreed to in writing, software
15
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17
License for the specific language governing permissions and limitations under
18
the License.
19
"""
20
from __future__ import unicode_literals
21
from builtins import bytes, range
22
23
import base64
24
from datetime import datetime
25
from uuid import UUID
26
27
from django.core.urlresolvers import reverse
28
from django.contrib.auth import get_user_model
29
from django.core.files.uploadedfile import SimpleUploadedFile
30
from django.conf import settings
31
32
from rest_framework import status
33
from rest_framework.test import APITestCase, APIClient
34
from freezegun import freeze_time
35
36
from bitmapist import mark_event
37
from freezegun import freeze_time
38
import pytz
39
40
from omaha_server.utils import is_private
41
from omaha.statistics import userid_counting, get_users_versions, get_channel_statistics
42
from omaha.utils import redis
43
from omaha.serializers import (
44
    AppSerializer,
45
    DataSerializer,
46
    PlatformSerializer,
47
    ChannelSerializer,
48
    VersionSerializer,
49
    ActionSerializer,
50
    StatisticsMonthsSerializer,
51
    ServerVersionSerializer,
52
)
53
from omaha.factories import ApplicationFactory, DataFactory, PlatformFactory, ChannelFactory, VersionFactory, ActionFactory
54
from omaha.models import Application, Data, Channel, Platform, Version, Action
55
from omaha.tests.utils import temporary_media_root
56
from sparkle.models import SparkleVersion
57
58
User = get_user_model()
59
60
61
class BaseTest(object):
62
    url = None
63
    url_args = ()
64
    url_detail = None
65
    factory = None
66
    serializer = None
67
    maxDiff = None
68
    is_private = True
69
70
    def _is_private(self):
71
        if not self.is_private and not settings.IS_PRIVATE:
72
            return True
73
        elif self.is_private and settings.IS_PRIVATE:
74
            return True
75
        else:
76
            return False
77
78
    def setUp(self):
79
        self.objects = self.factory.create_batch(10)
80
        self.user = User.objects.create_user(username='test', password='secret', email='[email protected]')
81
        self.client.credentials(
82
            HTTP_AUTHORIZATION='Basic %s' % base64.b64encode(bytes('{}:{}'.format('test', 'secret'), 'utf8')).decode())
83
84
    def test_unauthorized(self):
85
        if not self._is_private():
86
            return
87
        client = APIClient()
88
        response = client.get(reverse(self.url, args=self.url_args), format='json')
89
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
90
91
    def test_list(self):
92
        if not self._is_private():
93
            return
94
        response = self.client.get(reverse(self.url, args=self.url_args), format='json')
95
        self.assertEqual(response.status_code, status.HTTP_200_OK)
96
        self.assertEqual(len(response.data), 10)
97
        self.assertEqual(self.serializer(self.objects, many=True).data, response.data[::-1])
98
99
    def test_detail(self):
100
        if not self._is_private():
101
            return
102
        obj = self.objects[0]
103
        url = reverse(self.url_detail, kwargs=dict(pk=obj.pk))
104
105
        response = self.client.get(url, format='json')
106
        self.assertEqual(response.status_code, status.HTTP_200_OK)
107
        self.assertDictEqual(response.data, self.serializer(obj).data)
108
109
110
class AppTest(BaseTest, APITestCase):
111
    url = 'application-list'
112
    url_detail = 'application-detail'
113
    factory = ApplicationFactory
114
    serializer = AppSerializer
115
116
    @is_private()
117
    def test_create(self):
118
        data = dict(id='test_id', name='test_name', data_set=[])
119
        response = self.client.post(reverse(self.url
120
                                            ), data, format='json')
121
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
122
        obj = Application.objects.get(id=response.data['id'])
123
        self.assertEqual(response.data, self.serializer(obj).data)
124
125
126
class DataTest(BaseTest, APITestCase):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
127
    url = 'data-list'
128
    url_detail = 'data-detail'
129
    factory = DataFactory
130
    serializer = DataSerializer
131
132
    @is_private()
133
    def test_create(self):
134
        app = ApplicationFactory.create()
135
        data = dict(name=0, app=app.pk)
136
        response = self.client.post(reverse(self.url), data, format='json')
137
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
138
        obj = Data.objects.get(id=response.data['id'])
139
        self.assertEqual(response.data, self.serializer(obj).data)
140
141
142
class PlatformTest(BaseTest, APITestCase):
143
    url = 'platform-list'
144
    url_detail = 'platform-detail'
145
    factory = PlatformFactory
146
    serializer = PlatformSerializer
147
148
    @is_private()
149
    def test_list(self):
150
        super(PlatformTest, self).test_list()
151
152
    @is_private()
153
    def test_create(self):
154
        data = dict(name='test_name')
155
        response = self.client.post(reverse(self.url), data, format='json')
156
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
157
        obj = Platform.objects.get(id=response.data['id'])
158
        self.assertEqual(response.data, self.serializer(obj).data)
159
160
161
class ChannelTest(BaseTest, APITestCase):
162
    url = 'channel-list'
163
    url_detail = 'channel-detail'
164
    factory = ChannelFactory
165
    serializer = ChannelSerializer
166
167
    @is_private()
168
    def test_create(self):
169
        data = dict(name='test_name')
170
        response = self.client.post(reverse(self.url), data, format='json')
171
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
172
        obj = Channel.objects.get(id=response.data['id'])
173
        self.assertEqual(response.data, self.serializer(obj).data)
174
175
176
class VersionTest(BaseTest, APITestCase):
177
    url = 'version-list'
178
    url_detail = 'version-detail'
179
    factory = VersionFactory
180
    serializer = VersionSerializer
181
182
    @is_private()
183
    @temporary_media_root(MEDIA_URL='http://cache.pack.google.com/edgedl/chrome/install/782.112/')
184
    def test_detail(self):
185
        super(VersionTest, self).test_detail()
186
187
    @is_private()
188
    @temporary_media_root(MEDIA_URL='http://cache.pack.google.com/edgedl/chrome/install/782.112/')
189
    def test_list(self):
190
        super(VersionTest, self).test_list()
191
192
    @is_private()
193
    @temporary_media_root(MEDIA_URL='http://cache.pack.google.com/edgedl/chrome/install/782.112/')
194
    def test_create(self):
195
        data = dict(
196
            app=ApplicationFactory.create().id,
197
            platform=PlatformFactory.create().id,
198
            channel=ChannelFactory.create().id,
199
            version='1.2.3.4',
200
            file=SimpleUploadedFile("chrome.exe", b'content'),
201
        )
202
        response = self.client.post(reverse(self.url), data)
203
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
204
        version = Version.objects.get(id=response.data['id'])
205
        self.assertEqual(response.data, self.serializer(version).data)
206
        self.assertEqual(version.file_size, len(b'content'))
207
        self.assertTrue(version.is_enabled)
208
209
210
class ActionTest(BaseTest, APITestCase):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
211
    url = 'action-list'
212
    url_detail = 'action-detail'
213
    factory = ActionFactory
214
    serializer = ActionSerializer
215
216
    @is_private()
217
    def test_create(self):
218
        version = VersionFactory.create()
219
        data = dict(event=1, version=version.pk)
220
        response = self.client.post(reverse(self.url), data, format='json')
221
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
222
        obj = Action.objects.get(id=response.data['id'])
223
        self.assertEqual(response.data, self.serializer(obj).data)
224
225
class LiveStatistics(APITestCase):
226
    maxDiff = None
227
228
    def _generate_fake_statistics(self):
229
        now = datetime(2016, 2, 13)
230
231
        for i in range(self.n_hours):
232
            date = datetime(now.year, now.month, now.day, i)
233
            for id in range(0, i):
234
                mark_event('online:app:win:2.0.0.0', id, now=date, track_hourly=True)
235
236
                mark_event('online:app:mac:4.0.0.1', id, now=date, track_hourly=True)
237
            for id in range(i, self.n_hours):
238
                mark_event('online:app:win:1.0.0.0', id, now=date, track_hourly=True)
239
                mark_event('online:app:mac:3.0.0.0', id, now=date, track_hourly=True)
240
241
242
    def setUp(self):
243
        self.user = User.objects.create_user(username='test', password='secret', email='[email protected]')
244
        self.client.credentials(
245
            HTTP_AUTHORIZATION='Basic %s' % base64.b64encode(bytes('{}:{}'.format('test', 'secret'), 'utf8')).decode())
246
247
        redis.flushdb()
248
        self.app = Application.objects.create(id='app', name='app')
249
        self.channel = Channel.objects.create(name='stable')
250
        self.platform = Platform.objects.create(name='win')
251
        self.version1 = Version.objects.create(
252
            app=self.app,
253
            platform=self.platform,
254
            channel=self.channel,
255
            version='1.0.0.0',
256
            file=SimpleUploadedFile('./chrome_installer.exe', False))
257
258
        self.version2 = Version.objects.create(
259
            app=self.app,
260
            platform=self.platform,
261
            channel=self.channel,
262
            version='2.0.0.0',
263
            file=SimpleUploadedFile('./chrome_installer.exe', False))
264
265
        self.sparkle_version1 = SparkleVersion.objects.create(
266
            app=self.app,
267
            channel=self.channel,
268
            version='0.0',
269
            short_version='3.0.0.0',
270
            file=SimpleUploadedFile('./chrome_installer.dmg', False))
271
272
        self.sparkle_version2 = SparkleVersion.objects.create(
273
            app=self.app,
274
            channel=self.channel,
275
            version='0.1',
276
            short_version='4.0.0.1',
277
            file=SimpleUploadedFile('./chrome_installer.dmg', False))
278
279
        self.n_hours = 24
280
        self._generate_fake_statistics()
281
282
        self.win_statistics = [('1.0.0.0', [[datetime(2016, 2, 13, hour, tzinfo=pytz.UTC).strftime("%Y-%m-%dT%H:%M:%S.%fZ"), self.n_hours - hour]
283
                                            for hour in range(self.n_hours)])]
284
        self.win_statistics.append(('2.0.0.0', [[datetime(2016, 2, 13, hour, tzinfo=pytz.UTC).strftime("%Y-%m-%dT%H:%M:%S.%fZ"), hour]
285
                                                for hour in range(self.n_hours)]))
286
287
        self.mac_statistics = [('3.0.0.0', [[datetime(2016, 2, 13, hour, tzinfo=pytz.UTC).strftime("%Y-%m-%dT%H:%M:%S.%fZ"), self.n_hours - hour]
288
                                            for hour in range(self.n_hours)])]
289
        self.mac_statistics.append(('4.0.0.1', [[datetime(2016, 2, 13, hour, tzinfo=pytz.UTC).strftime("%Y-%m-%dT%H:%M:%S.%fZ"), hour]
290
                                                for hour in range(self.n_hours)]))
291
292
        self.data = dict(data=dict(win=dict(self.win_statistics),
293
                                   mac=dict(self.mac_statistics)))
294
295
    @is_private()
296
    def test_unauthorized(self):
297
        client = APIClient()
298
        response = client.get(reverse('api-statistics-live', args=('app',)), format='json')
299
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
300
301
    @is_private()
302
    def test_list(self):
303
        with freeze_time("2016-02-13 23:00:01"):
304
            response = self.client.get(reverse('api-statistics-live', args=('app',)), format='json')
305
        self.assertEqual(response.status_code, status.HTTP_200_OK)
306
        self.assertDictEqual(StatisticsMonthsSerializer(self.data).data, response.data)
307
308
309
@freeze_time("2016-01-27")
310
class StatisticsMonthsMixin(object):
311
    url = None
312
    url_args = ()
313
    serializer = None
314
315
    def _generate_fake_statistics(self):
316
        now = datetime.now()
317
        prev_year = now.year - 1
318
319
        for i in range(2, 13):
320
            date = datetime(year=prev_year, month=i, day=1)
321
            for id in range(1, i + 1):
322
                user_id = UUID(int=id)
323
                userid_counting(user_id, self.app_list, self.platform.name, now=date)
324
325
        user_id = UUID(int=13)
326
        userid_counting(user_id, self.app_list, self.platform.name, now=datetime(year=now.year, month=1, day=1))
327
328
    @temporary_media_root()
329
    def setUp(self):
330
        self.user = User.objects.create_user(username='test', password='secret', email='[email protected]')
331
        self.client.credentials(
332
            HTTP_AUTHORIZATION='Basic %s' % base64.b64encode(bytes('{}:{}'.format('test', 'secret'), 'utf8')).decode())
333
334
        redis.flushdb()
335
        self.app = Application.objects.create(id='app', name='app')
336
        self.channel = Channel.objects.create(name='stable')
337
        self.platform = Platform.objects.create(name='win')
338
        self.version1 = Version.objects.create(
339
            app=self.app,
340
            platform=self.platform,
341
            channel=self.channel,
342
            version='1.0.0.0',
343
            file=SimpleUploadedFile('./chrome_installer.exe', False))
344
        self.version2 = Version.objects.create(
345
            app=self.app,
346
            platform=self.platform,
347
            channel=self.channel,
348
            version='2.0.0.0',
349
            file=SimpleUploadedFile('./chrome_installer.exe', False))
350
        self.app_list = [dict(appid=self.app.id, version=str(self.version1.version))]
351
352
        self._generate_fake_statistics()
353
        now = datetime.now()
354
        self.users_statistics = [(datetime(now.year-1, x, 1).strftime("%Y-%m"), x) for x in range(2, 13)]
355
        self.users_statistics.append((datetime(now.year, 1, 1).strftime("%Y-%m"), 1))
356
        self.data = dict(data=dict(self.users_statistics))
357
358
    @is_private()
359
    def test_unauthorized(self):
360
        client = APIClient()
361
        response = client.get(reverse(self.url, args=self.url_args), format='json')
362
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
363
364
365
    @is_private()
366
    def test_list(self):
367
        response = self.client.get(reverse(self.url, args=self.url_args), format='json')
368
        self.assertEqual(response.status_code, status.HTTP_200_OK)
369
        self.assertEqual(self.serializer(self.data).data, response.data)
370
371
372
class StatisticsMonthsListTest(StatisticsMonthsMixin, APITestCase):
373
    url = 'api-statistics-months-list'
374
    serializer = StatisticsMonthsSerializer
375
376
@freeze_time("2016-01-27")
377
class StatisticsMonthsDetailTest(StatisticsMonthsMixin, APITestCase):
378
    url = 'api-statistics-months-detail'
379
    url_args = ('app',)
380
    serializer = StatisticsMonthsSerializer
381
382
    @is_private()
383
    def test_list(self):
384
        data_detail = self.data.copy()
385
        data_detail['data']['install_count'] = 0
386
        data_detail['data']['update_count'] = 0
387
        response = self.client.get(reverse(self.url, args=self.url_args), format='json')
388
        self.assertEqual(response.status_code, status.HTTP_200_OK)
389
        self.assertEqual(self.serializer(data_detail).data, response.data)
390
391
392
class StatisticsVersionsTest(StatisticsMonthsMixin, APITestCase):
393
    url = 'api-statistics-versions'
394
    url_args = ('app',)
395
    serializer = StatisticsMonthsSerializer
396
397
    def setUp(self):
398
        super(StatisticsVersionsTest, self).setUp()
399
        data = get_users_versions(self.app.id)
400
        self.data = dict(data=dict(data))
401
402
403
class StatisticsChannelsTest(StatisticsMonthsMixin, APITestCase):
404
    url = 'api-statistics-channels'
405
    url_args = ('app',)
406
    serializer = StatisticsMonthsSerializer
407
408
    def setUp(self):
409
        super(StatisticsChannelsTest, self).setUp()
410
        data = get_channel_statistics(self.app.id)
411
        self.data = dict(data=dict(data))
412
413
class ServerVersionTest(APITestCase):
414
    url = 'api-version'
415
    serializer = ServerVersionSerializer
416
417
    def setUp(self):
418
        self.user = User.objects.create_user(username='test', password='secret', email='[email protected]')
419
        self.client.credentials(
420
            HTTP_AUTHORIZATION='Basic %s' % base64.b64encode(bytes('{}:{}'.format('test', 'secret'), 'utf8')).decode())
421
        self.data = dict(version=settings.APP_VERSION)
422
423
    @is_private()
424
    def test(self):
425
        response = self.client.get(reverse(self.url), format='json')
426
        self.assertEqual(response.status_code, status.HTTP_200_OK)
427
        self.assertEqual(self.serializer(self.data).data, response.data)
428