Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
S2-group
GitHub Repository: S2-group/android-runner
Path: blob/master/tests/unit/test_devices.py
908 views
1
import os
2
3
import pytest
4
from mock import MagicMock, Mock, call, patch
5
6
import AndroidRunner.Adb as Adb
7
from AndroidRunner.Device import Device
8
from AndroidRunner.Devices import Devices
9
from AndroidRunner.util import ConfigError
10
from tests.unit.fixtures.FakeDevice import FakeDevice
11
12
class TestDevice(object):
13
14
@pytest.fixture()
15
@patch('AndroidRunner.Adb.connect')
16
@patch('AndroidRunner.Adb.shell')
17
def device(self, adb_shell, adb_connect):
18
adb_connect.return_value = None
19
adb_shell.return_value = None
20
name = 'fake_device'
21
device_id = 123456789
22
device_settings = {}
23
24
return Device(name, device_id, device_settings)
25
26
@pytest.fixture()
27
@patch('AndroidRunner.Adb.connect')
28
@patch('AndroidRunner.Adb.shell')
29
def device_root(self, adb_shell, adb_connect):
30
adb_connect.return_value = None
31
adb_shell.return_value = None
32
name = 'fake_device'
33
device_id = 123456789
34
device_settings = {'root_disable_charging': True,
35
'charging_disabled_value': '0', 'usb_charging_disabled_file': 'test/file'}
36
37
return Device(name, device_id, device_settings)
38
39
@pytest.fixture()
40
@patch('AndroidRunner.Adb.connect')
41
@patch('AndroidRunner.Adb.shell')
42
def device_with_app_settings(self, adb_shell, adb_connect):
43
adb_connect.return_value = None
44
adb_shell.return_value = None
45
name = 'fake_device'
46
device_id = 123456789
47
device_settings = {"device_settings_reqs": {"app1": ["setting_1"], "app2": ["setting_1", "setting_2"]}}
48
49
return Device(name, device_id, device_settings)
50
51
@patch('AndroidRunner.Adb.connect')
52
@patch('AndroidRunner.Adb.shell')
53
def test_init(self, adb_shell, adb_connect):
54
name = 'fake_device'
55
device_id = 123456789
56
logcat_buffer_size = 64
57
device_settings = {'root_disable_charging': True,
58
'charging_disabled_value': '0',
59
'usb_charging_disabled_file': 'test/file',
60
'logcat_buffer_size' : logcat_buffer_size,
61
'power_device': {
62
'script_path': 'fake/path',
63
'py_path': 'python',
64
'vout': '3',
65
'serial_num': '23'
66
},
67
'device_settings_reqs': {'app1': ['a, b'], 'app2': ['c']}
68
}
69
70
device = Device(name, device_id, device_settings)
71
72
assert device.name == name
73
assert device.id == device_id
74
assert device.root_plug_value is None
75
assert device.root_unplug_file == 'test/file'
76
assert device.root_unplug_value == '0'
77
assert device.root_unplug is True
78
assert device.power_device is not None
79
assert device.power_device['script_path'] == 'fake/path'
80
assert device.power_device['py_path'] == 'python'
81
assert device.device_settings_reqs == {'app1': ['a, b'], 'app2': ['c']}
82
assert device.logcat_buffer_size == logcat_buffer_size
83
adb_connect.assert_called_once_with(device_id)
84
adb_shell.assert_called_once_with(device_id, f"logcat -G {logcat_buffer_size}K")
85
86
@patch('AndroidRunner.Adb.configure_settings')
87
@patch('logging.Logger.info')
88
def test_configure_settings_device(self, logger, configure_settings, device_with_app_settings):
89
device_with_app_settings.configure_settings_device("app1")
90
logger.assert_called_with('Enabling setting_1')
91
configure_settings.assert_called_with(device_with_app_settings.id, "setting_1",True)
92
93
device_with_app_settings.configure_settings_device("app2")
94
logger.assert_called_with('Enabling setting_2')
95
96
device_with_app_settings.configure_settings_device(None)
97
device_with_app_settings.configure_settings_device("app3")
98
99
assert configure_settings.call_count == 3
100
101
@patch('AndroidRunner.Adb.shell')
102
def test_get_version(self, adb_shell, device):
103
adb_shell.return_value = 9
104
version = device.get_version()
105
106
assert version == 9
107
adb_shell.assert_called_once_with(123456789, 'getprop ro.build.version.release')
108
109
@patch('AndroidRunner.Adb.shell')
110
def test_get_api_level(self, adb_shell, device):
111
adb_shell.return_value = 28
112
level = device.get_api_level()
113
114
assert level == 28
115
adb_shell.assert_called_once_with(123456789, 'getprop ro.build.version.sdk')
116
117
@patch('AndroidRunner.Device.Device.get_app_list')
118
def test_is_installed(self, get_app_list, device):
119
get_app_list.return_value = ['app1', 'app2', 'installed_app']
120
result_installed = device.is_installed(['app3', 'installed_app', 'app4'])
121
assert len(result_installed) == 3
122
assert 'app3' in result_installed and not result_installed['app3']
123
assert 'app4' in result_installed and not result_installed['app4']
124
assert 'installed_app' in result_installed and result_installed['installed_app']
125
126
@patch('AndroidRunner.Adb.list_apps')
127
def test_get_app_list(self, adb_list_apps, device):
128
adb_list_apps.return_value = ['app1', 'app2', 'app3']
129
app_list = device.get_app_list()
130
131
assert app_list == ['app1', 'app2', 'app3']
132
133
@patch('AndroidRunner.Adb.install')
134
def test_install_file_not_exist(self, adb_install, device):
135
with pytest.raises(Adb.AdbError):
136
device.install('fake.apk')
137
138
assert adb_install.call_count == 0
139
140
@patch('os.path.isfile')
141
@patch('AndroidRunner.Adb.install')
142
def test_install_file_exist(self, adb_install, os_isfile, device):
143
os_isfile.return_value = True
144
145
device.install('fake.apk')
146
147
adb_install.assert_called_once_with(123456789, 'fake.apk')
148
149
@patch("AndroidRunner.Adb.shell")
150
@pytest.mark.parametrize('size', [Device.LOGCAT_BUFFER_SIZE_MIN,
151
int((Device.LOGCAT_BUFFER_SIZE_MIN + Device.LOGCAT_BUFFER_SIZE_MAX)/2),
152
Device.LOGCAT_BUFFER_SIZE_MAX])
153
def test_set_logcat_buffer_size_success(self, adb_shell, device, size):
154
accepted_logcat_buffer_size = size
155
logcat_command = f'logcat -G {accepted_logcat_buffer_size}K'
156
157
device.logcat_buffer_size = accepted_logcat_buffer_size
158
159
adb_shell.assert_called_once_with(123456789, logcat_command)
160
assert device.logcat_buffer_size == accepted_logcat_buffer_size
161
162
@pytest.mark.parametrize('size', [Device.LOGCAT_BUFFER_SIZE_MIN-1, Device.LOGCAT_BUFFER_SIZE_MAX+1])
163
def test_set_logcat_buffer_size_failure_size_not_in_range(self, device, size):
164
with pytest.raises(ConfigError):
165
device.logcat_buffer_size = size
166
167
@pytest.mark.parametrize('size', [f"{Device.LOGCAT_BUFFER_SIZE_MIN}", float(Device.LOGCAT_BUFFER_SIZE_MIN), ""])
168
def test_set_logcat_buffer_size_failure_wrong_type(self, device, size):
169
with pytest.raises(ConfigError):
170
device.logcat_buffer_size = size
171
172
@patch('AndroidRunner.Adb.uninstall')
173
def test_uninstall(self, adb_uninstall, device):
174
app_name = 'fake_app'
175
176
device.uninstall(app_name)
177
178
adb_uninstall.assert_called_once_with(123456789, app_name)
179
180
@patch('AndroidRunner.Device.Device.su_unplug')
181
@patch('AndroidRunner.Device.Device.get_api_level')
182
@patch('AndroidRunner.Adb.shell')
183
def test_unplug_api_lower_23_no_root(self, adb_shell, get_api_level, su_unplug, device):
184
get_api_level.return_value = 22
185
device.unplug(False)
186
187
assert su_unplug.call_count == 0
188
adb_shell.assert_called_once_with(123456789, 'dumpsys battery set usb 0')
189
190
@patch('AndroidRunner.Device.Device.su_unplug')
191
@patch('AndroidRunner.Device.Device.get_api_level')
192
@patch('AndroidRunner.Adb.shell')
193
def test_unplug_api_higher_equal_23_no_root(self, adb_shell, get_api_level, su_unplug, device):
194
get_api_level.return_value = 23
195
device.unplug(False)
196
197
assert su_unplug.call_count == 0
198
adb_shell.assert_called_once_with(123456789, 'dumpsys battery unplug')
199
200
@patch('AndroidRunner.Device.Device.su_unplug')
201
@patch('AndroidRunner.Device.Device.get_api_level')
202
@patch('AndroidRunner.Adb.shell')
203
def test_unplug_api_lower_23_root(self, adb_shell, get_api_level, su_unplug, device_root):
204
get_api_level.return_value = 22
205
device_root.unplug(False)
206
207
su_unplug.assert_called_once_with(False)
208
assert adb_shell.call_count == 0
209
210
@patch('AndroidRunner.Device.Device.su_unplug')
211
@patch('AndroidRunner.Device.Device.get_api_level')
212
@patch('AndroidRunner.Adb.shell')
213
def test_unplug_api_lower_23_root_restart(self, adb_shell, get_api_level, su_unplug, device_root):
214
get_api_level.return_value = 22
215
device_root.unplug(True)
216
217
su_unplug.assert_called_once_with(True)
218
assert adb_shell.call_count == 0
219
220
@patch('AndroidRunner.Device.Device.su_unplug')
221
@patch('AndroidRunner.Device.Device.get_api_level')
222
@patch('AndroidRunner.Adb.shell')
223
def test_unplug_api_higher_equal_23_root(self, adb_shell, get_api_level, su_unplug, device_root):
224
get_api_level.return_value = 23
225
device_root.unplug(False)
226
227
su_unplug.assert_called_once_with(False)
228
assert adb_shell.call_count == 0
229
230
@patch('AndroidRunner.Device.Device.su_unplug')
231
@patch('AndroidRunner.Device.Device.get_api_level')
232
@patch('AndroidRunner.Adb.shell')
233
def test_unplug_api_higher_equal_23_root_restart(self, adb_shell, get_api_level, su_unplug, device_root):
234
get_api_level.return_value = 23
235
device_root.unplug(True)
236
237
su_unplug.assert_called_once_with(True)
238
assert adb_shell.call_count == 0
239
240
@patch('AndroidRunner.Device.Device.check_plug_value')
241
@patch('AndroidRunner.Adb.shell_su')
242
def test_su_unplug_no_error(self, shell_su, check_plug_value, device_root):
243
shell_su.side_effect = ['default_return', '']
244
245
device_root.su_unplug(False)
246
247
expected_calls = [call(device_root.id, 'cat %s' % device_root.root_unplug_file),
248
call(device_root.id, 'echo %s > %s' %
249
(device_root.root_unplug_value, device_root.root_unplug_file))]
250
assert shell_su.mock_calls == expected_calls
251
assert device_root.root_plug_value == 'default_return'
252
assert check_plug_value.call_count == 0
253
254
@patch('AndroidRunner.Device.Device.check_plug_value')
255
@patch('AndroidRunner.Adb.shell_su')
256
def test_su_unplug_not_rooted(self, shell_su, check_plug_value, device_root):
257
shell_su.side_effect = ['su: not found', 'default_return', 'No such file or directory']
258
with pytest.raises(Adb.AdbError):
259
device_root.su_unplug(False)
260
261
expected_calls = [call(device_root.id, 'cat test/file')]
262
assert shell_su.mock_calls == expected_calls
263
assert device_root.root_plug_value == 'su: not found'
264
assert check_plug_value.call_count == 0
265
266
@patch('AndroidRunner.Device.Device.check_plug_value')
267
@patch('AndroidRunner.Adb.shell_su')
268
def test_su_unplug_invalid_root_unplug_file(self, adb_shell, check_plug_value, device_root):
269
adb_shell.side_effect = ['No such file or directory', '']
270
with pytest.raises(ConfigError):
271
device_root.su_unplug(False)
272
273
expected_calls = [call(device_root.id, 'cat %s' % device_root.root_unplug_file)]
274
assert adb_shell.mock_calls == expected_calls
275
assert device_root.root_plug_value == 'No such file or directory'
276
assert check_plug_value.call_count == 0
277
278
@patch('AndroidRunner.Device.Device.check_plug_value')
279
@patch('AndroidRunner.Adb.shell_su')
280
def test_su_unplug_restart(self, shell_su, check_plug_value, device_root):
281
shell_su.side_effect = ['default_return', '']
282
283
device_root.su_unplug(True)
284
285
expected_calls = [call(device_root.id, 'cat %s' % device_root.root_unplug_file),
286
call(device_root.id, 'echo %s > %s' %
287
(device_root.root_unplug_value, device_root.root_unplug_file))]
288
assert shell_su.mock_calls == expected_calls
289
assert device_root.root_plug_value == 'default_return'
290
check_plug_value.assert_called_once()
291
292
def test_check_plug_value_no_action(self, device_root):
293
device_root.root_plug_value = 'enabled'
294
device_root.root_unplug_value = 'disabled'
295
296
device_root.check_plug_value()
297
298
assert device_root.root_plug_value == 'enabled'
299
assert device_root.root_unplug_value == 'disabled'
300
301
def test_check_plug_value_unplug_plug_int_no_match(self, device_root):
302
device_root.root_plug_value = 1
303
device_root.root_unplug_value = 0
304
305
device_root.check_plug_value()
306
307
assert device_root.root_plug_value == 1
308
assert device_root.root_unplug_value == 0
309
310
@patch('logging.Logger.info')
311
def test_check_plug_value_unplug_int_plug_string_no_match(self, logger, device_root):
312
device_root.root_plug_value = 'enabled'
313
device_root.root_unplug_value = 0
314
315
device_root.check_plug_value()
316
317
assert device_root.root_plug_value == 'enabled'
318
assert device_root.root_unplug_value == 0
319
logger.assert_called_once_with('Error setting root plug value, '
320
'check manually after experiment if charging is enabled')
321
322
def test_check_plug_value_same_plug_unplug_int(self, device_root):
323
device_root.root_plug_value = 0
324
device_root.root_unplug_value = 0
325
326
device_root.check_plug_value()
327
328
assert device_root.root_plug_value == 1
329
assert device_root.root_unplug_value == 0
330
331
def test_check_plug_value_same_plug_unplug_string_set_enabled(self, device_root):
332
device_root.root_plug_value = 'disabled'
333
device_root.root_unplug_value = 'disabled'
334
335
device_root.check_plug_value()
336
337
assert device_root.root_plug_value == 'enabled'
338
assert device_root.root_unplug_value == 'disabled'
339
340
def test_check_plug_value_same_plug_unplug_string_set_disabled(self, device_root):
341
device_root.root_plug_value = 'enabled'
342
device_root.root_unplug_value = 'enabled'
343
344
device_root.check_plug_value()
345
346
assert device_root.root_plug_value == 'disabled'
347
assert device_root.root_unplug_value == 'enabled'
348
349
@patch('AndroidRunner.Device.Device.su_plug')
350
@patch('AndroidRunner.Adb.shell')
351
def test_plug_no_root(self, adb_shell, su_plug, device):
352
device.plug()
353
354
assert su_plug.call_count == 0
355
adb_shell.assert_called_once_with(123456789, 'dumpsys battery reset')
356
357
@patch('AndroidRunner.Device.Device.su_plug')
358
@patch('AndroidRunner.Adb.shell')
359
def test_plug_root(self, adb_shell, su_plug, device_root):
360
device_root.plug()
361
362
su_plug.assert_called_once()
363
adb_shell.assert_called_once_with(123456789, 'dumpsys battery reset')
364
365
@patch('AndroidRunner.Adb.shell_su')
366
def test_su_plug(self, adb_shell_su, device_root):
367
device_root.root_plug_value = '123456'
368
369
device_root.su_plug()
370
371
adb_shell_su.assert_called_once_with(123456789, 'echo 123456 > test/file')
372
373
@patch('AndroidRunner.Adb.shell')
374
def test_current_activity_success(self, adb_shell, device):
375
adb_shell.return_value = 'test\norg.activity'
376
assert device.current_activity() == {'type': 'test', 'name': 'org.activity'}
377
378
@patch('AndroidRunner.Adb.shell')
379
def test_current_activity_error(self, adb_shell, device):
380
adb_shell.return_value = None
381
with pytest.raises(Adb.AdbError):
382
device.current_activity()
383
384
@patch('AndroidRunner.Adb.shell')
385
def test_launch_package_succes(self, adb_shell, device):
386
package = 'fake.test.package'
387
adb_shell.return_value = 'successsss'
388
389
device.launch_package(package)
390
391
adb_shell.assert_called_once_with(123456789, 'monkey -p {} 1'.format(package))
392
393
@patch('AndroidRunner.Adb.shell')
394
def test_launch_package_failure(self, adb_shell, device):
395
package = 'fake.test.package'
396
adb_shell.return_value = 'error error error monkey aborted error'
397
398
with pytest.raises(Adb.AdbError):
399
device.launch_package(package)
400
401
adb_shell.assert_called_once_with(123456789, 'monkey -p {} 1'.format(package))
402
403
@patch('AndroidRunner.Adb.shell')
404
def test_launch_activity(self, adb_shell, device):
405
package = 'fake.test.package'
406
activity = 'main'
407
408
device.launch_activity(package, activity)
409
410
adb_shell.assert_called_once_with(123456789, 'am start -n {}/{}'.format(package, activity))
411
412
@patch('AndroidRunner.Adb.shell')
413
def test_launch_activity_force_stop(self, adb_shell, device):
414
package = 'fake.test.package'
415
activity = 'main'
416
417
device.launch_activity(package, activity, force_stop=True)
418
419
adb_shell.assert_called_once_with(123456789, 'am start -S -n {}/{}'.format(package, activity))
420
421
@patch('AndroidRunner.Adb.shell')
422
def test_launch_activity_action(self, adb_shell, device):
423
package = 'fake.test.package'
424
activity = 'main'
425
426
device.launch_activity(package, activity, action='action')
427
428
adb_shell.assert_called_once_with(123456789, 'am start -a {} -n {}/{}'.format('action', package, activity))
429
430
@patch('AndroidRunner.Adb.shell')
431
def test_launch_activity_data_uri(self, adb_shell, device):
432
package = 'fake.test.package'
433
activity = 'main'
434
435
device.launch_activity(package, activity, data_uri='data.uri')
436
437
adb_shell.assert_called_once_with(123456789, 'am start -n {}/{} -d {}'.format(package, activity, 'data.uri'))
438
439
@patch('AndroidRunner.Adb.shell')
440
def test_launch_activity_from_scratch(self, adb_shell, device):
441
package = 'fake.test.package'
442
activity = 'main'
443
444
device.launch_activity(package, activity, from_scratch=True)
445
446
adb_shell.assert_called_once_with(123456789,
447
'am start -n {}/{} --activity-clear-task'.format(package, activity))
448
449
@patch('AndroidRunner.Adb.shell')
450
def test_force_stop(self, adb_shell, device):
451
name = 'fake_app'
452
453
device.force_stop(name)
454
455
adb_shell.assert_called_once_with(123456789, 'am force-stop {}'.format(name))
456
457
@patch('AndroidRunner.Adb.clear_app_data')
458
def test_clear_app_data(self, adb_clear_app_data, device):
459
name = 'fake_app'
460
461
device.clear_app_data(name)
462
463
adb_clear_app_data.assert_called_once_with(123456789, name)
464
465
@patch('AndroidRunner.Adb.logcat')
466
def test_logcat_to_file(self, adb_logcat, device, tmpdir):
467
path = os.path.join(str(tmpdir), 'logcat')
468
logcat_result = "test file content: 123dsfg564sdfhg"
469
adb_logcat.return_value = logcat_result
470
471
device.logcat_to_file(path)
472
473
files_in_path = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]
474
475
assert len(files_in_path) == 1
476
with open(os.path.join(path, files_in_path[0]), 'r') as fl:
477
file_content = fl.read()
478
assert file_content == logcat_result
479
adb_logcat.assert_called_once_with(123456789)
480
481
@patch('AndroidRunner.Adb.logcat')
482
def test_logcat_regex(self, adb_logcat, device):
483
logcat_result = "test result 123dsfg564sdfhg"
484
adb_logcat.return_value = logcat_result
485
fake_regex = 'auiashdfdfv'
486
487
result = device.logcat_regex(fake_regex)
488
489
adb_logcat.assert_called_once_with(123456789, regex=fake_regex)
490
assert result == logcat_result
491
492
@patch('AndroidRunner.Adb.push')
493
def test_push(self, adb_push, device):
494
adb_push.return_value = 'pushpush'
495
local_path = 'test/local/path'
496
remote_path = 'test/remote/path'
497
498
result = device.push(local_path, remote_path)
499
500
adb_push.assert_called_once_with(123456789, local_path, remote_path)
501
assert result == 'pushpush'
502
503
@patch('AndroidRunner.Adb.pull')
504
def test_pull(self, adb_pull, device):
505
adb_pull.return_value = 'pullpull'
506
local_path = 'test/local/path'
507
remote_path = 'test/remote/path'
508
509
result = device.pull(local_path, remote_path)
510
511
adb_pull.assert_called_once_with(123456789, local_path, remote_path)
512
assert result == 'pullpull'
513
514
@patch('AndroidRunner.Adb.shell')
515
def test_shell(self, adb_shell, device):
516
adb_shell.return_value = 'shell return value'
517
shell_command = 'dumpsys battery set usb 1'
518
519
result = device.shell(shell_command)
520
521
adb_shell.assert_called_once_with(123456789, shell_command)
522
assert result == 'shell return value'
523
524
@patch('AndroidRunner.Device.Device.get_api_level')
525
@patch('AndroidRunner.Device.Device.get_version')
526
def test_str(self, get_version, get_api_level, device):
527
get_version.return_value = 9
528
get_api_level.return_value = 28
529
530
device_string = str(device)
531
532
assert device_string == 'fake_device (123456789, Android 9, API level 28)'
533
534
535
class TestDevices(object):
536
@pytest.fixture()
537
@patch('AndroidRunner.Devices.load_json')
538
@patch('AndroidRunner.Adb.setup')
539
def devices(self, adb_setup, load_json):
540
adb_setup.return_value = None
541
load_json.return_value = {}
542
return Devices([])
543
544
@patch('AndroidRunner.Devices.load_json')
545
@patch('AndroidRunner.Adb.setup')
546
def test_init_error(self, adb_setup, load_json):
547
load_json.return_value = {}
548
with pytest.raises(ConfigError):
549
Devices(['fake_device'])
550
551
adb_setup.assert_called_once_with('adb')
552
553
@patch('AndroidRunner.Device.Device.__init__')
554
@patch('AndroidRunner.Devices.load_json')
555
@patch('AndroidRunner.Adb.setup')
556
def test_init_succes(self, adb_setup, load_json, device):
557
device.return_value = None
558
load_json.return_value = {'fake_device': 123456789}
559
mock_device_settings = Mock()
560
devices = Devices({'fake_device': mock_device_settings}, 'adb/path')
561
562
adb_setup.assert_called_once_with('adb/path')
563
device.assert_called_once_with('fake_device', 123456789, mock_device_settings)
564
assert len(devices.devices) == 1
565
assert isinstance(devices.devices[0], Device)
566
567
def test_iter(self, devices):
568
test_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
569
devices.devices = test_list
570
result_list = []
571
for n in devices:
572
result_list.append(n)
573
574
assert result_list == test_list
575
576
def test_get_device(self, devices):
577
device_names = ['a', 'b', 'c', 'd']
578
test_devices = []
579
for name in device_names:
580
mock_device = Mock()
581
mock_device.name = name
582
mock_device.id = name
583
test_devices.append(mock_device)
584
devices.devices = test_devices
585
586
device = devices.get_device('c')
587
assert device.name == 'c' and device.id == 'c'
588
589
def test_names(self, devices):
590
device_names = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
591
devices._device_map = device_names
592
593
names = devices.names()
594
595
assert len(names) == 4
596
assert 'a' in names
597
assert 'b' in names
598
assert 'c' in names
599
assert 'd' in names
600
601
def test_ids(self, devices):
602
device_names = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
603
devices._device_map = device_names
604
605
ids = devices.ids()
606
607
assert len(ids) == 4
608
assert 1 in ids
609
assert 2 in ids
610
assert 3 in ids
611
assert 4 in ids
612
613
def test_get_id(self, devices):
614
device_names = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
615
devices._device_map = device_names
616
617
device_id = devices.get_id('c')
618
619
assert device_id == 3
620
621
def test_get_name(self, devices):
622
device_names = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
623
devices._device_map = device_names
624
625
name = devices.get_name(3)
626
627
assert 'c' == name
628
629
630
class TestAdb(object):
631
632
@patch('AndroidRunner.Adb.ADB')
633
def test_setup_succes_custom_path(self, adb):
634
adb_instance = MagicMock()
635
adb_instance._ADB__error = None
636
adb.return_value = adb_instance
637
638
Adb.setup('adb/path')
639
640
assert isinstance(Adb.adb, MagicMock)
641
adb.assert_called_once_with(adb_path='adb/path')
642
643
@patch('AndroidRunner.Adb.ADB')
644
def test_setup_succes_default_path(self, adb):
645
adb_instance = MagicMock()
646
adb_instance._ADB__error = None
647
adb.return_value = adb_instance
648
649
Adb.setup()
650
651
assert isinstance(Adb.adb, MagicMock)
652
adb.assert_called_once_with(adb_path='adb')
653
654
@patch('AndroidRunner.Adb.ADB')
655
def test_setup_error(self, adb):
656
adb_instance = MagicMock()
657
adb_instance._ADB__error = True
658
adb.return_value = adb_instance
659
with pytest.raises(Adb.AdbError):
660
Adb.setup()
661
662
def test_connect_no_devices(self):
663
mock_adb = Mock()
664
mock_adb.get_devices.return_value = {}
665
Adb.adb = mock_adb
666
667
with pytest.raises(Adb.ConnectionError):
668
Adb.connect('123')
669
670
mock_adb.get_devices.assert_called_once()
671
672
def test_connect_device_missing(self):
673
mock_adb = Mock()
674
mock_adb.get_devices.return_value = {'a': 12, 'b': 13}
675
Adb.adb = mock_adb
676
677
with pytest.raises(Adb.ConnectionError):
678
Adb.connect(123)
679
680
mock_adb.get_devices.assert_called_once()
681
682
def test_connect_succes(self):
683
mock_adb = Mock()
684
mock_adb.get_devices.return_value = {'a': 12, 'b': 13, 'c': 123}
685
Adb.adb = mock_adb
686
687
Adb.connect(123)
688
689
mock_adb.get_devices.assert_called_once()
690
691
def test_shell_succes(self):
692
mock_adb = Mock()
693
mock_adb.shell_command.return_value = "succes "
694
Adb.adb = mock_adb
695
result = Adb.shell(123, "test_command")
696
697
expected_calls = [call.set_target_by_name(123), call.shell_command('test_command')]
698
assert mock_adb.mock_calls == expected_calls
699
assert result == 'succes'
700
701
def test_shell_error(self):
702
mock_adb = Mock()
703
mock_adb.shell_command.return_value = "error"
704
Adb.adb = mock_adb
705
706
with pytest.raises(Adb.AdbError):
707
Adb.shell(123, "test_command")
708
709
expected_calls = [call.set_target_by_name(123), call.shell_command('test_command')]
710
assert mock_adb.mock_calls == expected_calls
711
712
def test_shell_su_succes(self):
713
mock_adb = Mock()
714
mock_adb.shell_command.return_value = "su_succes "
715
Adb.adb = mock_adb
716
result = Adb.shell_su(123, "test_command_su")
717
718
expected_calls = [call.set_target_by_name(123), call.shell_command('su -c \'test_command_su\'')]
719
assert mock_adb.mock_calls == expected_calls
720
assert result == 'su_succes'
721
722
def test_shell_su_error(self):
723
mock_adb = Mock()
724
mock_adb.shell_command.return_value = "su_error"
725
Adb.adb = mock_adb
726
727
with pytest.raises(Adb.AdbError):
728
Adb.shell_su(123, "test_command_su")
729
730
expected_calls = [call.set_target_by_name(123), call.shell_command('su -c \'test_command_su\'')]
731
assert mock_adb.mock_calls == expected_calls
732
733
@patch('AndroidRunner.Adb.shell')
734
def test_list_apps(self, adb_shell):
735
adb_shell.return_value = 'package:com.app.1\npackage:com.app.2\npackage:com.app.3'
736
737
result = Adb.list_apps(123)
738
739
adb_shell.assert_called_once_with(123, 'pm list packages')
740
assert len(result) == 3
741
assert 'com.app.1' in result
742
assert 'com.app.2' in result
743
assert 'com.app.3' in result
744
745
def test_install_default(self):
746
mock_adb = Mock()
747
mock_adb._ADB__output = 'succes'
748
Adb.adb = mock_adb
749
device_id = 123
750
apk = 'test_apk.apk'
751
752
result = Adb.install(device_id, apk)
753
754
assert result == 'succes'
755
expected_calls = [call.set_target_by_name(device_id), call.run_cmd(['install', '-r', '-g', '-t', apk])]
756
assert mock_adb.mock_calls == expected_calls
757
758
@patch("zipfile.ZipFile")
759
def test_install_multiple_default(self, zipfile, tmpdir):
760
xapk_file = tmpdir.mkdir("xapk").join("test_apk.xapk")
761
apk_file = tmpdir.mkdir("xapk/test_apk/").join("test_apk.apk")
762
763
xapk_file.write("This is an xapk file")
764
apk_file.write("This is an apk file")
765
device_id = 123
766
767
mock_adb = Mock()
768
mock_adb._ADB__output = 'succes'
769
Adb.adb = mock_adb
770
result = Adb.install(device_id, xapk_file)
771
772
assert result == 'succes'
773
expected_calls = [call.set_target_by_name(device_id), call.run_cmd(['install-multiple', '-r', '-g', '-t', apk_file])]
774
assert mock_adb.mock_calls == expected_calls
775
776
@patch("zipfile.ZipFile")
777
def test_install_multiple_no_apks_in_xapk_file(self, zipfile, tmpdir):
778
xapk_file = tmpdir.mkdir("xapk").join("test_apk.xapk")
779
xapk_file.write("This is an xapk file")
780
device_id = 123
781
782
mock_adb = Mock()
783
mock_adb._ADB__output = 'succes'
784
Adb.adb = mock_adb
785
786
with pytest.raises(ConfigError):
787
Adb.install(device_id, xapk_file)
788
789
def test_install_no_replace(self):
790
mock_adb = Mock()
791
mock_adb._ADB__output = 'succes'
792
Adb.adb = mock_adb
793
device_id = 123
794
apk = 'test_apk.apk'
795
796
result = Adb.install(device_id, apk, replace=False)
797
798
assert result == 'succes'
799
expected_calls = [call.set_target_by_name(device_id), call.run_cmd(['install', '-g', '-t', apk])]
800
assert mock_adb.mock_calls == expected_calls
801
802
def test_install_not_all_permissions(self):
803
mock_adb = Mock()
804
mock_adb._ADB__output = 'succes'
805
Adb.adb = mock_adb
806
device_id = 123
807
apk = 'test_apk.apk'
808
809
result = Adb.install(device_id, apk, all_permissions=False)
810
811
assert result == 'succes'
812
expected_calls = [call.set_target_by_name(device_id), call.run_cmd(['install', '-r', '-t', apk])]
813
assert mock_adb.mock_calls == expected_calls
814
815
@patch('AndroidRunner.Adb.success_or_exception')
816
def test_uninstall_delete_data(self, s_or_e):
817
mock_adb = Mock()
818
mock_adb.uninstall.return_value = 'succes'
819
Adb.adb = mock_adb
820
device_id = 123
821
name = 'app_name'
822
823
manager = Mock()
824
manager.attach_mock(s_or_e, "s_or_e_mock")
825
manager.mock_adb = mock_adb
826
827
Adb.uninstall(device_id, name)
828
829
expected_calls = [call.mock_adb.set_target_by_name(123),
830
call.mock_adb.uninstall(package=name, keepdata=True),
831
call.s_or_e_mock('succes', '{}: "{}" uninstalled'.format(device_id, name),
832
'{}: Failed to uninstall "{}"'.format(device_id, name))]
833
assert manager.mock_calls == expected_calls
834
835
@patch('AndroidRunner.Adb.success_or_exception')
836
def test_uninstall_keep_data(self, s_or_e):
837
mock_adb = Mock()
838
mock_adb.uninstall.return_value = 'succes'
839
Adb.adb = mock_adb
840
device_id = 123
841
name = 'app_name'
842
843
manager = Mock()
844
manager.attach_mock(s_or_e, "s_or_e_mock")
845
manager.mock_adb = mock_adb
846
847
Adb.uninstall(device_id, name, True)
848
849
expected_calls = [call.mock_adb.set_target_by_name(123),
850
call.mock_adb.uninstall(package=name, keepdata=False),
851
call.s_or_e_mock('succes', '{}: "{}" uninstalled'.format(device_id, name),
852
'{}: Failed to uninstall "{}"'.format(device_id, name))]
853
assert manager.mock_calls == expected_calls
854
855
@patch('AndroidRunner.Adb.success_or_exception')
856
def test_clear_app_data(self, s_or_e):
857
mock_adb = Mock()
858
mock_adb.shell_command.return_value = 'succes'
859
Adb.adb = mock_adb
860
device_id = 123
861
name = 'app_name'
862
863
manager = Mock()
864
manager.attach_mock(s_or_e, "s_or_e_mock")
865
manager.mock_adb = mock_adb
866
867
Adb.clear_app_data(device_id, name)
868
869
expected_calls = [call.mock_adb.set_target_by_name(123),
870
call.mock_adb.shell_command('pm clear app_name'),
871
call.s_or_e_mock('succes', '{}: Data of "{}" cleared'.format(device_id, name),
872
'{}: Failed to clear data for "{}"'.format(device_id, name))]
873
assert manager.mock_calls == expected_calls
874
875
@patch('logging.Logger.info')
876
def test_success_or_exception_succes(self, logger):
877
input_string = 'Success'
878
succes_msg = 'action succes'
879
fail_msg = 'action fail'
880
881
Adb.success_or_exception(input_string, succes_msg, fail_msg)
882
883
logger.assert_called_once_with(succes_msg)
884
885
@patch('logging.Logger.info')
886
def test_success_or_exception_exception(self, logger):
887
input_string = 'fail'
888
succes_msg = 'action succes'
889
fail_msg = 'action fail'
890
891
with pytest.raises(Adb.AdbError):
892
Adb.success_or_exception(input_string, succes_msg, fail_msg)
893
894
logger.assert_called_once_with(fail_msg + '\nMessage returned:\n{}'.format(input_string))
895
896
def test_push(self):
897
mock_adb = Mock()
898
mock_adb._ADB__output = 'push output'
899
Adb.adb = mock_adb
900
901
device_id = 123
902
local_path = 'local/path'
903
remote_path = 'remote/path'
904
905
result = Adb.push(device_id, local_path, remote_path)
906
907
assert result == 'push output'
908
expected_calls = [call.set_target_by_name(device_id),
909
call.run_cmd('push {} {}'.format(local_path, remote_path))]
910
assert mock_adb.mock_calls == expected_calls
911
912
def test_pull_no_error(self):
913
mock_adb = Mock()
914
mock_adb._ADB__output = 'pull output'
915
mock_adb._ADB__error = None
916
Adb.adb = mock_adb
917
918
device_id = 123
919
local_path = 'local/path'
920
remote_path = 'remote/path'
921
922
result = Adb.pull(device_id, remote_path, local_path)
923
924
assert result == 'pull output'
925
expected_calls = [call.set_target_by_name(device_id),
926
call.run_cmd('pull {} {}'.format(remote_path, local_path))]
927
assert mock_adb.mock_calls == expected_calls
928
929
def test_pull_error_no_bytes_in(self):
930
mock_adb = Mock()
931
mock_adb._ADB__output = 'pull output'
932
mock_adb._ADB__error = 'error error'
933
Adb.adb = mock_adb
934
935
device_id = 123
936
local_path = 'local/path'
937
remote_path = 'remote/path'
938
939
result = Adb.pull(device_id, remote_path, local_path)
940
941
assert result == 'pull output'
942
expected_calls = [call.set_target_by_name(device_id),
943
call.run_cmd('pull {} {}'.format(remote_path, local_path))]
944
assert mock_adb.mock_calls == expected_calls
945
946
def test_pull_error_with_bytes_in(self):
947
mock_adb = Mock()
948
mock_adb._ADB__output = 'pull output'
949
mock_adb._ADB__error = 'bytes in error'
950
Adb.adb = mock_adb
951
952
device_id = 123
953
local_path = 'local/path'
954
remote_path = 'remote/path'
955
956
result = Adb.pull(device_id, remote_path, local_path)
957
958
assert result == 'bytes in error'
959
expected_calls = [call.set_target_by_name(device_id),
960
call.run_cmd('pull {} {}'.format(remote_path, local_path))]
961
assert mock_adb.mock_calls == expected_calls
962
963
def test_logcat_no_regex(self):
964
mock_adb = Mock()
965
mock_adb.return_value = 'get_logcat output'
966
Adb.shell = mock_adb
967
968
device_id = 123
969
970
result = Adb.logcat(device_id)
971
972
assert result == 'get_logcat output'
973
expected_calls = [call.shell(device_id, f"logcat -d")]
974
assert mock_adb.mock_calls == expected_calls
975
976
def test_logcat_with_regex(self):
977
mock_adb = Mock()
978
mock_adb.return_value = 'get_logcat output'
979
Adb.shell = mock_adb
980
981
test_regex = '[a-zA-Z]+'
982
device_id = 123
983
984
result = Adb.logcat(device_id, test_regex)
985
986
assert result == 'get_logcat output'
987
expected_calls = [call.shell(device_id, f'logcat -d | grep "{test_regex}"')]
988
assert mock_adb.mock_calls == expected_calls
989
990
def test_reset_true(self):
991
Adb.adb = Mock()
992
cmd = True
993
Adb.reset(cmd)
994
expected_calls = [call.kill_server(), call.get_devices()]
995
assert Adb.adb.mock_calls == expected_calls
996
997
def test_reset_false(self):
998
Adb.adb = Mock()
999
cmd = False
1000
Adb.reset(cmd)
1001
expected_calls = []
1002
assert Adb.adb.mock_calls == expected_calls
1003
1004
@patch('AndroidRunner.Adb.shell')
1005
def test_configure_settings(self, shell):
1006
Adb.adb = Mock()
1007
device_id = 123
1008
setting1 = "location_high_accuracy"
1009
setting2 = "location_gps_only"
1010
Adb.configure_settings(device_id, setting1, enable=True)
1011
shell.assert_called_with(123, "settings put secure location_providers_allowed +gps,network")
1012
Adb.configure_settings(device_id, setting2, enable=False)
1013
shell.assert_called_with(123, "settings put secure location_providers_allowed -gps")
1014
1015