Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
S2-group
GitHub Repository: S2-group/android-runner
Path: blob/master/tests/unit/test_experiment.py
908 views
1
import filecmp
2
import os
3
from collections import OrderedDict
4
from http.server import HTTPServer
5
6
from AndroidRunner.Browsers import Browser
7
from AndroidRunner.StopRunWebserver import StopRunWebserver
8
import pytest
9
import psutil
10
from mock import MagicMock, Mock, call, patch
11
from AndroidRunner.util import ConfigError
12
import paths
13
from AndroidRunner.Devices import Devices
14
from AndroidRunner.Experiment import Experiment
15
from AndroidRunner.ExperimentFactory import ExperimentFactory
16
from AndroidRunner.NativeExperiment import NativeExperiment
17
from AndroidRunner.Profilers import Profilers
18
from AndroidRunner.Progress import Progress
19
from AndroidRunner.Scripts import Scripts
20
from AndroidRunner.WebExperiment import WebExperiment
21
from AndroidRunner.util import ConfigError, makedirs
22
from tests.PluginTests import PluginTests
23
from AndroidRunner.PrematureStoppableRun import PrematureStoppableRun
24
from tests.unit.fixtures.FakeDevice import FakeDevice
25
26
# noinspection PyUnusedLocal
27
class TestExperiment(object):
28
29
@pytest.fixture()
30
def test_config(self):
31
config = dict()
32
config['randomization'] = True
33
config['adb_path'] = 'test_adb'
34
config['devices'] = ['dev1', 'dev2']
35
config['repetitions'] = 10
36
config['paths'] = ['test/paths/1', 'test/paths/2']
37
config['profilers'] = {'fake': {'config1': 1, 'config2': 2}}
38
config['scripts'] = {'script1': 'path/to/1'}
39
config['reset_adb_among_runs'] = True
40
config['time_between_run'] = 10
41
config['clear_cache'] = True
42
return config
43
44
@pytest.fixture()
45
@patch('AndroidRunner.Tests.check_dependencies')
46
@patch('AndroidRunner.Devices.Devices.__init__')
47
def default_experiment(self, mock_devices, mock_test):
48
paths.OUTPUT_DIR = 'fake/path/name'
49
device_config = {'devices': 'fake_device'}
50
mock_devices.return_value = None
51
return Experiment(device_config, None, False)
52
53
def test_init_empty_config(self):
54
empty_config = {}
55
with pytest.raises(ConfigError):
56
Experiment(empty_config, None, False)
57
58
@patch('AndroidRunner.Experiment.Experiment.prepare_device')
59
@patch('AndroidRunner.Tests.check_dependencies')
60
@patch('AndroidRunner.Devices.Devices.__init__')
61
def test_init_only_device_config_no_restart(self, mock_devices, mock_test, mock_prepare):
62
paths.OUTPUT_DIR = 'fake/path/name'
63
device_config = {'devices': 'fake_device'}
64
mock_devices.return_value = None
65
experiment = Experiment(device_config, None, False)
66
67
assert experiment.progress is None
68
assert experiment.basedir is None
69
assert experiment.random is False
70
assert isinstance(experiment.devices, Devices)
71
assert experiment.repetitions == 1
72
assert experiment.paths == []
73
assert isinstance(experiment.profilers, Profilers)
74
assert isinstance(experiment.scripts, Scripts)
75
assert experiment.reset_adb_among_runs is False
76
assert experiment.time_between_run == 0
77
assert experiment.clear_cache == False
78
assert experiment.output_root == paths.OUTPUT_DIR
79
assert experiment.result_file_structure is None
80
assert mock_prepare.call_count == 0
81
82
@patch('AndroidRunner.Experiment.Experiment.prepare_device')
83
@patch('AndroidRunner.Tests.check_dependencies')
84
@patch('AndroidRunner.Devices.Devices.__iter__')
85
@patch('AndroidRunner.Devices.Devices.__init__')
86
def test_init_only_device_config_restart(self, mock_devices, mock_devices_itter, mock_test, mock_prepare):
87
paths.OUTPUT_DIR = 'fake/path/name'
88
device_config = {'devices': 'fake_device'}
89
mock_devices_itter.return_value = ['dev1', 'dev2', 'dev3'].__iter__()
90
mock_devices.return_value = None
91
experiment = Experiment(device_config, None, True)
92
93
assert experiment.progress is None
94
assert experiment.basedir is None
95
assert experiment.random is False
96
assert isinstance(experiment.devices, Devices)
97
assert experiment.repetitions == 1
98
assert experiment.paths == []
99
assert isinstance(experiment.profilers, Profilers)
100
assert isinstance(experiment.scripts, Scripts)
101
assert experiment.reset_adb_among_runs is False
102
assert experiment.time_between_run == 0
103
assert experiment.clear_cache == False
104
assert experiment.output_root == paths.OUTPUT_DIR
105
assert experiment.result_file_structure is None
106
assert mock_prepare.call_count == 3
107
assert mock_prepare.mock_calls[0] == call('dev1', restart=True)
108
assert mock_prepare.mock_calls[1] == call('dev2', restart=True)
109
assert mock_prepare.mock_calls[2] == call('dev3', restart=True)
110
111
@patch('AndroidRunner.Experiment.Experiment.prepare_device')
112
@patch('AndroidRunner.Scripts.Scripts.__init__')
113
@patch('AndroidRunner.Experiment.Profilers')
114
@patch('AndroidRunner.Tests.check_dependencies')
115
@patch('AndroidRunner.Devices.Devices.__init__')
116
def test_init_full_config_no_restart(self, mock_devices, mock_test, mock_profilers,
117
mock_scripts, mock_prepare, test_config):
118
paths.OUTPUT_DIR = 'fake/path/name'
119
mock_devices.return_value = None
120
profiler_instance = MagicMock()
121
profiler_instance.dependencies.return_value = []
122
mock_profilers.return_value = profiler_instance
123
mock_scripts.return_value = None
124
mock_progress = Mock()
125
experiment = Experiment(test_config, mock_progress, False)
126
127
assert experiment.progress == mock_progress
128
assert experiment.basedir is None
129
assert experiment.random is True
130
assert isinstance(experiment.devices, Devices)
131
assert experiment.repetitions == 10
132
assert experiment.paths == ['test/paths/1', 'test/paths/2']
133
assert 'Profilers()' in str(experiment.profilers)
134
assert isinstance(experiment.scripts, Scripts)
135
assert experiment.reset_adb_among_runs is True
136
assert experiment.time_between_run == 10
137
assert experiment.clear_cache == True
138
assert experiment.output_root == paths.OUTPUT_DIR
139
assert experiment.result_file_structure is None
140
mock_devices.assert_called_once_with(['dev1', 'dev2'], adb_path='test_adb', devices_spec=None)
141
mock_profilers.assert_called_once_with({'fake': {'config1': 1, 'config2': 2}})
142
mock_test.assert_called_once_with(experiment.devices, [])
143
assert mock_prepare.call_count == 0
144
145
def test_prepare_device(self, default_experiment):
146
mock_profilers = Mock()
147
fake_device = Mock()
148
mock_manager = Mock()
149
mock_manager.mock_profilers = mock_profilers
150
mock_manager.fake_device = fake_device
151
default_experiment.profilers = mock_profilers
152
153
default_experiment.prepare_device(fake_device)
154
155
expected_calls = [call.mock_profilers.load(fake_device), call.fake_device.unplug(False)]
156
assert mock_manager.mock_calls == expected_calls
157
158
def test_cleanup(self, default_experiment):
159
mock_profilers = Mock()
160
fake_device = Mock()
161
mock_manager = Mock()
162
mock_manager.mock_profilers = mock_profilers
163
mock_manager.fake_device = fake_device
164
default_experiment.profilers = mock_profilers
165
166
default_experiment.cleanup(fake_device)
167
168
expected_calls = [call.fake_device.plug(), call.mock_profilers.stop_profiling(fake_device),
169
call.mock_profilers.unload(fake_device)]
170
assert mock_manager.mock_calls == expected_calls
171
172
def test_get_progress_xml_file(self, default_experiment):
173
xml_path = 'path/to/progress/xml.xml'
174
mock_progress = Mock()
175
mock_progress.progress_xml_file = xml_path
176
default_experiment.progress = mock_progress
177
assert default_experiment.get_progress_xml_file() == xml_path
178
179
def test_update_progress_empty_folder(self, default_experiment, tmpdir):
180
mock_progress = Mock()
181
default_experiment.progress = mock_progress
182
paths.BASE_OUTPUT_DIR = str(tmpdir)
183
makedirs(os.path.join(paths.BASE_OUTPUT_DIR, 'data'))
184
default_experiment.update_progress()
185
186
mock_progress.write_progress_to_file.assert_called_once()
187
result_walk_list = list(default_experiment.result_file_structure)
188
expected_walk_list = default_experiment.walk_to_list(os.walk(os.path.join(paths.BASE_OUTPUT_DIR, 'data')))
189
assert result_walk_list == expected_walk_list
190
191
def test_update_progress_non_empty_folder(self, default_experiment, tmpdir):
192
mock_progress = Mock()
193
default_experiment.progress = mock_progress
194
paths.BASE_OUTPUT_DIR = str(tmpdir)
195
folder_path = os.path.join(paths.BASE_OUTPUT_DIR, 'data', '1', '2')
196
makedirs(folder_path)
197
open(os.path.join(folder_path, "test.txt"), "w+")
198
default_experiment.update_progress()
199
200
mock_progress.write_progress_to_file.assert_called_once()
201
result_walk_list = list(default_experiment.result_file_structure)
202
expected_walk_list = default_experiment.walk_to_list(os.walk(os.path.join(paths.BASE_OUTPUT_DIR, 'data')))
203
assert result_walk_list == expected_walk_list
204
205
def test_walk_to_list(self, default_experiment, tmpdir):
206
paths.BASE_OUTPUT_DIR = str(tmpdir)
207
folder_path1 = os.path.join(paths.BASE_OUTPUT_DIR, 'data', '1', '1')
208
folder_path2 = os.path.join(paths.BASE_OUTPUT_DIR, 'data', '2', '1')
209
makedirs(folder_path1), makedirs(folder_path2)
210
open(os.path.join(folder_path1, "test.txt"), "w+")
211
open(os.path.join(folder_path2, "test.txt"), "w+")
212
213
walk_list = default_experiment.walk_to_list(os.walk(paths.BASE_OUTPUT_DIR))
214
print(walk_list)
215
assert len(walk_list) == 7
216
217
files = ['data/1/1/test.txt', 'data/2/1/test.txt']
218
flags = [False]*2
219
220
for item in walk_list:
221
for i, file in enumerate(files):
222
flags[i] |= file in item
223
224
assert(all(flags))
225
226
def test_check_result_files_correct(self, default_experiment, tmpdir):
227
paths.BASE_OUTPUT_DIR = str(tmpdir)
228
folder_path1 = os.path.join(paths.BASE_OUTPUT_DIR, 'data', '1', '1')
229
folder_path2 = os.path.join(paths.BASE_OUTPUT_DIR, 'data', '2', '1')
230
makedirs(folder_path1), makedirs(folder_path2)
231
open(os.path.join(folder_path1, "test.txt"), "w+")
232
open(os.path.join(folder_path2, "test.txt"), "w+")
233
correct_file_structure1 = os.walk(os.path.join(paths.BASE_OUTPUT_DIR, 'data'))
234
correct_file_structure2 = os.walk(os.path.join(paths.BASE_OUTPUT_DIR, 'data'))
235
236
default_experiment.check_result_files(correct_file_structure1)
237
238
current_file_structure = os.walk(os.path.join(paths.BASE_OUTPUT_DIR, 'data'))
239
240
assert list(current_file_structure) == list(correct_file_structure2)
241
242
def test_check_result_files_incorrect(self, default_experiment, tmpdir):
243
paths.BASE_OUTPUT_DIR = str(tmpdir)
244
folder_path1 = os.path.join(paths.BASE_OUTPUT_DIR, 'data', '1', '1')
245
folder_path2 = os.path.join(paths.BASE_OUTPUT_DIR, 'data', '2', '1')
246
folder_path3 = os.path.join(paths.BASE_OUTPUT_DIR, 'data', '3', '1')
247
makedirs(folder_path1), makedirs(folder_path2)
248
open(os.path.join(folder_path1, "test.txt"), "w+")
249
open(os.path.join(folder_path2, "test.txt"), "w+")
250
251
correct_file_structure_list1 = default_experiment.walk_to_list(
252
os.walk(os.path.join(paths.BASE_OUTPUT_DIR, 'data')))
253
correct_file_structure_list2 = list(os.walk(os.path.join(paths.BASE_OUTPUT_DIR, 'data')))
254
255
makedirs(folder_path3)
256
open(os.path.join(folder_path3, "test.txt"), "w+")
257
258
incorrect_file_structure_list = list(os.walk(os.path.join(paths.BASE_OUTPUT_DIR, 'data')))
259
assert not correct_file_structure_list2 == incorrect_file_structure_list
260
261
default_experiment.check_result_files(correct_file_structure_list1)
262
263
current_file_structure_list = list(os.walk(os.path.join(paths.BASE_OUTPUT_DIR, 'data')))
264
assert current_file_structure_list == correct_file_structure_list2
265
266
def test_get_experiment(self, default_experiment):
267
default_experiment.random = False
268
mock_progress = Mock()
269
get_next_run_mock = Mock()
270
mock_progress.get_next_run.return_value = get_next_run_mock
271
default_experiment.progress = mock_progress
272
273
assert default_experiment.get_experiment() == get_next_run_mock
274
275
def test_get_experiment_random(self, default_experiment):
276
default_experiment.random = True
277
mock_progress = Mock()
278
get_random_run_mock = Mock()
279
mock_progress.get_random_run.return_value = get_random_run_mock
280
default_experiment.progress = mock_progress
281
282
assert default_experiment.get_experiment() == get_random_run_mock
283
284
def test_stop_run_function_call_on_error(self, default_experiment):
285
default_experiment.run_stopping_condition_config = None
286
287
with pytest.raises(ConfigError):
288
default_experiment.stop_run()
289
290
def test_stop_run_function_success(self, default_experiment):
291
default_experiment.run_stopping_condition_config = {"post_request" : {}}
292
default_experiment.queue = Mock()
293
294
default_experiment.stop_run()
295
296
default_experiment.queue.put.assert_called_once_with(PrematureStoppableRun.STOPPING_MECHANISM_FUNCTION_CALL)
297
298
@patch('AndroidRunner.Experiment.Experiment.prepare_device')
299
@patch('AndroidRunner.Experiment.Experiment.before_experiment')
300
def test_first_run_device(self, before_experiment, prepare_device, default_experiment):
301
mock_progress = Mock()
302
mock_progress.device_first.return_value = True
303
default_experiment.progress = mock_progress
304
mock_devices = Mock()
305
mock_device = Mock()
306
mock_devices.get_device.return_value = mock_device
307
default_experiment.devices = mock_devices
308
fake_dict = {'device': 'fake_device'}
309
mock_manager = Mock()
310
mock_manager.attach_mock(before_experiment, "before_experiment_managed")
311
mock_manager.attach_mock(prepare_device, "prepare_device_managed")
312
313
default_experiment.first_run_device(fake_dict)
314
expected_calls = [call.prepare_device_managed(mock_device), call.before_experiment_managed(mock_device)]
315
assert mock_manager.mock_calls == expected_calls
316
317
@patch('AndroidRunner.Experiment.Experiment.before_run_subject')
318
def test_before_every_run_subject(self, before_run_subject, default_experiment):
319
mock_devices = Mock()
320
mock_device = Mock()
321
mock_devices.get_device.return_value = mock_device
322
default_experiment.devices = mock_devices
323
fake_dict = {'device': 'fake_device', 'path': 'test/path'}
324
325
default_experiment.before_every_run_subject(fake_dict)
326
327
before_run_subject.assert_called_once_with(mock_device, fake_dict['path'])
328
329
@patch('AndroidRunner.Experiment.Experiment.after_experiment')
330
def test_last_run_device_false(self, after_experiment, default_experiment):
331
mock_progress = Mock()
332
mock_progress.device_finished.return_value = False
333
default_experiment.progress = mock_progress
334
fake_dict = {'device': 'fake_device'}
335
336
default_experiment.last_run_device(fake_dict)
337
338
assert after_experiment.call_count == 0
339
340
@patch('AndroidRunner.Experiment.Experiment.after_experiment')
341
def test_last_run_device_true(self, after_experiment, default_experiment):
342
mock_progress = Mock()
343
mock_progress.device_finished.return_value = True
344
default_experiment.progress = mock_progress
345
fake_dict = {'device': 'fake_device'}
346
mock_devices = Mock()
347
mock_device = Mock()
348
mock_devices.get_device.return_value = mock_device
349
default_experiment.devices = mock_devices
350
351
default_experiment.last_run_device(fake_dict)
352
353
after_experiment.assert_called_once_with(mock_device)
354
355
@patch('AndroidRunner.Experiment.Experiment.after_last_run')
356
@patch('AndroidRunner.Experiment.Experiment.aggregate_subject')
357
def test_last_run_false(self, aggregate_subject, after_last_run, default_experiment):
358
mock_progress = Mock()
359
mock_progress.subject_finished.return_value = False
360
default_experiment.progress = mock_progress
361
fake_dict = {'device': 'fake_device', 'path': 'test/path'}
362
363
default_experiment.last_run_subject(fake_dict)
364
365
assert after_last_run.call_count == 0
366
assert aggregate_subject.call_count == 0
367
368
@patch('AndroidRunner.Experiment.Experiment.after_last_run')
369
@patch('AndroidRunner.Experiment.Experiment.aggregate_subject')
370
def test_last_run_true(self, aggregate_subject, after_last_run, default_experiment):
371
mock_progress = Mock()
372
mock_progress.subject_finished.return_value = True
373
default_experiment.progress = mock_progress
374
fake_dict = {'device': 'fake_device', 'path': 'test/path'}
375
mock_devices = Mock()
376
mock_device = Mock()
377
mock_devices.get_device.return_value = mock_device
378
default_experiment.devices = mock_devices
379
380
default_experiment.last_run_subject(fake_dict)
381
382
after_last_run.assert_called_once_with(mock_device, fake_dict['path'])
383
aggregate_subject.assert_called_once()
384
385
def test_prepare_output_dir(self, tmpdir, default_experiment):
386
paths.BASE_OUTPUT_DIR = str(tmpdir)
387
fake_dict = {'device': 'fake_device', 'path': 'fake_path'}
388
389
default_experiment.prepare_output_dir(fake_dict)
390
391
assert os.path.isdir(paths.OUTPUT_DIR)
392
assert paths.OUTPUT_DIR == os.path.join(paths.BASE_OUTPUT_DIR, 'data', 'fake_device', 'fake_path')
393
394
@patch('AndroidRunner.Experiment.Experiment.after_run')
395
@patch('AndroidRunner.Experiment.Experiment.stop_profiling')
396
@patch('AndroidRunner.Experiment.Experiment.interaction')
397
@patch('AndroidRunner.Experiment.Experiment.start_profiling')
398
@patch('AndroidRunner.Experiment.Experiment.before_run')
399
def test_run(self, before_run, start_profiling, interaction, stop_profiling, after_run, default_experiment):
400
mock_device = Mock()
401
path = "test/path"
402
run = 123456789
403
mock_manager = Mock()
404
mock_manager.attach_mock(before_run, "before_run_managed")
405
mock_manager.attach_mock(start_profiling, "start_profiling_managed")
406
mock_manager.attach_mock(interaction, "interaction_managed")
407
mock_manager.attach_mock(stop_profiling, "stop_profiling_managed")
408
mock_manager.attach_mock(after_run, "after_run_managed")
409
410
default_experiment.run(mock_device, path, run, None)
411
412
expected_calls = [call.before_run_managed(mock_device, path, run, current_run=None),
413
call.start_profiling_managed(mock_device, path, run),
414
call.interaction_managed(mock_device, path, run, current_run=None),
415
call.stop_profiling_managed(mock_device, path, run),
416
call.after_run_managed(mock_device, path, run)]
417
assert mock_manager.mock_calls == expected_calls
418
419
@patch('AndroidRunner.Experiment.Experiment.after_run')
420
@patch('AndroidRunner.Experiment.Experiment.stop_profiling')
421
@patch('AndroidRunner.Experiment.Experiment.interaction')
422
@patch('AndroidRunner.Experiment.Experiment.start_profiling')
423
@patch('AndroidRunner.Experiment.Experiment.before_run')
424
@patch('AndroidRunner.PrematureStoppableRun.PrematureStoppableRun.__init__')
425
@patch('AndroidRunner.PrematureStoppableRun.PrematureStoppableRun.run')
426
@patch('multiprocessing.Queue')
427
def test_premature_stoppable_run(self, queue, premature_stoppable_run_run, premature_stoppable_run_init, before_run, start_profiling, interaction, stop_profiling, after_run,
428
default_experiment):
429
premature_stoppable_run_init.return_value = None
430
mock_device = Mock()
431
path = "test/path"
432
run = 123456789
433
run_stopping_condition_config = {"post_request" : {}}
434
default_experiment.run_stopping_condition_config = run_stopping_condition_config
435
default_experiment.queue = queue
436
437
queue_value = None
438
queue.return_value = queue_value
439
440
mock_manager = Mock()
441
mock_manager.attach_mock(before_run, "before_run_managed")
442
mock_manager.attach_mock(start_profiling, "start_profiling_managed")
443
mock_manager.attach_mock(premature_stoppable_run_init, "premature_stoppable_run_init")
444
mock_manager.attach_mock(premature_stoppable_run_run, "premature_stoppable_run_run")
445
mock_manager.attach_mock(stop_profiling, "stop_profiling_managed")
446
mock_manager.attach_mock(after_run, "after_run_managed")
447
448
default_experiment.run(mock_device, path, run, None)
449
450
expected_calls = [call.before_run_managed(mock_device, path, run, current_run=None),
451
call.start_profiling_managed(mock_device, path, run),
452
call.premature_stoppable_run_init(run_stopping_condition_config, queue_value, interaction, mock_device, path, run),
453
call.premature_stoppable_run_run(),
454
call.stop_profiling_managed(mock_device, path, run),
455
call.after_run_managed(mock_device, path, run)]
456
assert mock_manager.mock_calls == expected_calls
457
458
@patch('AndroidRunner.Scripts.Scripts.run')
459
def test_before_experiment(self, run_script_mock, default_experiment):
460
args = (1, 2, 3)
461
kwargs = {'arg1': 1, 'arg2': 2}
462
mock_device = Mock()
463
464
default_experiment.before_experiment(mock_device, *args, **kwargs)
465
466
run_script_mock.assert_called_once_with('before_experiment', mock_device, *args, **kwargs)
467
468
def test_before_first_run(self, default_experiment):
469
args = (1, 2, 3)
470
kwargs = {'arg1': 1, 'arg2': 2}
471
mock_device = Mock()
472
path = 'test/path'
473
474
default_experiment.before_run_subject(mock_device, path, *args, **kwargs)
475
476
@patch('AndroidRunner.Profilers.Profilers.set_output')
477
@patch('AndroidRunner.Scripts.Scripts.run')
478
def test_before_run(self, script_run, set_output, default_experiment):
479
args = (1, 2, 3)
480
kwargs = {'arg1': 1, 'arg2': 2}
481
mock_device = Mock()
482
path = 'test/path'
483
run = 1234566789
484
mock_manager = Mock()
485
mock_manager.attach_mock(set_output, 'set_output_managed')
486
mock_manager.attach_mock(mock_device, 'mock_device_managed')
487
mock_manager.attach_mock(script_run, 'script_run_managed')
488
default_experiment.before_run(mock_device, path, run, *args, **kwargs)
489
490
expected_calls = [call.set_output_managed(),
491
call.mock_device_managed.shell('logcat -c'),
492
call.script_run_managed('before_run', mock_device, *args, **kwargs)]
493
assert mock_manager.mock_calls == expected_calls
494
495
@patch('AndroidRunner.Scripts.Scripts.run')
496
def test_after_launch(self, script_run, default_experiment):
497
args = (1, 2, 3)
498
kwargs = {'arg1': 1, 'arg2': 2}
499
mock_device = Mock()
500
mock_device.id = 123
501
current_activity = FakeDevice.current_activity()
502
mock_device.current_activity.return_value = current_activity
503
path = 'test/path'
504
run = 1234566789
505
506
default_experiment.after_launch(mock_device, path, run, *args, **kwargs)
507
508
script_run.assert_called_once_with('after_launch', mock_device, 123, current_activity, *args, **kwargs)
509
510
@patch('AndroidRunner.Profilers.Profilers.start_profiling')
511
def test_start_profiling(self, start_profiling, default_experiment):
512
args = (1, 2, 3)
513
kwargs = {'arg1': 1, 'arg2': 2}
514
mock_device = Mock()
515
path = 'test/path'
516
run = 1234566789
517
518
default_experiment.start_profiling(mock_device, path, run, *args, **kwargs)
519
520
start_profiling.assert_called_once_with(mock_device, **kwargs)
521
522
@patch('AndroidRunner.Scripts.Scripts.run')
523
def test_interaction(self, script_run, default_experiment):
524
args = (1, 2, 3)
525
kwargs = {'arg1': 1, 'arg2': 2}
526
mock_device = Mock()
527
path = 'test/path'
528
run = 1234566789
529
530
default_experiment.interaction(mock_device, path, run, *args, **kwargs)
531
532
script_run.assert_called_once_with('interaction', mock_device, default_experiment, *args, **kwargs)
533
534
@patch('AndroidRunner.Profilers.Profilers.stop_profiling')
535
def test_stop_profiling(self, start_profiling, default_experiment):
536
args = (1, 2, 3)
537
kwargs = {'arg1': 1, 'arg2': 2}
538
mock_device = Mock()
539
path = 'test/path'
540
run = 1234566789
541
542
default_experiment.stop_profiling(mock_device, path, run, *args, **kwargs)
543
544
start_profiling.assert_called_once_with(mock_device, **kwargs)
545
546
@patch('AndroidRunner.Scripts.Scripts.run')
547
def test_before_close(self, script_run, default_experiment):
548
args = (1, 2, 3)
549
kwargs = {'arg1': 1, 'arg2': 2}
550
mock_device = Mock()
551
mock_device.id = 123
552
current_activity = FakeDevice.current_activity()
553
mock_device.current_activity.return_value = current_activity
554
path = 'test/path'
555
run = 1234566789
556
557
default_experiment.before_close(mock_device, path, run, *args, **kwargs)
558
559
script_run.assert_called_once_with('before_close', mock_device, 123, current_activity, *args, **kwargs)
560
561
@patch('time.sleep')
562
@patch('AndroidRunner.Adb.reset')
563
@patch('AndroidRunner.Profilers.Profilers.collect_results')
564
@patch('AndroidRunner.Scripts.Scripts.run')
565
def test_after_run(self, script_run, collect_results, reset, sleep, default_experiment):
566
args = (1, 2, 3)
567
kwargs = {'arg1': 1, 'arg2': 2}
568
mock_device = Mock()
569
path = 'test/path'
570
run = 1234566789
571
default_experiment.reset_adb_among_runs = True
572
default_experiment.time_between_run = 2000
573
mock_manager = Mock()
574
mock_manager.attach_mock(script_run, "script_run_managed")
575
mock_manager.attach_mock(collect_results, "collect_results_managed")
576
mock_manager.attach_mock(reset, "reset_managed")
577
mock_manager.attach_mock(sleep, "sleep_managed")
578
default_experiment.after_run(mock_device, path, run, *args, **kwargs)
579
580
expected_calls = [call.script_run_managed('after_run', mock_device, *args, **kwargs),
581
call.collect_results_managed(mock_device),
582
call.reset_managed(True),
583
call.sleep_managed(2)
584
]
585
assert mock_manager.mock_calls == expected_calls
586
587
def test_after_last_run(self, default_experiment):
588
args = (1, 2, 3)
589
kwargs = {'arg1': 1, 'arg2': 2}
590
mock_device = Mock()
591
path = 'test/path'
592
593
default_experiment.after_last_run(mock_device, path, *args, **kwargs)
594
595
@patch('AndroidRunner.Scripts.Scripts.run')
596
def test_after_experiment(self, script_run, default_experiment):
597
args = (1, 2, 3)
598
kwargs = {'arg1': 1, 'arg2': 2}
599
mock_device = Mock()
600
601
default_experiment.after_experiment(mock_device, *args, **kwargs)
602
603
script_run.assert_called_once_with('after_experiment', mock_device, *args, **kwargs)
604
605
@patch('AndroidRunner.Profilers.Profilers.aggregate_subject')
606
def test_aggregate_subject(self, aggregate_subject, default_experiment):
607
default_experiment.aggregate_subject()
608
609
aggregate_subject.assert_called_once()
610
611
@patch('AndroidRunner.Profilers.Profilers.aggregate_end')
612
def test_aggregate_end(self, aggregate_end, default_experiment, tmpdir):
613
default_experiment.output_root = str(tmpdir)
614
615
default_experiment.aggregate_end()
616
617
aggregate_end.assert_called_once_with(default_experiment.output_root)
618
619
@patch('AndroidRunner.Experiment.Experiment.aggregate_end')
620
@patch('AndroidRunner.Experiment.Experiment.cleanup')
621
@patch('AndroidRunner.Experiment.Experiment.check_result_files')
622
def test_finish_experiment_regular_no_devices(self, check_result_files, cleanup, aggregate_end, default_experiment):
623
fake_file_structure = 'test_structure'
624
default_experiment.result_file_structure = fake_file_structure
625
default_experiment.devices = []
626
mock_manager = Mock()
627
mock_manager.attach_mock(check_result_files, "check_result_files_managed")
628
mock_manager.attach_mock(aggregate_end, "aggregate_end_managed")
629
630
default_experiment.finish_experiment(False, False)
631
632
expected_calls = [call.check_result_files_managed(fake_file_structure),
633
call.aggregate_end_managed()]
634
assert mock_manager.mock_calls == expected_calls
635
assert cleanup.call_count == 0
636
637
@patch('AndroidRunner.Experiment.Experiment.aggregate_end')
638
@patch('AndroidRunner.Experiment.Experiment.cleanup')
639
@patch('AndroidRunner.Experiment.Experiment.check_result_files')
640
def test_finish_experiment_regular_multiple_devices(self, check_result_files, cleanup, aggregate_end,
641
default_experiment):
642
fake_file_structure = 'test_structure'
643
default_experiment.result_file_structure = fake_file_structure
644
default_experiment.devices = ['1', '2', '3']
645
mock_manager = Mock()
646
mock_manager.attach_mock(check_result_files, "check_result_files_managed")
647
mock_manager.attach_mock(aggregate_end, "aggregate_end_managed")
648
mock_manager.attach_mock(cleanup, "cleanup_managed")
649
650
default_experiment.finish_experiment(False, False)
651
652
expected_calls = [call.check_result_files_managed(fake_file_structure),
653
call.cleanup_managed('1'),
654
call.cleanup_managed('2'),
655
call.cleanup_managed('3'),
656
call.aggregate_end_managed()]
657
assert mock_manager.mock_calls == expected_calls
658
659
@patch('AndroidRunner.Experiment.Experiment.aggregate_end')
660
@patch('AndroidRunner.Experiment.Experiment.cleanup')
661
@patch('AndroidRunner.Experiment.Experiment.check_result_files')
662
def test_finish_experiment_error(self, check_result_files, cleanup, aggregate_end, default_experiment):
663
fake_file_structure = 'test_structure'
664
default_experiment.devices = ['1']
665
default_experiment.result_file_structure = fake_file_structure
666
default_experiment.finish_experiment(True, False)
667
668
check_result_files.assert_called_once_with(fake_file_structure)
669
cleanup.assert_called_once_with('1')
670
assert aggregate_end.call_count == 0
671
672
@patch('AndroidRunner.Experiment.Experiment.aggregate_end')
673
@patch('AndroidRunner.Experiment.Experiment.cleanup')
674
@patch('AndroidRunner.Experiment.Experiment.check_result_files')
675
def test_finish_experiment_interrupted(self, check_result_files, cleanup, aggregate_end, default_experiment):
676
fake_file_structure = 'test_structure'
677
default_experiment.devices = ['1']
678
default_experiment.result_file_structure = fake_file_structure
679
680
default_experiment.finish_experiment(False, True)
681
682
check_result_files.assert_called_once_with(fake_file_structure)
683
cleanup.assert_called_once_with('1')
684
assert aggregate_end.call_count == 0
685
686
@patch('AndroidRunner.Experiment.Experiment.aggregate_end')
687
@patch('AndroidRunner.Experiment.Experiment.cleanup')
688
@patch('AndroidRunner.Experiment.Experiment.check_result_files')
689
def test_finish_experiment_error_in_cleanup(self, check_result_files, cleanup, aggregate_end, default_experiment):
690
fake_file_structure = 'test_structure'
691
default_experiment.devices = ['1']
692
default_experiment.result_file_structure = fake_file_structure
693
cleanup.side_effect = Exception
694
default_experiment.finish_experiment(True, False)
695
check_result_files.assert_called_once_with(fake_file_structure)
696
cleanup.assert_called_once_with('1')
697
assert aggregate_end.call_count == 0
698
699
@patch('AndroidRunner.Experiment.Experiment.finish_run')
700
@patch('AndroidRunner.Experiment.Experiment.run_run')
701
@patch('AndroidRunner.Experiment.Experiment.prepare_run')
702
def test_run_experiment(self, prepare_run, run_run, finish_run, default_experiment):
703
test_run = Mock()
704
mock_manager = Mock()
705
mock_manager.attach_mock(prepare_run, "prepare_run_managed")
706
mock_manager.attach_mock(run_run, "run_run_managed")
707
mock_manager.attach_mock(finish_run, "finish_run_managed")
708
709
default_experiment.run_experiment(test_run)
710
711
expected_calls = [call.prepare_run_managed(test_run),
712
call.run_run_managed(test_run),
713
call.finish_run_managed(test_run)]
714
assert mock_manager.mock_calls == expected_calls
715
716
@patch('AndroidRunner.Experiment.Experiment.prepare_output_dir')
717
@patch('AndroidRunner.Experiment.Experiment.first_run_device')
718
@patch('AndroidRunner.Experiment.Experiment.before_every_run_subject')
719
def test_prepare_run(self, before_every_run_subject, first_run_device, prepare_output_dir, default_experiment):
720
test_run = Mock()
721
mock_manager = Mock()
722
mock_manager.attach_mock(before_every_run_subject, "before_every_run_subject_managed")
723
mock_manager.attach_mock(first_run_device, "first_run_device_managed")
724
mock_manager.attach_mock(prepare_output_dir, "prepare_output_dir_managed")
725
726
default_experiment.prepare_run(test_run)
727
728
expected_calls = [call.prepare_output_dir_managed(test_run),
729
call.first_run_device_managed(test_run),
730
call.before_every_run_subject_managed(test_run)]
731
assert mock_manager.mock_calls == expected_calls
732
733
@patch('AndroidRunner.Experiment.Experiment.run')
734
def test_run_run_w_browser(self, run, default_experiment):
735
mock_device = Mock()
736
mock_devices = Mock()
737
mock_devices.get_device.return_value = mock_device
738
default_experiment.devices = mock_devices
739
test_run = {'device': 'test_device', 'path': 'test_path', 'runCount': '123', 'browser': 'test_browser'}
740
default_experiment.run_run(test_run)
741
742
run.assert_called_once_with(mock_device, test_run['path'], int(test_run['runCount']), test_run, browser=test_run['browser'])
743
744
@patch('AndroidRunner.Experiment.Experiment.run')
745
def test_run_run_wo_browser(self, run, default_experiment):
746
mock_device = Mock()
747
mock_devices = Mock()
748
mock_devices.get_device.return_value = mock_device
749
default_experiment.devices = mock_devices
750
test_run = {'device': 'test_device', 'path': 'test_path', 'runCount': '123'}
751
default_experiment.run_run(test_run)
752
753
run.assert_called_once_with(mock_device, test_run['path'], int(test_run['runCount']), test_run)
754
755
@patch('AndroidRunner.Experiment.Experiment.last_run_device')
756
@patch('AndroidRunner.Experiment.Experiment.last_run_subject')
757
def test_finish_run(self, last_run_subject, last_run_device, default_experiment):
758
mock_progres = Mock()
759
default_experiment.progress = mock_progres
760
test_run = {'device': 'test_device', 'path': 'test_path', 'runId': '123'}
761
mock_manager = Mock()
762
mock_manager.attach_mock(mock_progres, "mock_progres_managed")
763
mock_manager.attach_mock(last_run_subject, "last_run_managed")
764
mock_manager.attach_mock(last_run_device, "last_run_device_managed")
765
766
default_experiment.finish_run(test_run)
767
768
expected_calls = [call.mock_progres_managed.run_finished(test_run['runId']),
769
call.last_run_managed(test_run),
770
call.last_run_device_managed(test_run)]
771
assert mock_manager.mock_calls == expected_calls
772
773
@patch('threading.Thread.join')
774
@patch('threading.Thread.start')
775
@patch('threading.Thread.__init__')
776
def test_save_progress(self, mock_threading_init, mock_threading_start, mock_threading_join, default_experiment):
777
mock_threading_init.return_value = None
778
mock_manager = Mock()
779
mock_manager.attach_mock(mock_threading_init, "mock_threading_init_managed")
780
mock_manager.attach_mock(mock_threading_start, "mock_threading_start_managed")
781
mock_manager.attach_mock(mock_threading_join, "mock_threading_join_managed")
782
783
default_experiment.save_progress()
784
785
expected_calls = [call.mock_threading_init_managed(target=default_experiment.update_progress),
786
call.mock_threading_start_managed(),
787
call.mock_threading_join_managed()]
788
assert mock_manager.mock_calls == expected_calls
789
790
@patch('AndroidRunner.Experiment.Experiment.finish_experiment')
791
def test_start_error(self, finish_experiment_mock, capsys, default_experiment):
792
mock_logger = Mock()
793
default_experiment.logger = mock_logger
794
paths.BASE_OUTPUT_DIR = None # raises TypeError
795
796
with pytest.raises(Exception):
797
default_experiment.start()
798
captured = capsys.readouterr() # Catch std out
799
finish_experiment_mock.assert_called_once_with(True, False)
800
mock_logger.error.assert_called_once_with("TypeError: expected str, bytes or os.PathLike object, not NoneType")
801
802
@patch("AndroidRunner.Experiment.Experiment.walk_to_list")
803
@patch('AndroidRunner.Experiment.Experiment.finish_experiment')
804
def test_start_interupt(self, finish_experiment_mock, walk_to_list_mock, default_experiment):
805
paths.BASE_OUTPUT_DIR = "test"
806
walk_to_list_mock.side_effect = KeyboardInterrupt
807
with pytest.raises(KeyboardInterrupt):
808
default_experiment.start()
809
finish_experiment_mock.assert_called_once_with(False, True)
810
811
@patch("AndroidRunner.Experiment.walk")
812
@patch("AndroidRunner.Experiment.Experiment.get_experiment")
813
@patch('AndroidRunner.Experiment.Experiment.run_experiment')
814
@patch('AndroidRunner.Experiment.Experiment.save_progress')
815
@patch("AndroidRunner.Experiment.Experiment.walk_to_list")
816
@patch('AndroidRunner.Experiment.Experiment.finish_experiment')
817
def test_start_experiment_finished(self, finish_experiment_mock, walk_to_list_mock, save_progress_mock,
818
run_experiment_mock, get_experiment_mock, walk_mock, default_experiment):
819
paths.BASE_OUTPUT_DIR = "test"
820
mock_walk_to_list_result = Mock()
821
walk_to_list_mock.return_value = mock_walk_to_list_result
822
mock_walk_result = Mock()
823
walk_mock.return_value = mock_walk_result
824
mock_progress = Mock()
825
mock_progress.experiment_finished_check.return_value = True
826
default_experiment.progress = mock_progress
827
828
default_experiment.start()
829
830
assert get_experiment_mock.call_count == run_experiment_mock.call_count == save_progress_mock.call_count == 0
831
walk_to_list_mock.assert_called_once_with(mock_walk_result)
832
finish_experiment_mock.assert_called_once_with(False, False)
833
834
@patch("AndroidRunner.Experiment.walk")
835
@patch("AndroidRunner.Experiment.Experiment.get_experiment")
836
@patch('AndroidRunner.Experiment.Experiment.run_experiment')
837
@patch('AndroidRunner.Experiment.Experiment.save_progress')
838
@patch("AndroidRunner.Experiment.Experiment.walk_to_list")
839
@patch('AndroidRunner.Experiment.Experiment.finish_experiment')
840
def test_start_experiment_one_run(self, finish_experiment_mock, walk_to_list_mock, save_progress_mock,
841
run_experiment_mock, get_experiment_mock, walk_mock, default_experiment):
842
paths.BASE_OUTPUT_DIR = "test"
843
mock_walk_to_list_result = Mock()
844
walk_to_list_mock.return_value = mock_walk_to_list_result
845
mock_walk_result = Mock()
846
walk_mock.return_value = mock_walk_result
847
mock_progress = Mock()
848
mock_progress.experiment_finished_check.side_effect = [False, True]
849
default_experiment.progress = mock_progress
850
mock_get_experiment_result = Mock()
851
get_experiment_mock.return_value = mock_get_experiment_result
852
mock_manager = Mock()
853
mock_manager.attach_mock(walk_mock, 'walk_mock_managed')
854
mock_manager.attach_mock(walk_to_list_mock, 'walk_to_list_managed')
855
mock_manager.attach_mock(mock_progress, 'mock_progress_managed')
856
mock_manager.attach_mock(get_experiment_mock, 'get_experiment_managed')
857
mock_manager.attach_mock(run_experiment_mock, 'run_experiment_managed')
858
mock_manager.attach_mock(save_progress_mock, 'save_progress_managed')
859
mock_manager.attach_mock(finish_experiment_mock, 'finish_experiment_managed')
860
861
default_experiment.start()
862
expected_calls = [call.walk_mock_managed(os.path.join('test', 'data')),
863
call.walk_to_list_managed(mock_walk_result),
864
call.mock_progress_managed.experiment_finished_check(),
865
call.get_experiment_managed(),
866
call.run_experiment_managed(mock_get_experiment_result),
867
call.save_progress_managed(),
868
call.mock_progress_managed.experiment_finished_check(),
869
call.finish_experiment_managed(False, False)]
870
assert mock_manager.mock_calls == expected_calls
871
872
@patch("AndroidRunner.Experiment.walk")
873
@patch("AndroidRunner.Experiment.Experiment.get_experiment")
874
@patch('AndroidRunner.Experiment.Experiment.run_experiment')
875
@patch('AndroidRunner.Experiment.Experiment.save_progress')
876
@patch("AndroidRunner.Experiment.Experiment.walk_to_list")
877
@patch('AndroidRunner.Experiment.Experiment.finish_experiment')
878
def test_start_experiment_multiple_runs(self, finish_experiment_mock, walk_to_list_mock, save_progress_mock,
879
run_experiment_mock, get_experiment_mock, walk_mock, default_experiment):
880
paths.BASE_OUTPUT_DIR = "test"
881
mock_walk_to_list_result = Mock()
882
walk_to_list_mock.return_value = mock_walk_to_list_result
883
mock_walk_result = Mock()
884
walk_mock.return_value = mock_walk_result
885
mock_progress = Mock()
886
mock_progress.experiment_finished_check.side_effect = [False] * 9 + [True]
887
default_experiment.progress = mock_progress
888
mock_get_experiment_result = Mock()
889
get_experiment_mock.return_value = mock_get_experiment_result
890
891
default_experiment.start()
892
893
assert get_experiment_mock.call_count == run_experiment_mock.call_count == save_progress_mock.call_count == 9
894
895
896
class TestWebExperiment(object):
897
@pytest.fixture()
898
@patch('AndroidRunner.Tests.check_dependencies')
899
@patch('AndroidRunner.Devices.Devices.__init__')
900
def web_experiment(self, device, check_dependencies):
901
check_dependencies.return_value = None
902
device.return_value = None
903
device_config = {'devices': 'fake_device'}
904
return WebExperiment(device_config, None, False)
905
906
@patch('AndroidRunner.Browsers.Browser')
907
@patch('AndroidRunner.BrowserFactory.BrowserFactory.get_browser')
908
@patch('AndroidRunner.Tests.check_dependencies')
909
@patch('AndroidRunner.Devices.Devices.__init__')
910
def test_init_empty_config(self, device, check_dependencies, get_browser, mock_browser):
911
get_browser.return_value = mock_browser
912
913
device.return_value = None
914
device_config = {'devices': 'fake_device'}
915
web_experiment = WebExperiment(device_config, None, False)
916
917
assert check_dependencies.call_count == 2
918
assert web_experiment.duration == 0
919
get_browser.assert_called_once_with('chrome')
920
mock_browser.assert_called_once_with()
921
922
@patch('AndroidRunner.BrowserFactory.BrowserFactory.get_browser')
923
@patch('AndroidRunner.Tests.check_dependencies')
924
@patch('AndroidRunner.Devices.Devices.__init__')
925
def test_init_nom_empty_config(self, device, check_dependencies, get_browser):
926
device.return_value = None
927
device_config = {'devices': 'fake_device', 'browsers': ['firefox', 'opera'], 'duration': 1000}
928
web_experiment = WebExperiment(device_config, None, False)
929
930
assert check_dependencies.call_count == 2
931
assert web_experiment.duration == 1
932
assert len(web_experiment.browsers) == 2
933
expected_calls = [call('firefox'), call()(), call('opera'), call()()]
934
assert get_browser.mock_calls == expected_calls
935
936
@patch('AndroidRunner.WebExperiment.WebExperiment.after_run')
937
@patch('AndroidRunner.WebExperiment.WebExperiment.before_close')
938
@patch('AndroidRunner.WebExperiment.WebExperiment.stop_profiling')
939
@patch('AndroidRunner.WebExperiment.WebExperiment.interaction')
940
@patch('AndroidRunner.WebExperiment.WebExperiment.start_profiling')
941
@patch('AndroidRunner.WebExperiment.WebExperiment.after_launch')
942
@patch('AndroidRunner.WebExperiment.WebExperiment.before_run')
943
def test_run(self, before_run, after_launch, start_profiling, interaction, stop_profiling, before_close, after_run,
944
web_experiment):
945
mock_device = Mock()
946
mock_device.get_version.return_value = "10"
947
path = "test/path"
948
run = 123456789
949
mock_browser = Mock()
950
mock_browser.to_string.return_value = 'chrome'
951
web_experiment.browsers = [mock_browser]
952
web_experiment.run(mock_device, path, run, 'chrome')
953
954
kwargs = {
955
"browser": mock_browser,
956
"app": mock_browser.package_name
957
}
958
959
mock_manager = Mock()
960
mock_manager.attach_mock(before_run, "before_run_managed")
961
mock_manager.attach_mock(after_launch, "after_launch_managed")
962
mock_manager.attach_mock(start_profiling, "start_profiling_managed")
963
mock_manager.attach_mock(interaction, "interaction_managed")
964
mock_manager.attach_mock(stop_profiling, "stop_profiling_managed")
965
mock_manager.attach_mock(before_close, "before_close_managed")
966
mock_manager.attach_mock(after_run, "after_run_managed")
967
968
web_experiment.run(mock_device, path, run, 'chrome')
969
970
expected_calls = [call.before_run_managed(mock_device, path, run, **kwargs),
971
call.after_launch_managed(mock_device, path, run, **kwargs),
972
call.start_profiling_managed(mock_device, path, run, **kwargs),
973
call.interaction_managed(mock_device, path, run, **kwargs),
974
call.stop_profiling_managed(mock_device, path, run, **kwargs),
975
call.before_close_managed(mock_device, path, run, **kwargs),
976
call.after_run_managed(mock_device, path, run, **kwargs)]
977
assert mock_manager.mock_calls == expected_calls
978
979
@patch('AndroidRunner.WebExperiment.WebExperiment.after_run')
980
@patch('AndroidRunner.WebExperiment.WebExperiment.before_close')
981
@patch('AndroidRunner.WebExperiment.WebExperiment.stop_profiling')
982
@patch('AndroidRunner.WebExperiment.WebExperiment.interaction')
983
@patch('AndroidRunner.WebExperiment.WebExperiment.start_profiling')
984
@patch('AndroidRunner.WebExperiment.WebExperiment.after_launch')
985
@patch('AndroidRunner.WebExperiment.WebExperiment.before_run')
986
@patch('AndroidRunner.PrematureStoppableRun.PrematureStoppableRun.__init__')
987
@patch('AndroidRunner.PrematureStoppableRun.PrematureStoppableRun.run')
988
@patch('multiprocessing.Queue')
989
def test_premature_stoppable_run(self, queue, premature_stoppable_run_run, premature_stoppable_run_init, before_run, after_launch, start_profiling, interaction, stop_profiling, before_close, after_run,
990
web_experiment):
991
premature_stoppable_run_init.return_value = None
992
mock_device = Mock()
993
mock_device.get_version.return_value = "10"
994
path = "test/path"
995
run = 123456789
996
run_stopping_condition_config = {"post_request" : {}}
997
mock_browser = Mock()
998
mock_browser.to_string.return_value = 'chrome'
999
web_experiment.browsers = [mock_browser]
1000
web_experiment.run_stopping_condition_config = run_stopping_condition_config
1001
web_experiment.queue = queue
1002
1003
kwargs = {
1004
'browser': mock_browser,
1005
'app': mock_browser.package_name
1006
}
1007
1008
queue_value = None
1009
queue.return_value = queue_value
1010
1011
mock_manager = Mock()
1012
mock_manager.attach_mock(before_run, "before_run_managed")
1013
mock_manager.attach_mock(after_launch, "after_launch_managed")
1014
mock_manager.attach_mock(start_profiling, "start_profiling_managed")
1015
mock_manager.attach_mock(premature_stoppable_run_init, "premature_stoppable_run_init")
1016
mock_manager.attach_mock(premature_stoppable_run_run, "premature_stoppable_run_run")
1017
mock_manager.attach_mock(stop_profiling, "stop_profiling_managed")
1018
mock_manager.attach_mock(before_close, "before_close_managed")
1019
mock_manager.attach_mock(after_run, "after_run_managed")
1020
1021
web_experiment.run(mock_device, path, run, 'chrome')
1022
1023
expected_calls = [call.before_run_managed(mock_device, path, run, **kwargs),
1024
call.after_launch_managed(mock_device, path, run, **kwargs),
1025
call.start_profiling_managed(mock_device, path, run, **kwargs),
1026
call.premature_stoppable_run_init(run_stopping_condition_config, queue_value, interaction, mock_device, path, run, **kwargs),
1027
call.premature_stoppable_run_run(),
1028
call.stop_profiling_managed(mock_device, path, run, **kwargs),
1029
call.before_close_managed(mock_device, path, run, **kwargs),
1030
call.after_run_managed(mock_device, path, run, **kwargs)]
1031
assert mock_manager.mock_calls == expected_calls
1032
1033
@patch('AndroidRunner.WebExperiment.WebExperiment.after_last_run')
1034
@patch('AndroidRunner.WebExperiment.WebExperiment.aggregate_subject')
1035
def test_last_run_false(self, aggregate_subject, after_last_run, web_experiment):
1036
mock_progress = Mock()
1037
mock_progress.subject_finished.return_value = False
1038
web_experiment.progress = mock_progress
1039
fake_dict = {'device': 'fake_device', 'path': 'test/path', 'browser': 'fake_browser'}
1040
1041
web_experiment.last_run_subject(fake_dict)
1042
1043
mock_progress.subject_finished.assert_called_once_with(fake_dict['device'], fake_dict['path'],
1044
fake_dict['browser'])
1045
assert after_last_run.call_count == 0
1046
assert aggregate_subject.call_count == 0
1047
1048
@patch('AndroidRunner.WebExperiment.WebExperiment.after_last_run')
1049
@patch('AndroidRunner.WebExperiment.WebExperiment.aggregate_subject')
1050
def test_last_run_true(self, aggregate_subject, after_last_run, web_experiment):
1051
mock_progress = Mock()
1052
mock_progress.subject_finished.return_value = True
1053
web_experiment.progress = mock_progress
1054
fake_dict = {'device': 'fake_device', 'path': 'test/path', 'browser': 'fake_browser'}
1055
mock_devices = Mock()
1056
mock_device = Mock()
1057
mock_devices.get_device.return_value = mock_device
1058
web_experiment.devices = mock_devices
1059
mock_manager = Mock()
1060
mock_manager.attach_mock(after_last_run, "after_last_run_managed")
1061
mock_manager.attach_mock(aggregate_subject, "aggregate_subject_managed")
1062
1063
web_experiment.last_run_subject(fake_dict)
1064
1065
mock_progress.subject_finished.assert_called_once_with(fake_dict['device'], fake_dict['path'],
1066
fake_dict['browser'])
1067
expected_calls = [call.after_last_run_managed(mock_device, fake_dict['path']),
1068
call.aggregate_subject_managed()]
1069
assert mock_manager.mock_calls == expected_calls
1070
1071
def test_prepare_output_dir(self, tmpdir, web_experiment):
1072
paths.BASE_OUTPUT_DIR = str(tmpdir)
1073
fake_dict = {'device': 'fake_device', 'path': 'fake_path', 'browser': 'fake_browser'}
1074
1075
web_experiment.prepare_output_dir(fake_dict)
1076
1077
assert os.path.isdir(paths.OUTPUT_DIR)
1078
assert paths.OUTPUT_DIR == os.path.join(paths.BASE_OUTPUT_DIR, 'data', 'fake_device', 'fake_path',
1079
'fake_browser')
1080
1081
@patch('AndroidRunner.Experiment.Experiment.before_run_subject')
1082
def test_before_run_subject(self, before_run_subject, web_experiment):
1083
args = (1, 2, 3)
1084
kwargs = {'arg1': 1, 'arg2': 2}
1085
mock_device = Mock()
1086
path = 'test/path'
1087
1088
web_experiment.before_run_subject(mock_device, path, *args, **kwargs)
1089
1090
before_run_subject.assert_called_once_with(mock_device, path, *args, **kwargs)
1091
1092
@patch('time.sleep')
1093
@patch('AndroidRunner.Experiment.Experiment.before_run')
1094
def test_before_run(self, before_run, sleep, web_experiment):
1095
mock_browser = Mock()
1096
args = (2, 3)
1097
kwargs = {'arg1': 1, 'arg2': 2, 'browser': mock_browser}
1098
mock_device = Mock()
1099
mock_device.id = 'id'
1100
current_activity = FakeDevice.current_activity()
1101
mock_device.current_activity.return_value = current_activity
1102
path = 'test/path'
1103
run = 123456789
1104
mock_manager = Mock()
1105
mock_manager.attach_mock(before_run, "before_run_managed")
1106
mock_manager.attach_mock(mock_browser, "mock_browser_managed")
1107
mock_manager.attach_mock(sleep, "sleep_managed")
1108
1109
web_experiment.before_run(mock_device, path, run, *args, **kwargs)
1110
1111
expected_calls = [call.before_run_managed(mock_device, path, run, *args, **kwargs),
1112
call.mock_browser_managed.start(mock_device),
1113
call.sleep_managed(5)]
1114
assert mock_manager.mock_calls == expected_calls
1115
1116
@patch('time.sleep')
1117
@patch('AndroidRunner.Experiment.Experiment.interaction')
1118
def test_interaction(self, interaction, sleep, web_experiment):
1119
mock_browser = Mock()
1120
args = (2, 3)
1121
kwargs = {'arg1': 1, 'arg2': 2, 'browser': mock_browser}
1122
mock_device = Mock()
1123
path = 'test/path'
1124
run = 123456789
1125
mock_manager = Mock()
1126
mock_manager.attach_mock(mock_browser, "mock_browser_managed")
1127
mock_manager.attach_mock(sleep, "sleep_managed")
1128
mock_manager.attach_mock(interaction, "interaction_managed")
1129
1130
web_experiment.interaction(mock_device, path, run, *args, **kwargs)
1131
1132
expected_calls = [call.mock_browser_managed.load_url(mock_device, path),
1133
call.sleep_managed(5),
1134
call.interaction_managed(mock_device, path, run, *args, **kwargs),
1135
call.sleep_managed(web_experiment.duration)]
1136
assert mock_manager.mock_calls == expected_calls
1137
1138
@patch('time.sleep')
1139
@patch('AndroidRunner.Experiment.Experiment.after_run')
1140
def test_after_run(self, after_run, sleep, web_experiment):
1141
mock_browser = Mock()
1142
args = (2, 3)
1143
kwargs = {'arg1': 1, 'arg2': 2, 'browser': mock_browser}
1144
mock_device = Mock()
1145
mock_device.id = 'id'
1146
current_activity = FakeDevice.current_activity()
1147
mock_device.current_activity.return_value = current_activity
1148
path = 'test/path'
1149
run = 123456789
1150
web_experiment.clear_cache = False
1151
mock_manager = Mock()
1152
mock_manager.attach_mock(mock_browser, "mock_browser_managed")
1153
mock_manager.attach_mock(sleep, "sleep_managed")
1154
mock_manager.attach_mock(after_run, "after_run_managed")
1155
1156
web_experiment.after_run(mock_device, path, run, *args, **kwargs)
1157
1158
expected_calls = [call.mock_browser_managed.stop(mock_device, False),
1159
call.sleep_managed(3),
1160
call.after_run_managed(mock_device, path, run, *args, **kwargs)]
1161
assert mock_manager.mock_calls == expected_calls
1162
1163
mock_manager.reset_mock()
1164
web_experiment.clear_cache = True
1165
web_experiment.after_run(mock_device, path, run, *args, **kwargs)
1166
1167
expected_calls = [call.mock_browser_managed.stop(mock_device, True),
1168
call.sleep_managed(3),
1169
call.after_run_managed(mock_device, path, run, *args, **kwargs)]
1170
assert mock_manager.mock_calls == expected_calls
1171
1172
@patch('AndroidRunner.Experiment.Experiment.after_last_run')
1173
def test_after_last_run(self, after_last_run, web_experiment):
1174
args = (1, 2, 3)
1175
kwargs = {'arg1': 1, 'arg2': 2}
1176
mock_device = Mock()
1177
path = 'test/path'
1178
1179
web_experiment.after_last_run(mock_device, path, *args, **kwargs)
1180
1181
after_last_run.assert_called_once_with(mock_device, path, *args, **kwargs)
1182
1183
@patch('AndroidRunner.Browsers.Browser.Browser.stop')
1184
@patch('AndroidRunner.Experiment.Experiment.cleanup')
1185
def test_cleanup_empty_browsers(self, cleanup, stop, web_experiment):
1186
mock_device = Mock()
1187
web_experiment.browsers = []
1188
web_experiment.cleanup(mock_device)
1189
1190
cleanup.assert_called_once_with(mock_device)
1191
assert stop.call_count == 0
1192
1193
@patch('AndroidRunner.Experiment.Experiment.cleanup')
1194
def test_cleanup_non_empty_browsers(self, cleanup, web_experiment):
1195
mock_device = Mock()
1196
mock_browser = Mock()
1197
fake_browsers = []
1198
for _ in range(5):
1199
fake_browsers.append(mock_browser)
1200
web_experiment.browsers = fake_browsers
1201
web_experiment.cleanup(mock_device)
1202
1203
cleanup.assert_called_once_with(mock_device)
1204
assert mock_browser.stop.call_count == 5
1205
for mock_call in mock_browser.stop.mock_calls:
1206
assert mock_call == call(mock_device, clear_data=True)
1207
1208
1209
class TestNativeExperiment(object):
1210
@pytest.fixture()
1211
@patch('AndroidRunner.Tests.check_dependencies')
1212
@patch('AndroidRunner.Devices.Devices.__init__')
1213
def native_experiment(self, device, check_dependencies):
1214
check_dependencies.return_value = None
1215
device.return_value = None
1216
device_config = {'devices': 'fake_device'}
1217
return NativeExperiment(device_config, None, False)
1218
1219
@patch('os.path.isfile')
1220
@patch('AndroidRunner.Experiment.Experiment.__init__')
1221
def test_init_empty_config(self, experiment, isfile):
1222
native_experiment = NativeExperiment({}, None, False)
1223
1224
experiment.assert_called_once_with({}, None, False)
1225
assert native_experiment.duration == 0
1226
assert isfile.call_count == 0
1227
1228
@patch('os.path.isfile')
1229
@patch('AndroidRunner.Experiment.Experiment.__init__')
1230
def test_init_non_empty_config_all_files_found(self, experiment, isfile):
1231
test_paths = ['path1', 'path2', 'path3']
1232
config = {'paths': test_paths, 'duration': 1000}
1233
isfile.return_value = True
1234
1235
native_experiment = NativeExperiment(config, None, False)
1236
1237
experiment.assert_called_once_with(config, None, False)
1238
assert native_experiment.duration == 1
1239
assert isfile.call_count == 3
1240
isfile.assert_has_calls([call(test_paths[0]), call(test_paths[1]), call(test_paths[2])])
1241
1242
@patch('os.path.isfile')
1243
@patch('AndroidRunner.Experiment.Experiment.__init__')
1244
def test_init_non_empty_config_file_not_found(self, experiment, isfile):
1245
test_paths = ['path1']
1246
config = {'paths': test_paths}
1247
isfile.return_value = False
1248
with pytest.raises(ConfigError):
1249
NativeExperiment(config, None, False)
1250
1251
experiment.assert_called_once_with(config, None, False)
1252
isfile.assert_called_once_with(test_paths[0])
1253
1254
@patch('AndroidRunner.Experiment.Experiment.cleanup')
1255
def test_cleanup_app_not_installed(self, cleanup, native_experiment):
1256
mock_device = Mock()
1257
mock_device.get_app_list.return_value = []
1258
native_experiment.package = 'com.fake.package'
1259
1260
native_experiment.cleanup(mock_device)
1261
1262
cleanup.assert_called_once_with(mock_device)
1263
assert mock_device.uninstall.call_count == 0
1264
mock_device.get_app_list.assert_called_once()
1265
1266
@patch('AndroidRunner.Experiment.Experiment.cleanup')
1267
def test_cleanup_app_installed(self, cleanup, native_experiment):
1268
mock_device = Mock()
1269
mock_device.get_app_list.return_value = ['com.mock.package1', 'com.mock.package2', 'com.mock.package3']
1270
native_experiment.package = 'com.mock.package2'
1271
1272
native_experiment.cleanup(mock_device)
1273
1274
cleanup.assert_called_once_with(mock_device)
1275
mock_device.uninstall.assert_called_once_with('com.mock.package2')
1276
mock_device.get_app_list.assert_called_once()
1277
1278
@patch('AndroidRunner.Experiment.Experiment.before_experiment')
1279
def test_before_experiment(self, before_experiment, native_experiment):
1280
args = (1, 2, 3)
1281
kwargs = {'arg1': 1, 'arg2': 2}
1282
mock_device = Mock()
1283
path = 'test/path'
1284
1285
native_experiment.before_experiment(mock_device, path, *args, **kwargs)
1286
1287
before_experiment.assert_called_once_with(mock_device)
1288
1289
@patch('AndroidRunner.Experiment.Experiment.before_run_subject')
1290
def test_before_run_subject_pre_app_installed(self, before_run_subject, native_experiment):
1291
args = (1, 2, 3)
1292
kwargs = {'arg1': 1, 'arg2': 2}
1293
mock_device = Mock()
1294
test_package = 'com.test.app'
1295
path = os.path.join(test_package)
1296
mock_device.get_app_list.return_value = [test_package]
1297
native_experiment.pre_installed_apps = ['com.test.app']
1298
1299
native_experiment.before_run_subject(mock_device, path, *args, **kwargs)
1300
1301
before_run_subject.assert_called_once_with(mock_device, path)
1302
assert mock_device.install.call_count == 0
1303
assert mock_device.get_app_list.call_count == 0
1304
assert native_experiment.package == 'com.test.app'
1305
1306
@patch('AndroidRunner.Experiment.Experiment.before_run_subject')
1307
def test_before_run_subject_in_app_list(self, before_run_subject, native_experiment):
1308
args = (1, 2, 3)
1309
kwargs = {'arg1': 1, 'arg2': 2}
1310
mock_device = Mock()
1311
test_package = 'com.test.app.apk'
1312
path = os.path.join('test', test_package)
1313
mock_device.get_app_list.return_value = [test_package]
1314
1315
native_experiment.before_run_subject(mock_device, path, *args, **kwargs)
1316
1317
before_run_subject.assert_called_once_with(mock_device, path)
1318
mock_device.get_app_list.assert_called_once()
1319
assert mock_device.install.call_count == 0
1320
assert native_experiment.package == 'com.test.app'
1321
1322
@patch('AndroidRunner.Experiment.Experiment.before_run_subject')
1323
def test_before_run_subject_app_not_installed(self, before_run_subject, native_experiment):
1324
args = (1, 2, 3)
1325
kwargs = {'arg1': 1, 'arg2': 2}
1326
mock_device = Mock()
1327
test_package_file = 'com.test.app.apk'
1328
path = os.path.join('test', test_package_file)
1329
mock_device.get_app_list.return_value = []
1330
1331
native_experiment.before_run_subject(mock_device, path, *args, **kwargs)
1332
1333
before_run_subject.assert_called_once_with(mock_device, path)
1334
mock_device.get_app_list.assert_called_once()
1335
mock_device.install.assert_called_once_with(path)
1336
assert native_experiment.package == 'com.test.app'
1337
1338
@patch('AndroidRunner.Experiment.Experiment.after_launch')
1339
@patch('AndroidRunner.Experiment.Experiment.before_run')
1340
def test_before_run(self, before_run, after_launch, native_experiment):
1341
args = (1, 2, 3)
1342
kwargs = {'arg1': 1, 'arg2': 2}
1343
mock_device = Mock()
1344
mock_device.id = 'id'
1345
current_activity = FakeDevice.current_activity()
1346
mock_device.current_activity.return_value = current_activity
1347
path = 'test/path'
1348
run = 123456789
1349
native_experiment.package = 'com.test.app'
1350
mock_manager = Mock()
1351
mock_manager.attach_mock(before_run, 'before_run_managed')
1352
mock_manager.attach_mock(mock_device, 'mock_device_managed')
1353
mock_manager.attach_mock(after_launch, 'after_launch_managed')
1354
1355
native_experiment.before_run(mock_device, path, run, *args, **kwargs)
1356
1357
expected_calls = [call.before_run_managed(mock_device, path, run, *args, **kwargs),
1358
call.mock_device_managed.configure_settings_device('com.test.app', enable=True),
1359
call.mock_device_managed.launch_package('com.test.app'),
1360
call.after_launch_managed(mock_device, path, run)]
1361
assert mock_manager.mock_calls == expected_calls
1362
1363
@patch('time.sleep')
1364
@patch('AndroidRunner.Profilers.Profilers.start_profiling')
1365
def test_start_profiling(self, start_profiling, sleep, native_experiment):
1366
args = (1, 2, 3)
1367
kwargs = {'arg1': 1, 'arg2': 2}
1368
mock_device = Mock()
1369
path = 'test/path'
1370
run = 123456789
1371
native_experiment.package = 'com.test.app'
1372
mock_manager = Mock()
1373
mock_manager.attach_mock(start_profiling, 'start_profiling_managed')
1374
mock_manager.attach_mock(sleep, 'sleep_managed')
1375
1376
native_experiment.start_profiling(mock_device, path, run, *args, **kwargs)
1377
1378
expected_calls = [call.start_profiling_managed(mock_device, app='com.test.app')]
1379
assert mock_manager.mock_calls == expected_calls
1380
1381
@patch('AndroidRunner.Experiment.Experiment.after_run')
1382
def test_after_run(self, after_run, native_experiment):
1383
args = (1, 2, 3)
1384
kwargs = {'arg1': 1, 'arg2': 2}
1385
mock_device = Mock()
1386
mock_device.id = 'id'
1387
current_activity = FakeDevice.current_activity()
1388
mock_device.current_activity.return_value = current_activity
1389
path = 'test/path'
1390
run = 123456789
1391
native_experiment.package = 'com.test.app'
1392
native_experiment.clear_cache = True
1393
mock_manager = Mock()
1394
mock_manager.attach_mock(mock_device, 'mock_device_managed')
1395
mock_manager.attach_mock(after_run, 'after_run_managed')
1396
1397
native_experiment.after_run(mock_device, path, run, *args, **kwargs)
1398
1399
expected_calls = [call.mock_device_managed.current_activity(),
1400
call.mock_device_managed.force_stop(native_experiment.package),
1401
call.mock_device_managed.clear_app_data(native_experiment.package),
1402
call.mock_device_managed.configure_settings_device(native_experiment.package, enable=False),
1403
call.after_run_managed(mock_device, path, run)]
1404
assert mock_manager.mock_calls == expected_calls
1405
1406
@patch('time.sleep')
1407
@patch('AndroidRunner.Experiment.Experiment.interaction')
1408
def test_interaction(self, interaction, sleep, native_experiment):
1409
args = (1, 2, 3)
1410
kwargs = {'arg1': 1, 'arg2': 2}
1411
mock_device = Mock()
1412
path = 'test/path'
1413
run = 123456789
1414
mock_manager = Mock()
1415
mock_manager.attach_mock(sleep, "sleep_managed")
1416
mock_manager.attach_mock(interaction, "interaction_managed")
1417
1418
native_experiment.interaction(mock_device, path, run, *args, **kwargs)
1419
1420
expected_calls = [call.interaction_managed(mock_device, path, run, *args, **kwargs),
1421
call.sleep_managed(native_experiment.duration)]
1422
assert mock_manager.mock_calls == expected_calls
1423
1424
@patch('AndroidRunner.Experiment.Experiment.after_last_run')
1425
def test_after_last_run_pre_installed(self, after_last_run, native_experiment):
1426
after_last_run.return_value = None
1427
args = (1, 2, 3)
1428
kwargs = {'arg1': 1, 'arg2': 2}
1429
mock_device = Mock()
1430
mock_device.get_app_list.return_value = ['com.test.app']
1431
path = 'test/path'
1432
native_experiment.pre_installed_apps = ['com.test.app']
1433
native_experiment.package = 'com.test.app'
1434
1435
native_experiment.after_last_run(mock_device, path, *args, **kwargs)
1436
1437
assert mock_device.uninstall.call_count == 0
1438
assert native_experiment.package is None
1439
1440
@patch('AndroidRunner.Experiment.Experiment.after_last_run')
1441
def test_after_last_run_not_installed(self, after_last_run, native_experiment):
1442
after_last_run.return_value = None
1443
args = (1, 2, 3)
1444
kwargs = {'arg1': 1, 'arg2': 2}
1445
mock_device = Mock()
1446
mock_device.get_app_list.return_value = []
1447
path = 'test/path'
1448
native_experiment.pre_installed_apps = ['com.test.app']
1449
native_experiment.package = 'com.test.app'
1450
1451
native_experiment.after_last_run(mock_device, path, *args, **kwargs)
1452
1453
assert mock_device.uninstall.call_count == 0
1454
assert native_experiment.package is None
1455
1456
@patch('AndroidRunner.Experiment.Experiment.after_last_run')
1457
def test_after_last_run_not_pre_installed(self, after_last_run, native_experiment):
1458
args = (1, 2, 3)
1459
kwargs = {'arg1': 1, 'arg2': 2}
1460
mock_device = Mock()
1461
mock_device.get_app_list.return_value = ['com.test.app']
1462
path = 'test/path'
1463
native_experiment.pre_installed_apps = []
1464
native_experiment.package = 'com.test.app'
1465
mock_manager = Mock()
1466
mock_manager.attach_mock(after_last_run, 'after_last_run_managed')
1467
mock_manager.attach_mock(mock_device, 'mock_device_managed')
1468
1469
native_experiment.after_last_run(mock_device, path, *args, **kwargs)
1470
1471
expected_calls = [call.after_last_run_managed(mock_device, path),
1472
call.mock_device_managed.get_app_list(),
1473
call.mock_device_managed.uninstall('com.test.app')]
1474
assert mock_manager.mock_calls == expected_calls
1475
assert native_experiment.package is None
1476
1477
@patch('AndroidRunner.Experiment.Experiment.after_experiment')
1478
def test_after_experiment(self, after_experiment, native_experiment):
1479
args = (1, 2, 3)
1480
kwargs = {'arg1': 1, 'arg2': 2}
1481
mock_device = Mock()
1482
1483
native_experiment.after_experiment(mock_device, *args, **kwargs)
1484
1485
after_experiment.assert_called_once_with(mock_device)
1486
1487
1488
class TestExperimentFactory(object):
1489
def test_init(self):
1490
ExperimentFactory()
1491
1492
@patch('AndroidRunner.Progress.Progress.__init__')
1493
@patch('AndroidRunner.NativeExperiment.NativeExperiment.__init__')
1494
def test_from_json_native_progress(self, native_experiment, progress_init, tmpdir):
1495
native_experiment.return_value = None
1496
paths.OUTPUT_DIR = os.path.join(str(tmpdir), 'output')
1497
makedirs(paths.OUTPUT_DIR)
1498
tmp_file = tmpdir.join('tmp.txt')
1499
tmp_file.write('{"type":"native"}')
1500
mock_progress = Mock()
1501
1502
experiment = ExperimentFactory.from_json(str(tmp_file), mock_progress)
1503
1504
assert isinstance(experiment, NativeExperiment)
1505
native_experiment.assert_called_once_with({'type': 'native'}, mock_progress, True)
1506
assert progress_init.call_count == 0
1507
assert os.path.isfile(os.path.join(paths.OUTPUT_DIR, 'config.json'))
1508
assert filecmp.cmp(str(tmp_file), os.path.join(paths.OUTPUT_DIR, 'config.json'), False)
1509
1510
@patch('AndroidRunner.Progress.Progress.__init__')
1511
@patch('AndroidRunner.WebExperiment.WebExperiment.__init__')
1512
def test_from_json_web_progress(self, web_experiment, progress_init, tmpdir):
1513
web_experiment.return_value = None
1514
paths.OUTPUT_DIR = os.path.join(str(tmpdir), 'output')
1515
makedirs(paths.OUTPUT_DIR)
1516
tmp_file = tmpdir.join('tmp.txt')
1517
tmp_file.write('{"type":"web"}')
1518
mock_progress = Mock()
1519
1520
experiment = ExperimentFactory.from_json(str(tmp_file), mock_progress)
1521
1522
assert isinstance(experiment, WebExperiment)
1523
web_experiment.assert_called_once_with({'type': 'web'}, mock_progress, True)
1524
assert progress_init.call_count == 0
1525
assert os.path.isfile(os.path.join(paths.OUTPUT_DIR, 'config.json'))
1526
assert filecmp.cmp(str(tmp_file), os.path.join(paths.OUTPUT_DIR, 'config.json'), False)
1527
1528
@patch('AndroidRunner.Progress.Progress.__init__')
1529
@patch('AndroidRunner.Experiment.Experiment.__init__')
1530
def test_from_json_experiment_progress(self, mock_experiment, progress_init, tmpdir):
1531
mock_experiment.return_value = None
1532
paths.OUTPUT_DIR = os.path.join(str(tmpdir), 'output')
1533
makedirs(paths.OUTPUT_DIR)
1534
tmp_file = tmpdir.join('tmp.txt')
1535
tmp_file.write('{"type":"regular"}')
1536
mock_progress = Mock()
1537
1538
experiment = ExperimentFactory.from_json(str(tmp_file), mock_progress)
1539
1540
assert isinstance(experiment, Experiment)
1541
mock_experiment.assert_called_once_with({'type': 'regular'}, mock_progress, True)
1542
assert progress_init.call_count == 0
1543
assert os.path.isfile(os.path.join(paths.OUTPUT_DIR, 'config.json'))
1544
assert filecmp.cmp(str(tmp_file), os.path.join(paths.OUTPUT_DIR, 'config.json'), False)
1545
1546
@patch('AndroidRunner.Progress.Progress.__init__')
1547
@patch('AndroidRunner.Experiment.Experiment.__init__')
1548
def test_from_json_experiment_no_progres(self, mock_experiment, mock_progress, tmpdir):
1549
mock_experiment.return_value = None
1550
mock_progress.return_value = None
1551
paths.OUTPUT_DIR = os.path.join(str(tmpdir), 'output')
1552
makedirs(paths.OUTPUT_DIR)
1553
tmp_file = tmpdir.join('tmp.txt')
1554
tmp_file.write('{"type":"regular"}')
1555
1556
experiment = ExperimentFactory.from_json(str(tmp_file), None)
1557
1558
mock_progress.assert_called_once_with(config_file=str(tmp_file), config={'type': 'regular'},
1559
load_progress=False)
1560
mock_experiment.assert_called_once()
1561
assert isinstance(experiment, Experiment)
1562
assert isinstance(mock_experiment.mock_calls[0][1][1], Progress)
1563
assert os.path.isfile(os.path.join(paths.OUTPUT_DIR, 'config.json'))
1564
assert filecmp.cmp(str(tmp_file), os.path.join(paths.OUTPUT_DIR, 'config.json'), False)
1565
1566
@patch('AndroidRunner.Progress.Progress.__init__')
1567
@patch('tests.PluginTests.PluginTests.__init__')
1568
def test_from_json_plugintester_no_progres(self, mock_experiment, mock_progress, tmpdir):
1569
mock_experiment.return_value = None
1570
mock_progress.return_value = None
1571
paths.OUTPUT_DIR = os.path.join(str(tmpdir), 'output')
1572
makedirs(paths.OUTPUT_DIR)
1573
tmp_file = tmpdir.join('tmp.txt')
1574
tmp_file.write('{"type":"plugintest", "devices": {"nexus6p": {}}}')
1575
config = OrderedDict([('type', 'plugintest'), ('devices', OrderedDict([('nexus6p', OrderedDict())]))])
1576
experiment = ExperimentFactory.from_json(str(tmp_file), None)
1577
1578
assert mock_progress.call_count == 0
1579
mock_experiment.assert_called_once_with(config)
1580
assert isinstance(experiment, PluginTests)
1581
assert os.path.isfile(os.path.join(paths.OUTPUT_DIR, 'config.json'))
1582
assert filecmp.cmp(str(tmp_file), os.path.join(paths.OUTPUT_DIR, 'config.json'), False)
1583
1584
class TestPrematureStoppableRun(object):
1585
def test_invalid_stopping_condition_error(self):
1586
config = {"invalid": {}}
1587
queue = Mock()
1588
interaction = Mock()
1589
device = Mock()
1590
path = Mock()
1591
run = Mock()
1592
args = [1, 2, 3]
1593
kwargs = {"key" : "value"}
1594
1595
with pytest.raises(ConfigError):
1596
prsc = PrematureStoppableRun(config, queue, interaction, device, path, run, *args, **kwargs)
1597
1598
def test_no_regex_given(self):
1599
config = {"logcat_regex": {}}
1600
queue = Mock()
1601
interaction = Mock()
1602
device = Mock()
1603
path = Mock()
1604
run = Mock()
1605
args = [1, 2, 3]
1606
kwargs = {"key" : "value"}
1607
1608
with pytest.raises(ConfigError):
1609
prsc = PrematureStoppableRun(config, queue, interaction, device, path, run, *args, **kwargs)
1610
1611
def test_server_port_non_integer(self):
1612
config = {"post_request": {"port" : "2222"}}
1613
queue = Mock()
1614
interaction = Mock()
1615
device = Mock()
1616
path = Mock()
1617
run = Mock()
1618
args = [1, 2, 3]
1619
kwargs = {"key" : "value"}
1620
1621
with pytest.raises(ConfigError):
1622
prsc = PrematureStoppableRun(config, queue, interaction, device, path, run, *args, **kwargs)
1623
1624
@pytest.fixture()
1625
def rsc(self):
1626
config = {"post_request": {}}
1627
queue = Mock()
1628
interaction = Mock()
1629
device = Mock()
1630
path = Mock()
1631
run = Mock()
1632
args = [1, 2, 3]
1633
kwargs = {"key" : "value"}
1634
1635
rsc = PrematureStoppableRun(config, queue, interaction, device, path, run, *args, **kwargs)
1636
return rsc
1637
1638
def test_mp_interaction(self, rsc):
1639
rsc._mp_interaction(rsc.queue, rsc.interaction_function, rsc.device, rsc.path, rsc.run, rsc.args, rsc.kwargs)
1640
1641
rsc.interaction_function.assert_called_once_with(rsc.device, rsc.path, rsc.run, rsc.args, rsc.kwargs)
1642
rsc.queue.put.assert_called_once_with("interaction")
1643
1644
@patch("time.sleep")
1645
def test_mp_logcat_regex(self, time_mock, rsc):
1646
rsc.device.logcat_regex.side_effect = [False, True]
1647
rsc._mp_logcat_regex(rsc.queue, rsc.device, "test_regex")
1648
1649
time_mock.assert_called_once_with(1)
1650
rsc.queue.put.assert_called_once_with(PrematureStoppableRun.STOPPING_MECHANISM_LOGCAT_REGEX)
1651
1652
@patch("http.server.HTTPServer.serve_forever")
1653
@patch("AndroidRunner.StopRunWebserver.StopRunWebserver")
1654
def test_mp_post_request(self, stop_run_webserver, http_server, rsc):
1655
rsc._mp_post_request(rsc.queue, 8000)
1656
1657
http_server.assert_called_once_with()
1658
rsc.queue.put.assert_called_once_with("HTTP POST request")
1659
1660
@patch("AndroidRunner.PrematureStoppableRun.mp.Process")
1661
@patch("AndroidRunner.PrematureStoppableRun.psutil.Process")
1662
def test_run_post_request(self, psutil_, mp, rsc):
1663
proc = Mock()
1664
proc_a = Mock()
1665
proc_b = Mock()
1666
proc.children.return_value = [proc_a, proc_b]
1667
psutil_.return_value = proc
1668
rsc.condition = "post_request"
1669
rsc.run()
1670
1671
assert mp.call_count == 2
1672
assert psutil_.call_count == 2
1673
assert proc.children.call_count == 2
1674
assert proc_a.terminate.call_count == 2
1675
assert proc_b.terminate.call_count == 2
1676
1677
@patch("AndroidRunner.PrematureStoppableRun.mp.Process")
1678
@patch("AndroidRunner.PrematureStoppableRun.psutil.Process")
1679
def test_run_logcat_regex(self, psutil_, mp, rsc):
1680
proc = Mock()
1681
proc_a = Mock()
1682
proc_b = Mock()
1683
proc.children.return_value = [proc_a, proc_b]
1684
psutil_.return_value = proc
1685
rsc.condition = "logcat_regex"
1686
rsc.run()
1687
1688
assert mp.call_count == 2
1689
assert psutil_.call_count == 2
1690
assert proc.children.call_count == 2
1691
assert proc_a.terminate.call_count == 2
1692
assert proc_b.terminate.call_count == 2
1693
1694
@patch("AndroidRunner.PrematureStoppableRun.mp.Process")
1695
@patch("AndroidRunner.PrematureStoppableRun.psutil.Process")
1696
def test_run_function_call(self, psutil_, mp, rsc):
1697
proc = Mock()
1698
proc_a = Mock()
1699
proc_b = Mock()
1700
proc.children.return_value = [proc_a, proc_b]
1701
psutil_.return_value = proc
1702
rsc.condition = "function"
1703
rsc.run()
1704
1705
assert mp.call_count == 1
1706
assert psutil_.call_count == 1
1707
assert proc.children.call_count == 1
1708
proc.children.assert_called_once_with(recursive=True)
1709
assert proc_a.terminate.call_count == 1
1710
assert proc_b.terminate.call_count == 1
1711
1712