Completed
Push — master ( f684af...589bde )
by Egor
01:18
created

StatisticsTest.test_userid_counting()   B

Complexity

Conditions 4

Size

Total Lines 40

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 40
rs 8.5806
cc 4
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
21
from builtins import range
22
23
from datetime import datetime
24
from uuid import UUID
25
26
from django.test import TestCase
27
from django.core.files.uploadedfile import SimpleUploadedFile
28
29
from mock import patch
30
from freezegun import freeze_time
31
from bitmapist import DayEvents, HourEvents, mark_event
32
33
from omaha.tests import fixtures
34
from omaha.parser import parse_request
35
from omaha.statistics import (
36
    userid_counting,
37
    add_app_statistics,
38
    add_app_live_statistics,
39
    is_user_active,
40
    get_kwargs_for_model,
41
    parse_os,
42
    parse_hw,
43
    parse_req,
44
    parse_apps,
45
    parse_events,
46
    collect_statistics,
47
    update_live_statistics,
48
    get_users_statistics_months,
49
    get_users_statistics_weeks,
50
    get_channel_statistics,
51
    get_users_versions,
52
)
53
54
from omaha.tests.utils import temporary_media_root
55
from omaha.utils import redis, get_id
56
from omaha.settings import DEFAULT_CHANNEL
57
from omaha.models import (
58
    ACTIVE_USERS_DICT_CHOICES,
59
    Os,
60
    Hw,
61
    Request,
62
    AppRequest,
63
    Event,
64
    Application,
65
    Platform,
66
    Channel,
67
    Version,
68
)
69
70
71
class StatisticsTest(TestCase):
72
    def setUp(self):
73
        redis.flushdb()
74
75
    def tearDown(self):
76
        redis.flushdb()
77
78
    @patch('omaha.statistics.add_app_statistics')
79
    def test_userid_counting(self, mock_add_app_statistics):
80
        now = datetime.utcnow()
81
82
        userid1 = '{F07B3878-CD6F-4B96-B52F-95C4D23077E0}'
83
        user1_id = get_id(userid1)
84
85
        userid2 = '{EC4C5647-F798-4BCA-83DA-926CD448A1D5}'
86
        user2_id = get_id(userid2)
87
88
        app_list = [dict(appid='{F97917B1-19AB-48C1-9802-CEF305B10804}'),
89
                    dict(appid='{555B8D18-076D-4576-9579-1FD7F0399EAE}')]
90
91
        request_events = DayEvents('request', now.year, now.month, now.day)
92
93
        self.assertFalse(user1_id in request_events)
94
        self.assertEqual(len(request_events), 0)
95
96
        userid_counting(userid1, app_list, 'win')
97
98
        for app in app_list:
99
            mock_add_app_statistics.assert_any_call(user1_id, 'win', app, now=None)
100
101
        self.assertEqual(len(request_events), 1)
102
        self.assertTrue(user1_id in request_events)
103
104
        userid_counting(userid1, app_list, 'win')
105
106
        for app in app_list:
107
            mock_add_app_statistics.assert_any_call(user1_id, 'win', app, now=None)
108
109
        self.assertEqual(len(request_events), 1)
110
111
        self.assertFalse(user2_id in request_events)
112
        userid_counting(userid2, app_list[:1], 'win')
113
        self.assertTrue(user2_id in request_events)
114
        for app in app_list[:1]:
115
            mock_add_app_statistics.assert_any_call(user2_id, 'win', app, now=None)
116
117
        self.assertEqual(len(request_events), 2)
118
119
    def test_add_app_statistics(self):
120
        now = datetime.utcnow()
121
        userid = 1
122
        channel = DEFAULT_CHANNEL
123
        platform = 'win'
124
        app = dict(appid='{F97917B1-20AB-48C1-9802-CEF305B10804}', version='30.0.123.1234')
125
        appid = app.get('appid')
126
        version = app.get('version')
127
128
        events_appid = DayEvents('request:%s' % app.get('appid'), now.year, now.month, now.day)
129
        events_appid_version = DayEvents('request:{}:{}'.format(appid, version), now.year, now.month, now.day)
130
        events_appid_platform =DayEvents('request:{}:{}'.format(appid, platform), now.year, now.month, now.day)
131
        events_appid_channel = DayEvents('request:{}:{}'.format(appid, channel), now.year, now.month, now.day)
132
        events_appid_platform_version = DayEvents('request:{}:{}:{}'.format(appid, platform, version), now.year, now.month, now.day)
133
134
        self.assertEqual(len(events_appid), 0)
135
        self.assertEqual(len(events_appid_version), 0)
136
        self.assertEqual(len(events_appid_platform), 0)
137
        self.assertEqual(len(events_appid_channel), 0)
138
        self.assertEqual(len(events_appid_platform_version), 0)
139
140
        add_app_statistics(userid, platform, app)
141
142
        self.assertEqual(len(events_appid), 1)
143
        self.assertEqual(len(events_appid_version), 1)
144
        self.assertEqual(len(events_appid_platform), 1)
145
        self.assertEqual(len(events_appid_channel), 1)
146
        self.assertEqual(len(events_appid_platform_version), 1)
147
148
        self.assertIn(userid, events_appid)
149
        self.assertIn(userid, events_appid_version)
150
        self.assertIn(userid, events_appid_platform)
151
        self.assertIn(userid, events_appid_channel)
152
        self.assertIn(userid, events_appid_platform_version)
153
154
    def test_add_app_live_statistics(self):
155
        request = parse_request(fixtures.request_update_check)
156
        app = request.findall('app')[0]
157
158
        now = datetime.utcnow()
159
        userid = 1
160
        platform = 'win'
161
162
        appid = app.get('appid')
163
        version = app.get('version')
164
165
        events_appid_version = HourEvents('online:{}:{}'.format(appid, version), now.year, now.month, now.day, now.hour)
166
        events_appid_platform_version = HourEvents('online:{}:{}:{}'.format(appid, platform, version), now.year, now.month, now.day, now.hour)
167
168
        self.assertEqual(len(events_appid_version), 0)
169
        self.assertEqual(len(events_appid_platform_version), 0)
170
171
        add_app_live_statistics(userid, platform, app)
172
173
        self.assertEqual(len(events_appid_version), 1)
174
        self.assertEqual(len(events_appid_platform_version), 1)
175
176
        self.assertIn(userid, events_appid_version)
177
        self.assertIn(userid, events_appid_platform_version)
178
179
    def test_is_user_active(self):
180
        userid = '{F07B3878-CD6F-4B96-B52F-95C4D23077E0}'
181
        id = get_id(userid)
182
183
        self.assertTrue(is_user_active(ACTIVE_USERS_DICT_CHOICES['all'], userid))
184
        self.assertFalse(is_user_active(ACTIVE_USERS_DICT_CHOICES['week'], userid))
185
        self.assertFalse(is_user_active(ACTIVE_USERS_DICT_CHOICES['month'], userid))
186
187
        mark_event('request', id)
188
189
        self.assertTrue(is_user_active(ACTIVE_USERS_DICT_CHOICES['all'], userid))
190
        self.assertTrue(is_user_active(ACTIVE_USERS_DICT_CHOICES['week'], userid))
191
        self.assertTrue(is_user_active(ACTIVE_USERS_DICT_CHOICES['month'], userid))
192
193
    def test_get_kwargs_for_model(self):
194
        os = dict(platform="win",
195
                  version="6.1",
196
                  sp="",
197
                  arch="x64")
198
        kwargs = get_kwargs_for_model(Os, os)
199
        self.assertDictEqual(kwargs, dict(platform="win",
200
                                          version="6.1",
201
                                          sp="",
202
                                          arch="x64",
203
                                          id=None))
204
205
    def test_parse_os(self):
206
        request = parse_request(fixtures.request_event)
207
        os = parse_os(request.os)
208
        self.assertIsInstance(os, Os)
209
        self.assertEqual(os.platform, 'win')
210
        self.assertEqual(os.version, '6.1')
211
        self.assertEqual(os.sp, '')
212
        self.assertEqual(os.arch, 'x64')
213
214
    def test_parse_hw(self):
215
        hw = dict(sse2="1")
216
        hw = parse_hw(hw)
217
        self.assertIsInstance(hw, Hw)
218
        self.assertEqual(hw.sse, None)
219
        self.assertEqual(hw.sse2, 1)
220
        self.assertEqual(hw.sse3, None)
221
        self.assertEqual(hw.ssse3, None)
222
        self.assertEqual(hw.sse41, None)
223
        self.assertEqual(hw.sse42, None)
224
        self.assertEqual(hw.avx, None)
225
        self.assertEqual(hw.physmemory, None)
226
227
    def test_parse_request(self):
228
        request = parse_request(fixtures.request_event)
229
        req = parse_req(request)
230
        self.assertIsInstance(req, Request)
231
        self.assertEqual(req.version, Request._meta.get_field_by_name('version')[0].to_python('1.3.23.0'))
232
        self.assertEqual(req.ismachine, 1)
233
        self.assertEqual(req.sessionid, '{2882CF9B-D9C2-4edb-9AAF-8ED5FCF366F7}')
234
        self.assertEqual(req.userid, '{F25EC606-5FC2-449b-91FF-FA21CADB46E4}')
235
        self.assertEqual(req.originurl, None)
236
        self.assertEqual(req.testsource, 'ossdev')
237
        self.assertEqual(req.updaterchannel, None)
238
239
    def test_parse_apps(self):
240
        request = parse_request(fixtures.request_event)
241
        req = parse_req(request)
242
        req.os = parse_os(request.os)
243
        req.hw = parse_hw(request.hw) if request.get('hw') else None
244
        req.save()
245
246
        apps = parse_apps(request.findall('app'), req)
247
        self.assertEqual(len(apps), 1)
248
        app = apps[0]
249
        self.assertIsInstance(app, AppRequest)
250
        self.assertEqual(app.version, None)
251
        self.assertEqual(app.nextversion, Request._meta.get_field_by_name('version')[0].to_python('13.0.782.112'))
252
        self.assertEqual(app.lang, 'en')
253
        self.assertEqual(app.tag, None)
254
        self.assertEqual(app.installage, 6)
255
        self.assertEqual(app.appid, '{8A69D345-D564-463C-AFF1-A69D9E530F96}')
256
257
    def test_parse_events(self):
258
        request = parse_request(fixtures.request_event)
259
        events = request.findall('app')[0].findall('event')
260
        events = parse_events(events)
261
        self.assertEqual(len(events), 3)
262
        event = events[0]
263
        self.assertIsInstance(event, Event)
264
        self.assertEqual(event.eventtype, 9)
265
        self.assertEqual(event.eventresult, 1)
266
        self.assertEqual(event.errorcode, 0)
267
        self.assertEqual(event.extracode1, 0)
268
        self.assertEqual(event.download_time_ms, None)
269
        self.assertEqual(event.downloaded, None)
270
        self.assertEqual(event.total, None)
271
        self.assertEqual(event.update_check_time_ms, None)
272
        self.assertEqual(event.install_time_ms, None)
273
        self.assertEqual(event.source_url_index, None)
274
        self.assertEqual(event.state_cancelled, None)
275
        self.assertEqual(event.time_since_update_available_ms, None)
276
        self.assertEqual(event.time_since_download_start_ms, None)
277
        self.assertEqual(event.nextversion, None)
278
        self.assertEqual(event.previousversion, None)
279
280
    def test_collect_statistics(self):
281
        request = parse_request(fixtures.request_event)
282
283
        self.assertEqual(Os.objects.all().count(), 0)
284
        self.assertEqual(Hw.objects.all().count(), 0)
285
        self.assertEqual(Request.objects.all().count(), 0)
286
        self.assertEqual(AppRequest.objects.all().count(), 0)
287
        self.assertEqual(Event.objects.all().count(), 0)
288
289
        collect_statistics(request)
290
291
        self.assertEqual(Os.objects.all().count(), 1)
292
        self.assertEqual(Hw.objects.all().count(), 0)
293
        self.assertEqual(Request.objects.all().count(), 1)
294
        self.assertEqual(AppRequest.objects.all().count(), 1)
295
        self.assertEqual(Event.objects.all().count(), 3)
296
297
        os = Os.objects.get()
298
        req = Request.objects.get()
299
        app_req = AppRequest.objects.get()
300
        events = Event.objects.all()
301
302
        self.assertEqual(os.platform, 'win')
303
        self.assertEqual(os.version, '6.1')
304
        self.assertEqual(os.sp, '')
305
        self.assertEqual(os.arch, 'x64')
306
307
        self.assertEqual(req.version, Request._meta.get_field_by_name('version')[0].to_python('1.3.23.0'))
308
        self.assertEqual(req.ismachine, 1)
309
        self.assertEqual(req.sessionid, '{2882CF9B-D9C2-4edb-9AAF-8ED5FCF366F7}')
310
        self.assertEqual(req.userid, '{F25EC606-5FC2-449b-91FF-FA21CADB46E4}')
311
        self.assertEqual(req.originurl, None)
312
        self.assertEqual(req.testsource, 'ossdev')
313
        self.assertEqual(req.updaterchannel, None)
314
        self.assertEqual(req.os, os)
315
        self.assertEqual(req.hw, None)
316
317
        self.assertEqual(app_req.version, None)
318
        self.assertEqual(app_req.nextversion, Request._meta.get_field_by_name('version')[0].to_python('13.0.782.112'))
319
        self.assertEqual(app_req.lang, 'en')
320
        self.assertEqual(app_req.tag, None)
321
        self.assertEqual(app_req.installage, 6)
322
        self.assertEqual(app_req.appid, '{8A69D345-D564-463C-AFF1-A69D9E530F96}')
323
        self.assertEqual(app_req.request, req)
324
325
        event = events[0]
326
327
        self.assertEqual(event.eventtype, 9)
328
        self.assertEqual(event.eventresult, 1)
329
        self.assertEqual(event.errorcode, 0)
330
        self.assertEqual(event.extracode1, 0)
331
        self.assertEqual(event.download_time_ms, None)
332
        self.assertEqual(event.downloaded, None)
333
        self.assertEqual(event.total, None)
334
        self.assertEqual(event.update_check_time_ms, None)
335
        self.assertEqual(event.install_time_ms, None)
336
        self.assertEqual(event.source_url_index, None)
337
        self.assertEqual(event.state_cancelled, None)
338
        self.assertEqual(event.time_since_update_available_ms, None)
339
        self.assertEqual(event.time_since_download_start_ms, None)
340
        self.assertEqual(event.nextversion, None)
341
        self.assertEqual(event.previousversion, None)
342
343
        for e in events:
344
            self.assertIn(e, app_req.events.all())
345
346
    def test_update_live_statistics_install(self):
347
        request = parse_request(fixtures.request_event_install_success)
348
        apps = request.findall('app')
349
        app = apps[0]
350
351
        now = datetime.utcnow()
352
        userid = 1
353
        platform = 'win'
354
355
        appid = app.get('appid')
356
        version_1 = '0.0.0.1'
357
        version_2 = '0.0.0.2'
358
359
        events_appid_version_1 = HourEvents('online:{}:{}'.format(appid, version_1), now.year, now.month, now.day, now.hour)
360
        events_appid_platform_version_1 = HourEvents('online:{}:{}:{}'.format(appid, platform, version_1), now.year, now.month, now.day, now.hour)
361
362
        self.assertEqual(len(events_appid_version_1), 0)
363
        self.assertEqual(len(events_appid_platform_version_1), 0)
364
365
        update_live_statistics(userid, apps, platform)
366
367
        self.assertEqual(len(events_appid_version_1), 1)
368
        self.assertEqual(len(events_appid_platform_version_1), 1)
369
370
        request = parse_request(fixtures.request_event_update_success)
371
        apps = request.findall('app')
372
373
        update_live_statistics(userid, apps, platform)
374
375
        events_appid_version_1 = HourEvents('online:{}:{}'.format(appid, version_1), now.year, now.month, now.day, now.hour)
376
        events_appid_platform_version_1 = HourEvents('online:{}:{}:{}'.format(appid, platform, version_1), now.year, now.month, now.day, now.hour)
377
        events_appid_version_2 = HourEvents('online:{}:{}'.format(appid, version_2), now.year, now.month, now.day, now.hour)
378
        events_appid_platform_version_2 = HourEvents('online:{}:{}:{}'.format(appid, platform, version_2), now.year, now.month, now.day, now.hour)
379
380
        self.assertEqual(len(events_appid_version_1), 0)
381
        self.assertEqual(len(events_appid_platform_version_1), 0)
382
        self.assertEqual(len(events_appid_version_2), 1)
383
        self.assertEqual(len(events_appid_platform_version_2), 1)
384
385
        request = parse_request(fixtures.request_event_uninstall_success)
386
        apps = request.findall('app')
387
388
        update_live_statistics(userid, apps, platform)
389
390
        events_appid_version_2 = HourEvents('online:{}:{}'.format(appid, version_2),
391
                                            now.year, now.month, now.day, now.hour)
392
        events_appid_platform_version_2 = HourEvents('online:{}:{}:{}'.format(appid, platform, version_2),
393
                                                     now.year, now.month, now.day, now.hour)
394
395
        self.assertEqual(len(events_appid_version_2), 0)
396
        self.assertEqual(len(events_appid_platform_version_2), 0)
397
398
    def test_update_live_statistics_updatecheck(self):
399
        request = parse_request(fixtures.request_update_check)
400
        apps = request.findall('app')
401
        app = apps[0]
402
403
        now = datetime.utcnow()
404
        userid = 1
405
        platform = 'win'
406
407
        appid = app.get('appid')
408
        version = app.get('version')
409
410
        events_appid_version = HourEvents('online:{}:{}'.format(appid, version), now.year, now.month, now.day, now.hour)
411
        events_appid_platform_version = HourEvents('online:{}:{}:{}'.format(appid, platform, version), now.year, now.month, now.day, now.hour)
412
413
        self.assertEqual(len(events_appid_version), 0)
414
        self.assertEqual(len(events_appid_platform_version), 0)
415
416
        update_live_statistics(userid, apps, platform)
417
418
        self.assertEqual(len(events_appid_version), 1)
419
        self.assertEqual(len(events_appid_platform_version), 1)
420
421
422
class GetStatisticsTest(TestCase):
423
    def _generate_fake_statistics(self):
424
        now = datetime.now()
425
        year = now.year
426
427
        for i in range(1, 13):
428
            date = datetime(year=year, month=i, day=10)
429
            for id in range(1, i + 1):
430
                user_id = UUID(int=id)
431
                userid_counting(user_id, self.app_list, self.platform.name, now=date)
432
433
    @temporary_media_root()
434
    def setUp(self):
435
        redis.flushdb()
436
        self.app = Application.objects.create(id='app', name='app')
437
        self.channel = Channel.objects.create(name='stable')
438
        self.platform = Platform.objects.create(name='win')
439
        self.version1 = Version.objects.create(
440
            app=self.app,
441
            platform=self.platform,
442
            channel=self.channel,
443
            version='1.0.0.0',
444
            file=SimpleUploadedFile('./chrome_installer.exe', False))
445
        self.version2 = Version.objects.create(
446
            app=self.app,
447
            platform=self.platform,
448
            channel=self.channel,
449
            version='2.0.0.0',
450
            file=SimpleUploadedFile('./chrome_installer.exe', False))
451
        self.app_list = [dict(appid=self.app.id, version=str(self.version1.version))]
452
453
        self._generate_fake_statistics()
454
        now = datetime.now()
455
        self.users_statistics = [(datetime(now.year, x, 1).strftime("%Y-%m"), x) for x in range(1, 13)]
456
457
    def tearDown(self):
458
        redis.flushdb()
459
460
    def test_get_users_statistics_months(self):
461
        self.assertListEqual(get_users_statistics_months(), self.users_statistics)
462
        self.assertListEqual(get_users_statistics_months(app_id=self.app.id), self.users_statistics)
463
464
    def test_get_users_statistics_weeks(self):
465
        now = datetime.now()
466
        with freeze_time(datetime(year=now.year, month=now.month, day=10)):
467
            self.assertListEqual(get_users_statistics_weeks(),
468
                                 [('Previous week', 0),
469
                                  ('Current week', now.month),
470
                                  ('Yesterday', 0),
471
                                  ('Today', now.month)])
472
            self.assertListEqual(get_users_statistics_weeks(self.app.id),
473
                                 [('Previous week', 0),
474
                                  ('Current week', now.month),
475
                                  ('Yesterday', 0),
476
                                  ('Today', now.month)])
477
478
    def test_get_chanels_statistics(self):
479
        now = datetime.now()
480
        with freeze_time(datetime(year=now.year, month=now.month, day=10)):
481
            self.assertListEqual(get_channel_statistics(self.app.id), [('stable', now.month)])
482
483
    def test_get_users_versions(self):
484
        now = datetime.now()
485
        with freeze_time(datetime(year=now.year, month=now.month, day=10)):
486
            self.assertListEqual(get_users_versions(self.app.id), [('1.0.0.0', now.month)])
487