diff options
author | Eric Lin (Tzu Hsiang Lin) <ericth@google.com> | 2021-01-13 23:02:47 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-13 23:02:47 +0800 |
commit | 8eb87e0a1099f14526a6378803940fc1d79bfa2d (patch) | |
tree | 392a3d8ea9f01db34cb0d8ba34b14c2d8df6b991 /tests/mobly/controllers | |
parent | e09ecd407146cdcf88b26269af3b9636bdfd87a1 (diff) | |
download | mobly-8eb87e0a1099f14526a6378803940fc1d79bfa2d.tar.gz |
Move to 2-space indent: AndroidDevice related test files. (#709)
Pure shortening of the indentation length, no actual code change.
Diffstat (limited to 'tests/mobly/controllers')
13 files changed, 2845 insertions, 2845 deletions
diff --git a/tests/mobly/controllers/android_device_lib/adb_test.py b/tests/mobly/controllers/android_device_lib/adb_test.py index e920bbd..36e207a 100755 --- a/tests/mobly/controllers/android_device_lib/adb_test.py +++ b/tests/mobly/controllers/android_device_lib/adb_test.py @@ -24,27 +24,27 @@ from mobly.controllers.android_device_lib import adb MOCK_INSTRUMENTATION_PACKAGE = 'com.my.instrumentation.tests' MOCK_INSTRUMENTATION_RUNNER = 'com.my.instrumentation.runner' MOCK_INSTRUMENTATION_OPTIONS = OrderedDict([ - ('option1', 'value1'), - ('option2', 'value2'), + ('option1', 'value1'), + ('option2', 'value2'), ]) # Mock android instrumentation commands. MOCK_BASIC_INSTRUMENTATION_COMMAND = ('am instrument -r -w com.my' - '.instrumentation.tests/com.android' - '.common.support.test.runner' - '.AndroidJUnitRunner') + '.instrumentation.tests/com.android' + '.common.support.test.runner' + '.AndroidJUnitRunner') MOCK_RUNNER_INSTRUMENTATION_COMMAND = ('am instrument -r -w com.my' - '.instrumentation.tests/com.my' - '.instrumentation.runner') + '.instrumentation.tests/com.my' + '.instrumentation.runner') MOCK_OPTIONS_INSTRUMENTATION_COMMAND = ('am instrument -r -w -e option1 value1' - ' -e option2 value2 com.my' - '.instrumentation.tests/com.android' - '.common.support.test.runner' - '.AndroidJUnitRunner') + ' -e option2 value2 com.my' + '.instrumentation.tests/com.android' + '.common.support.test.runner' + '.AndroidJUnitRunner') # Mock root command outputs. MOCK_ROOT_SUCCESS_OUTPUT = 'adbd is already running as root' MOCK_ROOT_ERROR_OUTPUT = ( - 'adb: unable to connect for root: closed'.encode('utf-8')) + 'adb: unable to connect for root: closed'.encode('utf-8')) # Mock Shell Command MOCK_SHELL_COMMAND = 'ls' @@ -56,781 +56,781 @@ MOCK_ADB_SHELL_COMMAND_CHECK = 'adb shell command -v ls' class AdbTest(unittest.TestCase): - """Unit tests for mobly.controllers.android_device_lib.adb. - """ - - def _mock_process(self, mock_psutil_process, mock_popen): - # the created proc object in adb._exec_cmd() - mock_proc = mock.Mock() - mock_popen.return_value = mock_proc - - # the created process object in adb._exec_cmd() - mock_psutil_process.return_value = mock.Mock() - - mock_proc.communicate = mock.Mock( - return_value=(MOCK_DEFAULT_STDOUT.encode('utf-8'), - MOCK_DEFAULT_STDERR.encode('utf-8'))) - mock_proc.returncode = 0 - return (mock_psutil_process, mock_popen) - - def _mock_execute_and_process_stdout_process(self, mock_popen): - # the created proc object in adb._execute_and_process_stdout() - mock_proc = mock.Mock() - mock_popen.return_value = mock_proc - - mock_popen.return_value.stdout.readline.side_effect = [''] - - mock_proc.communicate = mock.Mock( - return_value=('', MOCK_DEFAULT_STDERR.encode('utf-8'))) - mock_proc.returncode = 0 - return mock_popen - - @mock.patch('mobly.utils.run_command') - def test_exec_cmd_no_timeout_success(self, mock_run_command): - mock_run_command.return_value = (0, - MOCK_DEFAULT_STDOUT.encode('utf-8'), - MOCK_DEFAULT_STDERR.encode('utf-8')) - out = adb.AdbProxy()._exec_cmd(['fake_cmd'], - shell=False, - timeout=None, - stderr=None) - self.assertEqual(MOCK_DEFAULT_STDOUT, out.decode('utf-8')) - mock_run_command.assert_called_with(['fake_cmd'], - shell=False, - timeout=None) - - @mock.patch('mobly.utils.run_command') - def test_exec_cmd_error_with_serial(self, mock_run_command): - # Return 1 for retcode for error. - mock_run_command.return_value = (1, - MOCK_DEFAULT_STDOUT.encode('utf-8'), - MOCK_DEFAULT_STDERR.encode('utf-8')) - mock_serial = 'ABCD1234' - with self.assertRaisesRegex(adb.AdbError, - 'Error executing adb cmd .*') as context: - adb.AdbProxy(mock_serial).fake_cmd() - self.assertEqual(context.exception.serial, mock_serial) - self.assertIn(mock_serial, context.exception.cmd) - - @mock.patch('mobly.utils.run_command') - def test_exec_cmd_error_without_serial(self, mock_run_command): - # Return 1 for retcode for error. - mock_run_command.return_value = (1, - MOCK_DEFAULT_STDOUT.encode('utf-8'), - MOCK_DEFAULT_STDERR.encode('utf-8')) - with self.assertRaisesRegex(adb.AdbError, - 'Error executing adb cmd .*') as context: - adb.AdbProxy()._exec_cmd(['fake_cmd'], - shell=False, - timeout=None, - stderr=None) - self.assertFalse(context.exception.serial) - mock_run_command.assert_called_with(['fake_cmd'], - shell=False, - timeout=None) - - @mock.patch('mobly.utils.run_command') - def test_exec_cmd_with_timeout_success(self, mock_run_command): - mock_run_command.return_value = (0, - MOCK_DEFAULT_STDOUT.encode('utf-8'), - MOCK_DEFAULT_STDERR.encode('utf-8')) - - out = adb.AdbProxy()._exec_cmd(['fake_cmd'], - shell=False, - timeout=1, - stderr=None) - self.assertEqual(MOCK_DEFAULT_STDOUT, out.decode('utf-8')) - mock_run_command.assert_called_with(['fake_cmd'], - shell=False, - timeout=1) - - @mock.patch('mobly.utils.run_command') - def test_exec_cmd_timed_out(self, mock_run_command): - mock_run_command.side_effect = adb.psutil.TimeoutExpired('Timed out') - mock_serial = '1234Abcd' - with self.assertRaisesRegex( - adb.AdbTimeoutError, 'Timed out executing command "adb -s ' - '1234Abcd fake-cmd" after 0.01s.') as context: - adb.AdbProxy(mock_serial).fake_cmd(timeout=0.01) - self.assertEqual(context.exception.serial, mock_serial) - self.assertIn(mock_serial, context.exception.cmd) - - @mock.patch('mobly.utils.run_command') - def test_exec_cmd_timed_out_without_serial(self, mock_run_command): - mock_run_command.side_effect = adb.psutil.TimeoutExpired('Timed out') - with self.assertRaisesRegex( - adb.AdbTimeoutError, 'Timed out executing command "adb ' - 'fake-cmd" after 0.01s.') as context: - adb.AdbProxy().fake_cmd(timeout=0.01) - - def test_exec_cmd_with_negative_timeout_value(self): - with self.assertRaisesRegex(ValueError, - 'Timeout is not a positive value: -1'): - adb.AdbProxy()._exec_cmd(['fake_cmd'], - shell=False, - timeout=-1, - stderr=None) - - @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') - def test_execute_and_process_stdout_reads_stdout(self, mock_popen): - self._mock_execute_and_process_stdout_process(mock_popen) - mock_popen.return_value.stdout.readline.side_effect = ['1', '2', ''] + """Unit tests for mobly.controllers.android_device_lib.adb. + """ + + def _mock_process(self, mock_psutil_process, mock_popen): + # the created proc object in adb._exec_cmd() + mock_proc = mock.Mock() + mock_popen.return_value = mock_proc + + # the created process object in adb._exec_cmd() + mock_psutil_process.return_value = mock.Mock() + + mock_proc.communicate = mock.Mock( + return_value=(MOCK_DEFAULT_STDOUT.encode('utf-8'), + MOCK_DEFAULT_STDERR.encode('utf-8'))) + mock_proc.returncode = 0 + return (mock_psutil_process, mock_popen) + + def _mock_execute_and_process_stdout_process(self, mock_popen): + # the created proc object in adb._execute_and_process_stdout() + mock_proc = mock.Mock() + mock_popen.return_value = mock_proc + + mock_popen.return_value.stdout.readline.side_effect = [''] + + mock_proc.communicate = mock.Mock( + return_value=('', MOCK_DEFAULT_STDERR.encode('utf-8'))) + mock_proc.returncode = 0 + return mock_popen + + @mock.patch('mobly.utils.run_command') + def test_exec_cmd_no_timeout_success(self, mock_run_command): + mock_run_command.return_value = (0, + MOCK_DEFAULT_STDOUT.encode('utf-8'), + MOCK_DEFAULT_STDERR.encode('utf-8')) + out = adb.AdbProxy()._exec_cmd(['fake_cmd'], + shell=False, + timeout=None, + stderr=None) + self.assertEqual(MOCK_DEFAULT_STDOUT, out.decode('utf-8')) + mock_run_command.assert_called_with(['fake_cmd'], + shell=False, + timeout=None) + + @mock.patch('mobly.utils.run_command') + def test_exec_cmd_error_with_serial(self, mock_run_command): + # Return 1 for retcode for error. + mock_run_command.return_value = (1, + MOCK_DEFAULT_STDOUT.encode('utf-8'), + MOCK_DEFAULT_STDERR.encode('utf-8')) + mock_serial = 'ABCD1234' + with self.assertRaisesRegex(adb.AdbError, + 'Error executing adb cmd .*') as context: + adb.AdbProxy(mock_serial).fake_cmd() + self.assertEqual(context.exception.serial, mock_serial) + self.assertIn(mock_serial, context.exception.cmd) + + @mock.patch('mobly.utils.run_command') + def test_exec_cmd_error_without_serial(self, mock_run_command): + # Return 1 for retcode for error. + mock_run_command.return_value = (1, + MOCK_DEFAULT_STDOUT.encode('utf-8'), + MOCK_DEFAULT_STDERR.encode('utf-8')) + with self.assertRaisesRegex(adb.AdbError, + 'Error executing adb cmd .*') as context: + adb.AdbProxy()._exec_cmd(['fake_cmd'], + shell=False, + timeout=None, + stderr=None) + self.assertFalse(context.exception.serial) + mock_run_command.assert_called_with(['fake_cmd'], + shell=False, + timeout=None) + + @mock.patch('mobly.utils.run_command') + def test_exec_cmd_with_timeout_success(self, mock_run_command): + mock_run_command.return_value = (0, + MOCK_DEFAULT_STDOUT.encode('utf-8'), + MOCK_DEFAULT_STDERR.encode('utf-8')) + + out = adb.AdbProxy()._exec_cmd(['fake_cmd'], + shell=False, + timeout=1, + stderr=None) + self.assertEqual(MOCK_DEFAULT_STDOUT, out.decode('utf-8')) + mock_run_command.assert_called_with(['fake_cmd'], + shell=False, + timeout=1) + + @mock.patch('mobly.utils.run_command') + def test_exec_cmd_timed_out(self, mock_run_command): + mock_run_command.side_effect = adb.psutil.TimeoutExpired('Timed out') + mock_serial = '1234Abcd' + with self.assertRaisesRegex( + adb.AdbTimeoutError, 'Timed out executing command "adb -s ' + '1234Abcd fake-cmd" after 0.01s.') as context: + adb.AdbProxy(mock_serial).fake_cmd(timeout=0.01) + self.assertEqual(context.exception.serial, mock_serial) + self.assertIn(mock_serial, context.exception.cmd) + + @mock.patch('mobly.utils.run_command') + def test_exec_cmd_timed_out_without_serial(self, mock_run_command): + mock_run_command.side_effect = adb.psutil.TimeoutExpired('Timed out') + with self.assertRaisesRegex( + adb.AdbTimeoutError, 'Timed out executing command "adb ' + 'fake-cmd" after 0.01s.') as context: + adb.AdbProxy().fake_cmd(timeout=0.01) + + def test_exec_cmd_with_negative_timeout_value(self): + with self.assertRaisesRegex(ValueError, + 'Timeout is not a positive value: -1'): + adb.AdbProxy()._exec_cmd(['fake_cmd'], + shell=False, + timeout=-1, + stderr=None) + + @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') + def test_execute_and_process_stdout_reads_stdout(self, mock_popen): + self._mock_execute_and_process_stdout_process(mock_popen) + mock_popen.return_value.stdout.readline.side_effect = ['1', '2', ''] + mock_handler = mock.MagicMock() + + err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'], + shell=False, + handler=mock_handler) + self.assertEqual(mock_handler.call_count, 2) + mock_handler.assert_any_call('1') + mock_handler.assert_any_call('2') + + @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') + def test_execute_and_process_stdout_reads_unexpected_stdout( + self, mock_popen): + unexpected_stdout = MOCK_DEFAULT_STDOUT.encode('utf-8') + + self._mock_execute_and_process_stdout_process(mock_popen) + mock_handler = mock.MagicMock() + mock_popen.return_value.communicate = mock.Mock( + return_value=(unexpected_stdout, + MOCK_DEFAULT_STDERR.encode('utf-8'))) + + err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'], + shell=False, + handler=mock_handler) + self.assertEqual(mock_handler.call_count, 1) + mock_handler.assert_called_with(unexpected_stdout) + + @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') + @mock.patch('logging.debug') + def test_execute_and_process_stdout_logs_cmd(self, mock_debug_logger, + mock_popen): + raw_expected_stdout = '' + expected_stdout = '[elided, processed via handler]' + expected_stderr = MOCK_DEFAULT_STDERR.encode('utf-8') + self._mock_execute_and_process_stdout_process(mock_popen) + mock_popen.return_value.communicate = mock.Mock( + return_value=(raw_expected_stdout, expected_stderr)) + + err = adb.AdbProxy()._execute_and_process_stdout( + ['fake_cmd'], shell=False, handler=mock.MagicMock()) + mock_debug_logger.assert_called_with( + 'cmd: %s, stdout: %s, stderr: %s, ret: %s', 'fake_cmd', + expected_stdout, expected_stderr, 0) + + @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') + @mock.patch('logging.debug') + def test_execute_and_process_stdout_logs_cmd_with_unexpected_stdout( + self, mock_debug_logger, mock_popen): + raw_expected_stdout = MOCK_DEFAULT_STDOUT.encode('utf-8') + expected_stdout = '[unexpected stdout] %s' % raw_expected_stdout + expected_stderr = MOCK_DEFAULT_STDERR.encode('utf-8') + + self._mock_execute_and_process_stdout_process(mock_popen) + mock_popen.return_value.communicate = mock.Mock( + return_value=(raw_expected_stdout, expected_stderr)) + + err = adb.AdbProxy()._execute_and_process_stdout( + ['fake_cmd'], shell=False, handler=mock.MagicMock()) + mock_debug_logger.assert_called_with( + 'cmd: %s, stdout: %s, stderr: %s, ret: %s', 'fake_cmd', + expected_stdout, expected_stderr, 0) + + @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') + def test_execute_and_process_stdout_despite_cmd_exits(self, mock_popen): + self._mock_execute_and_process_stdout_process(mock_popen) + mock_popen.return_value.poll.side_effect = [None, 0] + mock_popen.return_value.stdout.readline.side_effect = [ + '1', '2', '3', '' + ] + mock_handler = mock.MagicMock() + + err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'], + shell=False, + handler=mock_handler) + + self.assertEqual(mock_handler.call_count, 3) + mock_handler.assert_any_call('1') + mock_handler.assert_any_call('2') + mock_handler.assert_any_call('3') + + @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') + def test_execute_and_process_stdout_when_cmd_eof(self, mock_popen): + self._mock_execute_and_process_stdout_process(mock_popen) + mock_popen.return_value.stdout.readline.side_effect = [ + '1', '2', '3', '' + ] + mock_handler = mock.MagicMock() + + err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'], + shell=False, + handler=mock_handler) + + self.assertEqual(mock_handler.call_count, 3) + mock_handler.assert_any_call('1') + mock_handler.assert_any_call('2') + mock_handler.assert_any_call('3') + + @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') + def test_execute_and_process_stdout_returns_stderr(self, mock_popen): + self._mock_execute_and_process_stdout_process(mock_popen) + + err = adb.AdbProxy()._execute_and_process_stdout( + ['fake_cmd'], shell=False, handler=mock.MagicMock()) + self.assertEqual(MOCK_DEFAULT_STDERR, err.decode('utf-8')) + + @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') + def test_execute_and_process_stdout_raises_adb_error(self, mock_popen): + self._mock_execute_and_process_stdout_process(mock_popen) + mock_popen.return_value.returncode = 1 + + with self.assertRaisesRegex(adb.AdbError, + 'Error executing adb cmd .*'): + err = adb.AdbProxy()._execute_and_process_stdout( + ['fake_cmd'], shell=False, handler=mock.MagicMock()) + + @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') + def test_execute_and_process_stdout_when_handler_crash(self, mock_popen): + self._mock_execute_and_process_stdout_process(mock_popen) + mock_popen.return_value.stdout.readline.side_effect = [ + '1', '2', '3', '' + ] + mock_handler = mock.MagicMock() + mock_handler.side_effect = ['', TypeError('fake crash'), '', ''] + + with self.assertRaisesRegex(TypeError, 'fake crash'): + err = adb.AdbProxy()._execute_and_process_stdout( + ['fake_cmd'], shell=False, handler=mock_handler) + + mock_popen.return_value.communicate.assert_called_once_with() + + def test_construct_adb_cmd(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', + 'arg1', + shell=False) + self.assertEqual(adb_cmd, ['adb', 'shell', 'arg1']) + + def test_construct_adb_cmd_with_one_command(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd( + 'shell ls /asdafsfd/asdf-asfd/asa', [], shell=False) + self.assertEqual(adb_cmd, ['adb', 'shell ls /asdafsfd/asdf-asfd/asa']) + + def test_construct_adb_cmd_with_one_arg_command(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd( + 'shell', 'ls /asdafsfd/asdf-asfd/asa', shell=False) + self.assertEqual(adb_cmd, + ['adb', 'shell', 'ls /asdafsfd/asdf-asfd/asa']) + + def test_construct_adb_cmd_with_one_arg_command_list(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd( + 'shell', ['ls /asdafsfd/asdf-asfd/asa'], shell=False) + self.assertEqual(adb_cmd, + ['adb', 'shell', 'ls /asdafsfd/asdf-asfd/asa']) + + def test_construct_adb_cmd_with_special_characters(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', + ['a b', '"blah"', r'\/\/'], + shell=False) + self.assertEqual(adb_cmd, ['adb', 'shell', 'a b', '"blah"', r"\/\/"]) + + def test_construct_adb_cmd_with_serial(self): + adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell', + 'arg1', + shell=False) + self.assertEqual(adb_cmd, ['adb', '-s', '12345', 'shell', 'arg1']) + + def test_construct_adb_cmd_with_list(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', ['arg1', 'arg2'], + shell=False) + self.assertEqual(adb_cmd, ['adb', 'shell', 'arg1', 'arg2']) + + def test_construct_adb_cmd_with_serial_with_list(self): + adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell', + ['arg1', 'arg2'], + shell=False) + self.assertEqual(adb_cmd, + ['adb', '-s', '12345', 'shell', 'arg1', 'arg2']) + + def test_construct_adb_cmd_with_shell_true(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', + 'arg1 arg2', + shell=True) + self.assertEqual(adb_cmd, '"adb" shell arg1 arg2') + + def test_construct_adb_cmd_with_shell_true_with_one_command(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd( + 'shell ls /asdafsfd/asdf-asfd/asa', [], shell=True) + self.assertEqual(adb_cmd, '"adb" shell ls /asdafsfd/asdf-asfd/asa ') + + def test_construct_adb_cmd_with_shell_true_with_one_arg_command(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd( + 'shell', 'ls /asdafsfd/asdf-asfd/asa', shell=True) + self.assertEqual(adb_cmd, '"adb" shell ls /asdafsfd/asdf-asfd/asa') + + def test_construct_adb_cmd_with_shell_true_with_one_arg_command_list(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd( + 'shell', ['ls /asdafsfd/asdf-asfd/asa'], shell=True) + self.assertEqual(adb_cmd, '"adb" shell \'ls /asdafsfd/asdf-asfd/asa\'') + + def test_construct_adb_cmd_with_shell_true_with_auto_quotes(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', + ['a b', '"blah"', r'\/\/'], + shell=True) + self.assertEqual(adb_cmd, '"adb" shell \'a b\' \'"blah"\' \'\\/\\/\'') + + def test_construct_adb_cmd_with_shell_true_with_serial(self): + adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell', + 'arg1 arg2', + shell=True) + self.assertEqual(adb_cmd, '"adb" -s "12345" shell arg1 arg2') + + def test_construct_adb_cmd_with_shell_true_with_list(self): + adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', ['arg1', 'arg2'], + shell=True) + self.assertEqual(adb_cmd, '"adb" shell arg1 arg2') + + def test_construct_adb_cmd_with_shell_true_with_serial_with_list(self): + adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell', + ['arg1', 'arg2'], + shell=True) + self.assertEqual(adb_cmd, '"adb" -s "12345" shell arg1 arg2') + + def test_exec_adb_cmd(self): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT + adb.AdbProxy().shell(['arg1', 'arg2']) + mock_exec_cmd.assert_called_once_with( + ['adb', 'shell', 'arg1', 'arg2'], + shell=False, + timeout=None, + stderr=None) + + def test_exec_adb_cmd_with_shell_true(self): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT + adb.AdbProxy().shell('arg1 arg2', shell=True) + mock_exec_cmd.assert_called_once_with('"adb" shell arg1 arg2', + shell=True, + timeout=None, + stderr=None) + + def test_exec_adb_cmd_formats_command(self): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + with mock.patch.object( + adb.AdbProxy, + '_construct_adb_cmd') as mock_construct_adb_cmd: + mock_adb_cmd = mock.MagicMock() + mock_adb_args = mock.MagicMock() + mock_construct_adb_cmd.return_value = mock_adb_cmd + mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT + + adb.AdbProxy().shell(mock_adb_args) + mock_construct_adb_cmd.assert_called_once_with('shell', + mock_adb_args, + shell=False) + mock_exec_cmd.assert_called_once_with(mock_adb_cmd, + shell=False, + timeout=None, + stderr=None) + + def test_exec_adb_cmd_formats_command_with_shell_true(self): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + with mock.patch.object( + adb.AdbProxy, + '_construct_adb_cmd') as mock_construct_adb_cmd: + mock_adb_cmd = mock.MagicMock() + mock_adb_args = mock.MagicMock() + mock_construct_adb_cmd.return_value = mock_adb_cmd + + adb.AdbProxy().shell(mock_adb_args, shell=True) + mock_construct_adb_cmd.assert_called_once_with('shell', + mock_adb_args, + shell=True) + mock_exec_cmd.assert_called_once_with(mock_adb_cmd, + shell=True, + timeout=None, + stderr=None) + + def test_execute_adb_and_process_stdout_formats_command(self): + with mock.patch.object(adb.AdbProxy, '_execute_and_process_stdout' + ) as mock_execute_and_process_stdout: + with mock.patch.object( + adb.AdbProxy, + '_construct_adb_cmd') as mock_construct_adb_cmd: + mock_adb_cmd = mock.MagicMock() + mock_adb_args = mock.MagicMock() mock_handler = mock.MagicMock() + mock_construct_adb_cmd.return_value = mock_adb_cmd + + adb.AdbProxy()._execute_adb_and_process_stdout( + 'shell', mock_adb_args, shell=False, handler=mock_handler) + mock_construct_adb_cmd.assert_called_once_with('shell', + mock_adb_args, + shell=False) + mock_execute_and_process_stdout.assert_called_once_with( + mock_adb_cmd, shell=False, handler=mock_handler) + + @mock.patch('mobly.utils.run_command') + def test_exec_adb_cmd_with_stderr_pipe(self, mock_run_command): + mock_run_command.return_value = (0, + MOCK_DEFAULT_STDOUT.encode('utf-8'), + MOCK_DEFAULT_STDERR.encode('utf-8')) + stderr_redirect = io.BytesIO() + out = adb.AdbProxy().shell('arg1 arg2', + shell=True, + stderr=stderr_redirect) + self.assertEqual(MOCK_DEFAULT_STDOUT, out.decode('utf-8')) + self.assertEqual(MOCK_DEFAULT_STDERR, + stderr_redirect.getvalue().decode('utf-8')) + + def test_getprop(self): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + mock_exec_cmd.return_value = b'blah' + self.assertEqual(adb.AdbProxy().getprop('haha'), 'blah') + mock_exec_cmd.assert_called_once_with( + ['adb', 'shell', 'getprop', 'haha'], + shell=False, + stderr=None, + timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC) + + def test__parse_getprop_output_special_values(self): + mock_adb_output = ( + b'[selinux.restorecon_recursive]: [/data/misc_ce/10]\n' + b'[selinux.abc]: [key: value]\n' # "key: value" as value + b'[persist.sys.boot.reason.history]: [reboot,adb,1558549857\n' + b'reboot,factory_reset,1558483886\n' # multi-line value + b'reboot,1558483823]\n' + b'[persist.something]: [haha\n' + b']\n' + b'[[wrapped.key]]: [[wrapped value]]\n' + b'[persist.byte]: [J\xaa\x8bb\xab\x9dP\x0f]\n' # non-decodable + ) + parsed_props = adb.AdbProxy()._parse_getprop_output(mock_adb_output) + expected_output = { + 'persist.sys.boot.reason.history': + ('reboot,adb,1558549857\nreboot,factory_reset,1558483886\n' + 'reboot,1558483823'), + 'selinux.abc': + 'key: value', + 'persist.something': + 'haha\n', + 'selinux.restorecon_recursive': + '/data/misc_ce/10', + '[wrapped.key]': + '[wrapped value]', + 'persist.byte': + 'JbP\x0f', + } + self.assertEqual(parsed_props, expected_output) + + def test__parse_getprop_output_malformat_output(self): + mock_adb_output = ( + b'[selinux.restorecon_recursive][/data/misc_ce/10]\n' # Malformat + b'[persist.sys.boot.reason]: [reboot,adb,1558549857]\n' + b'[persist.something]: [haha]\n') + parsed_props = adb.AdbProxy()._parse_getprop_output(mock_adb_output) + expected_output = { + 'persist.sys.boot.reason': 'reboot,adb,1558549857', + 'persist.something': 'haha' + } + self.assertEqual(parsed_props, expected_output) + + def test__parse_getprop_output_special_line_separator(self): + mock_adb_output = ( + b'[selinux.restorecon_recursive][/data/misc_ce/10]\r\n' # Malformat + b'[persist.sys.boot.reason]: [reboot,adb,1558549857]\r\n' + b'[persist.something]: [haha]\r\n') + parsed_props = adb.AdbProxy()._parse_getprop_output(mock_adb_output) + expected_output = { + 'persist.sys.boot.reason': 'reboot,adb,1558549857', + 'persist.something': 'haha' + } + self.assertEqual(parsed_props, expected_output) + + @mock.patch('time.sleep', return_value=mock.MagicMock()) + def test_getprops(self, mock_sleep): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + mock_exec_cmd.return_value = ( + b'\n[sendbug.preferred.domain]: [google.com]\n' + b'[sys.uidcpupower]: []\n' + b'[sys.wifitracing.started]: [1]\n' + b'[telephony.lteOnCdmaDevice]: [1]\n\n') + actual_output = adb.AdbProxy().getprops([ + 'sys.wifitracing.started', # "numeric" value + 'sys.uidcpupower', # empty value + 'sendbug.preferred.domain', # string value + 'nonExistentProp' + ]) + self.assertEqual( + actual_output, { + 'sys.wifitracing.started': '1', + 'sys.uidcpupower': '', + 'sendbug.preferred.domain': 'google.com' + }) + mock_exec_cmd.assert_called_once_with( + ['adb', 'shell', 'getprop'], + shell=False, + stderr=None, + timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC) + mock_sleep.assert_not_called() + + @mock.patch('time.sleep', return_value=mock.MagicMock()) + def test_getprops_when_empty_string_randomly_returned(self, mock_sleep): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + mock_exec_cmd.side_effect = [ + b'', + (b'\n[ro.build.id]: [AB42]\n' + b'[ro.build.type]: [userdebug]\n\n') + ] + actual_output = adb.AdbProxy().getprops(['ro.build.id']) + self.assertEqual(actual_output, { + 'ro.build.id': 'AB42', + }) + self.assertEqual(mock_exec_cmd.call_count, 2) + mock_exec_cmd.assert_called_with( + ['adb', 'shell', 'getprop'], + shell=False, + stderr=None, + timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC) + self.assertEqual(mock_sleep.call_count, 1) + mock_sleep.assert_called_with(1) + + @mock.patch('time.sleep', return_value=mock.MagicMock()) + def test_getprops_when_empty_string_always_returned(self, mock_sleep): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + mock_exec_cmd.return_value = b'' + actual_output = adb.AdbProxy().getprops(['ro.build.id']) + self.assertEqual(actual_output, {}) + self.assertEqual(mock_exec_cmd.call_count, 3) + mock_exec_cmd.assert_called_with( + ['adb', 'shell', 'getprop'], + shell=False, + stderr=None, + timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC) + self.assertEqual(mock_sleep.call_count, 2) + mock_sleep.assert_called_with(1) + + def test_forward(self): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + adb.AdbProxy().forward(MOCK_SHELL_COMMAND) + + def test_instrument_without_parameters(self): + """Verifies the AndroidDevice object's instrument command is correct in + the basic case. + """ + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + output = adb.AdbProxy().instrument(MOCK_INSTRUMENTATION_PACKAGE) + mock_exec_cmd.assert_called_once_with( + ['adb', 'shell', MOCK_BASIC_INSTRUMENTATION_COMMAND], + shell=False, + timeout=None, + stderr=None) + self.assertEqual(output, mock_exec_cmd.return_value) + + def test_instrument_with_runner(self): + """Verifies the AndroidDevice object's instrument command is correct + with a runner specified. + """ + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + stdout = adb.AdbProxy().instrument( + MOCK_INSTRUMENTATION_PACKAGE, + runner=MOCK_INSTRUMENTATION_RUNNER) + mock_exec_cmd.assert_called_once_with( + ['adb', 'shell', MOCK_RUNNER_INSTRUMENTATION_COMMAND], + shell=False, + timeout=None, + stderr=None) + self.assertEqual(stdout, mock_exec_cmd.return_value) + + def test_instrument_with_options(self): + """Verifies the AndroidDevice object's instrument command is correct + with options. + """ + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + stdout = adb.AdbProxy().instrument( + MOCK_INSTRUMENTATION_PACKAGE, + options=MOCK_INSTRUMENTATION_OPTIONS) + mock_exec_cmd.assert_called_once_with( + ['adb', 'shell', MOCK_OPTIONS_INSTRUMENTATION_COMMAND], + shell=False, + timeout=None, + stderr=None) + self.assertEqual(stdout, mock_exec_cmd.return_value) + + def test_instrument_with_handler(self): + """Verifies the AndroidDevice object's instrument command is correct + with a handler passed in. + """ - err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'], - shell=False, - handler=mock_handler) - self.assertEqual(mock_handler.call_count, 2) - mock_handler.assert_any_call('1') - mock_handler.assert_any_call('2') - - @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') - def test_execute_and_process_stdout_reads_unexpected_stdout( - self, mock_popen): - unexpected_stdout = MOCK_DEFAULT_STDOUT.encode('utf-8') - - self._mock_execute_and_process_stdout_process(mock_popen) - mock_handler = mock.MagicMock() - mock_popen.return_value.communicate = mock.Mock( - return_value=(unexpected_stdout, - MOCK_DEFAULT_STDERR.encode('utf-8'))) - - err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'], - shell=False, - handler=mock_handler) - self.assertEqual(mock_handler.call_count, 1) - mock_handler.assert_called_with(unexpected_stdout) - - @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') - @mock.patch('logging.debug') - def test_execute_and_process_stdout_logs_cmd(self, mock_debug_logger, - mock_popen): - raw_expected_stdout = '' - expected_stdout = '[elided, processed via handler]' - expected_stderr = MOCK_DEFAULT_STDERR.encode('utf-8') - self._mock_execute_and_process_stdout_process(mock_popen) - mock_popen.return_value.communicate = mock.Mock( - return_value=(raw_expected_stdout, expected_stderr)) - - err = adb.AdbProxy()._execute_and_process_stdout( - ['fake_cmd'], shell=False, handler=mock.MagicMock()) - mock_debug_logger.assert_called_with( - 'cmd: %s, stdout: %s, stderr: %s, ret: %s', 'fake_cmd', - expected_stdout, expected_stderr, 0) - - @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') - @mock.patch('logging.debug') - def test_execute_and_process_stdout_logs_cmd_with_unexpected_stdout( - self, mock_debug_logger, mock_popen): - raw_expected_stdout = MOCK_DEFAULT_STDOUT.encode('utf-8') - expected_stdout = '[unexpected stdout] %s' % raw_expected_stdout - expected_stderr = MOCK_DEFAULT_STDERR.encode('utf-8') - - self._mock_execute_and_process_stdout_process(mock_popen) - mock_popen.return_value.communicate = mock.Mock( - return_value=(raw_expected_stdout, expected_stderr)) - - err = adb.AdbProxy()._execute_and_process_stdout( - ['fake_cmd'], shell=False, handler=mock.MagicMock()) - mock_debug_logger.assert_called_with( - 'cmd: %s, stdout: %s, stderr: %s, ret: %s', 'fake_cmd', - expected_stdout, expected_stderr, 0) - - @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') - def test_execute_and_process_stdout_despite_cmd_exits(self, mock_popen): - self._mock_execute_and_process_stdout_process(mock_popen) - mock_popen.return_value.poll.side_effect = [None, 0] - mock_popen.return_value.stdout.readline.side_effect = [ - '1', '2', '3', '' - ] - mock_handler = mock.MagicMock() + def mock_handler(raw_line): + pass + + with mock.patch.object(adb.AdbProxy, '_execute_and_process_stdout' + ) as mock_execute_and_process_stdout: + stderr = adb.AdbProxy().instrument(MOCK_INSTRUMENTATION_PACKAGE, + handler=mock_handler) + mock_execute_and_process_stdout.assert_called_once_with( + ['adb', 'shell', MOCK_BASIC_INSTRUMENTATION_COMMAND], + shell=False, + handler=mock_handler) + self.assertEqual(stderr, + mock_execute_and_process_stdout.return_value) + + def test_instrument_with_handler_with_runner(self): + """Verifies the AndroidDevice object's instrument command is correct + with a handler passed in and a runner specified. + """ - err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'], - shell=False, - handler=mock_handler) - - self.assertEqual(mock_handler.call_count, 3) - mock_handler.assert_any_call('1') - mock_handler.assert_any_call('2') - mock_handler.assert_any_call('3') - - @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') - def test_execute_and_process_stdout_when_cmd_eof(self, mock_popen): - self._mock_execute_and_process_stdout_process(mock_popen) - mock_popen.return_value.stdout.readline.side_effect = [ - '1', '2', '3', '' - ] - mock_handler = mock.MagicMock() + def mock_handler(raw_line): + pass + + with mock.patch.object(adb.AdbProxy, '_execute_and_process_stdout' + ) as mock_execute_and_process_stdout: + stderr = adb.AdbProxy().instrument( + MOCK_INSTRUMENTATION_PACKAGE, + runner=MOCK_INSTRUMENTATION_RUNNER, + handler=mock_handler) + mock_execute_and_process_stdout.assert_called_once_with( + ['adb', 'shell', MOCK_RUNNER_INSTRUMENTATION_COMMAND], + shell=False, + handler=mock_handler) + self.assertEqual(stderr, + mock_execute_and_process_stdout.return_value) + + def test_instrument_with_handler_with_options(self): + """Verifies the AndroidDevice object's instrument command is correct + with a handler passed in and options. + """ - err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'], - shell=False, - handler=mock_handler) - - self.assertEqual(mock_handler.call_count, 3) - mock_handler.assert_any_call('1') - mock_handler.assert_any_call('2') - mock_handler.assert_any_call('3') - - @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') - def test_execute_and_process_stdout_returns_stderr(self, mock_popen): - self._mock_execute_and_process_stdout_process(mock_popen) - - err = adb.AdbProxy()._execute_and_process_stdout( - ['fake_cmd'], shell=False, handler=mock.MagicMock()) - self.assertEqual(MOCK_DEFAULT_STDERR, err.decode('utf-8')) - - @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') - def test_execute_and_process_stdout_raises_adb_error(self, mock_popen): - self._mock_execute_and_process_stdout_process(mock_popen) - mock_popen.return_value.returncode = 1 - - with self.assertRaisesRegex(adb.AdbError, - 'Error executing adb cmd .*'): - err = adb.AdbProxy()._execute_and_process_stdout( - ['fake_cmd'], shell=False, handler=mock.MagicMock()) - - @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen') - def test_execute_and_process_stdout_when_handler_crash(self, mock_popen): - self._mock_execute_and_process_stdout_process(mock_popen) - mock_popen.return_value.stdout.readline.side_effect = [ - '1', '2', '3', '' - ] - mock_handler = mock.MagicMock() - mock_handler.side_effect = ['', TypeError('fake crash'), '', ''] - - with self.assertRaisesRegex(TypeError, 'fake crash'): - err = adb.AdbProxy()._execute_and_process_stdout( - ['fake_cmd'], shell=False, handler=mock_handler) - - mock_popen.return_value.communicate.assert_called_once_with() - - def test_construct_adb_cmd(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', - 'arg1', - shell=False) - self.assertEqual(adb_cmd, ['adb', 'shell', 'arg1']) - - def test_construct_adb_cmd_with_one_command(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd( - 'shell ls /asdafsfd/asdf-asfd/asa', [], shell=False) - self.assertEqual(adb_cmd, ['adb', 'shell ls /asdafsfd/asdf-asfd/asa']) - - def test_construct_adb_cmd_with_one_arg_command(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd( - 'shell', 'ls /asdafsfd/asdf-asfd/asa', shell=False) - self.assertEqual(adb_cmd, - ['adb', 'shell', 'ls /asdafsfd/asdf-asfd/asa']) - - def test_construct_adb_cmd_with_one_arg_command_list(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd( - 'shell', ['ls /asdafsfd/asdf-asfd/asa'], shell=False) - self.assertEqual(adb_cmd, - ['adb', 'shell', 'ls /asdafsfd/asdf-asfd/asa']) - - def test_construct_adb_cmd_with_special_characters(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', - ['a b', '"blah"', r'\/\/'], - shell=False) - self.assertEqual(adb_cmd, ['adb', 'shell', 'a b', '"blah"', r"\/\/"]) - - def test_construct_adb_cmd_with_serial(self): - adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell', - 'arg1', - shell=False) - self.assertEqual(adb_cmd, ['adb', '-s', '12345', 'shell', 'arg1']) - - def test_construct_adb_cmd_with_list(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', ['arg1', 'arg2'], - shell=False) - self.assertEqual(adb_cmd, ['adb', 'shell', 'arg1', 'arg2']) - - def test_construct_adb_cmd_with_serial_with_list(self): - adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell', - ['arg1', 'arg2'], - shell=False) - self.assertEqual(adb_cmd, - ['adb', '-s', '12345', 'shell', 'arg1', 'arg2']) - - def test_construct_adb_cmd_with_shell_true(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', - 'arg1 arg2', - shell=True) - self.assertEqual(adb_cmd, '"adb" shell arg1 arg2') - - def test_construct_adb_cmd_with_shell_true_with_one_command(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd( - 'shell ls /asdafsfd/asdf-asfd/asa', [], shell=True) - self.assertEqual(adb_cmd, '"adb" shell ls /asdafsfd/asdf-asfd/asa ') - - def test_construct_adb_cmd_with_shell_true_with_one_arg_command(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd( - 'shell', 'ls /asdafsfd/asdf-asfd/asa', shell=True) - self.assertEqual(adb_cmd, '"adb" shell ls /asdafsfd/asdf-asfd/asa') - - def test_construct_adb_cmd_with_shell_true_with_one_arg_command_list(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd( - 'shell', ['ls /asdafsfd/asdf-asfd/asa'], shell=True) - self.assertEqual(adb_cmd, '"adb" shell \'ls /asdafsfd/asdf-asfd/asa\'') - - def test_construct_adb_cmd_with_shell_true_with_auto_quotes(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', - ['a b', '"blah"', r'\/\/'], - shell=True) - self.assertEqual(adb_cmd, '"adb" shell \'a b\' \'"blah"\' \'\\/\\/\'') - - def test_construct_adb_cmd_with_shell_true_with_serial(self): - adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell', - 'arg1 arg2', - shell=True) - self.assertEqual(adb_cmd, '"adb" -s "12345" shell arg1 arg2') - - def test_construct_adb_cmd_with_shell_true_with_list(self): - adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', ['arg1', 'arg2'], - shell=True) - self.assertEqual(adb_cmd, '"adb" shell arg1 arg2') - - def test_construct_adb_cmd_with_shell_true_with_serial_with_list(self): - adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell', - ['arg1', 'arg2'], - shell=True) - self.assertEqual(adb_cmd, '"adb" -s "12345" shell arg1 arg2') - - def test_exec_adb_cmd(self): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT - adb.AdbProxy().shell(['arg1', 'arg2']) - mock_exec_cmd.assert_called_once_with( - ['adb', 'shell', 'arg1', 'arg2'], - shell=False, - timeout=None, - stderr=None) - - def test_exec_adb_cmd_with_shell_true(self): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT - adb.AdbProxy().shell('arg1 arg2', shell=True) - mock_exec_cmd.assert_called_once_with('"adb" shell arg1 arg2', - shell=True, - timeout=None, - stderr=None) - - def test_exec_adb_cmd_formats_command(self): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - with mock.patch.object( - adb.AdbProxy, - '_construct_adb_cmd') as mock_construct_adb_cmd: - mock_adb_cmd = mock.MagicMock() - mock_adb_args = mock.MagicMock() - mock_construct_adb_cmd.return_value = mock_adb_cmd - mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT - - adb.AdbProxy().shell(mock_adb_args) - mock_construct_adb_cmd.assert_called_once_with('shell', - mock_adb_args, - shell=False) - mock_exec_cmd.assert_called_once_with(mock_adb_cmd, - shell=False, - timeout=None, - stderr=None) - - def test_exec_adb_cmd_formats_command_with_shell_true(self): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - with mock.patch.object( - adb.AdbProxy, - '_construct_adb_cmd') as mock_construct_adb_cmd: - mock_adb_cmd = mock.MagicMock() - mock_adb_args = mock.MagicMock() - mock_construct_adb_cmd.return_value = mock_adb_cmd - - adb.AdbProxy().shell(mock_adb_args, shell=True) - mock_construct_adb_cmd.assert_called_once_with('shell', - mock_adb_args, - shell=True) - mock_exec_cmd.assert_called_once_with(mock_adb_cmd, - shell=True, - timeout=None, - stderr=None) - - def test_execute_adb_and_process_stdout_formats_command(self): - with mock.patch.object(adb.AdbProxy, '_execute_and_process_stdout' - ) as mock_execute_and_process_stdout: - with mock.patch.object( - adb.AdbProxy, - '_construct_adb_cmd') as mock_construct_adb_cmd: - mock_adb_cmd = mock.MagicMock() - mock_adb_args = mock.MagicMock() - mock_handler = mock.MagicMock() - mock_construct_adb_cmd.return_value = mock_adb_cmd - - adb.AdbProxy()._execute_adb_and_process_stdout( - 'shell', mock_adb_args, shell=False, handler=mock_handler) - mock_construct_adb_cmd.assert_called_once_with('shell', - mock_adb_args, - shell=False) - mock_execute_and_process_stdout.assert_called_once_with( - mock_adb_cmd, shell=False, handler=mock_handler) - - @mock.patch('mobly.utils.run_command') - def test_exec_adb_cmd_with_stderr_pipe(self, mock_run_command): - mock_run_command.return_value = (0, - MOCK_DEFAULT_STDOUT.encode('utf-8'), - MOCK_DEFAULT_STDERR.encode('utf-8')) - stderr_redirect = io.BytesIO() - out = adb.AdbProxy().shell('arg1 arg2', - shell=True, - stderr=stderr_redirect) - self.assertEqual(MOCK_DEFAULT_STDOUT, out.decode('utf-8')) - self.assertEqual(MOCK_DEFAULT_STDERR, - stderr_redirect.getvalue().decode('utf-8')) - - def test_getprop(self): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - mock_exec_cmd.return_value = b'blah' - self.assertEqual(adb.AdbProxy().getprop('haha'), 'blah') - mock_exec_cmd.assert_called_once_with( - ['adb', 'shell', 'getprop', 'haha'], - shell=False, - stderr=None, - timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC) - - def test__parse_getprop_output_special_values(self): - mock_adb_output = ( - b'[selinux.restorecon_recursive]: [/data/misc_ce/10]\n' - b'[selinux.abc]: [key: value]\n' # "key: value" as value - b'[persist.sys.boot.reason.history]: [reboot,adb,1558549857\n' - b'reboot,factory_reset,1558483886\n' # multi-line value - b'reboot,1558483823]\n' - b'[persist.something]: [haha\n' - b']\n' - b'[[wrapped.key]]: [[wrapped value]]\n' - b'[persist.byte]: [J\xaa\x8bb\xab\x9dP\x0f]\n' # non-decodable - ) - parsed_props = adb.AdbProxy()._parse_getprop_output(mock_adb_output) - expected_output = { - 'persist.sys.boot.reason.history': - ('reboot,adb,1558549857\nreboot,factory_reset,1558483886\n' - 'reboot,1558483823'), - 'selinux.abc': - 'key: value', - 'persist.something': - 'haha\n', - 'selinux.restorecon_recursive': - '/data/misc_ce/10', - '[wrapped.key]': - '[wrapped value]', - 'persist.byte': - 'JbP\x0f', - } - self.assertEqual(parsed_props, expected_output) - - def test__parse_getprop_output_malformat_output(self): - mock_adb_output = ( - b'[selinux.restorecon_recursive][/data/misc_ce/10]\n' # Malformat - b'[persist.sys.boot.reason]: [reboot,adb,1558549857]\n' - b'[persist.something]: [haha]\n') - parsed_props = adb.AdbProxy()._parse_getprop_output(mock_adb_output) - expected_output = { - 'persist.sys.boot.reason': 'reboot,adb,1558549857', - 'persist.something': 'haha' - } - self.assertEqual(parsed_props, expected_output) - - def test__parse_getprop_output_special_line_separator(self): - mock_adb_output = ( - b'[selinux.restorecon_recursive][/data/misc_ce/10]\r\n' # Malformat - b'[persist.sys.boot.reason]: [reboot,adb,1558549857]\r\n' - b'[persist.something]: [haha]\r\n') - parsed_props = adb.AdbProxy()._parse_getprop_output(mock_adb_output) - expected_output = { - 'persist.sys.boot.reason': 'reboot,adb,1558549857', - 'persist.something': 'haha' - } - self.assertEqual(parsed_props, expected_output) - - @mock.patch('time.sleep', return_value=mock.MagicMock()) - def test_getprops(self, mock_sleep): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - mock_exec_cmd.return_value = ( - b'\n[sendbug.preferred.domain]: [google.com]\n' - b'[sys.uidcpupower]: []\n' - b'[sys.wifitracing.started]: [1]\n' - b'[telephony.lteOnCdmaDevice]: [1]\n\n') - actual_output = adb.AdbProxy().getprops([ - 'sys.wifitracing.started', # "numeric" value - 'sys.uidcpupower', # empty value - 'sendbug.preferred.domain', # string value - 'nonExistentProp' - ]) - self.assertEqual( - actual_output, { - 'sys.wifitracing.started': '1', - 'sys.uidcpupower': '', - 'sendbug.preferred.domain': 'google.com' - }) - mock_exec_cmd.assert_called_once_with( - ['adb', 'shell', 'getprop'], - shell=False, - stderr=None, - timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC) - mock_sleep.assert_not_called() - - @mock.patch('time.sleep', return_value=mock.MagicMock()) - def test_getprops_when_empty_string_randomly_returned(self, mock_sleep): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - mock_exec_cmd.side_effect = [ - b'', - (b'\n[ro.build.id]: [AB42]\n' - b'[ro.build.type]: [userdebug]\n\n') - ] - actual_output = adb.AdbProxy().getprops(['ro.build.id']) - self.assertEqual(actual_output, { - 'ro.build.id': 'AB42', - }) - self.assertEqual(mock_exec_cmd.call_count, 2) - mock_exec_cmd.assert_called_with( - ['adb', 'shell', 'getprop'], - shell=False, - stderr=None, - timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC) - self.assertEqual(mock_sleep.call_count, 1) - mock_sleep.assert_called_with(1) - - @mock.patch('time.sleep', return_value=mock.MagicMock()) - def test_getprops_when_empty_string_always_returned(self, mock_sleep): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - mock_exec_cmd.return_value = b'' - actual_output = adb.AdbProxy().getprops(['ro.build.id']) - self.assertEqual(actual_output, {}) - self.assertEqual(mock_exec_cmd.call_count, 3) - mock_exec_cmd.assert_called_with( - ['adb', 'shell', 'getprop'], - shell=False, - stderr=None, - timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC) - self.assertEqual(mock_sleep.call_count, 2) - mock_sleep.assert_called_with(1) - - def test_forward(self): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - adb.AdbProxy().forward(MOCK_SHELL_COMMAND) - - def test_instrument_without_parameters(self): - """Verifies the AndroidDevice object's instrument command is correct in - the basic case. - """ - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - output = adb.AdbProxy().instrument(MOCK_INSTRUMENTATION_PACKAGE) - mock_exec_cmd.assert_called_once_with( - ['adb', 'shell', MOCK_BASIC_INSTRUMENTATION_COMMAND], - shell=False, - timeout=None, - stderr=None) - self.assertEqual(output, mock_exec_cmd.return_value) - - def test_instrument_with_runner(self): - """Verifies the AndroidDevice object's instrument command is correct - with a runner specified. - """ - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - stdout = adb.AdbProxy().instrument( - MOCK_INSTRUMENTATION_PACKAGE, - runner=MOCK_INSTRUMENTATION_RUNNER) - mock_exec_cmd.assert_called_once_with( - ['adb', 'shell', MOCK_RUNNER_INSTRUMENTATION_COMMAND], - shell=False, - timeout=None, - stderr=None) - self.assertEqual(stdout, mock_exec_cmd.return_value) - - def test_instrument_with_options(self): - """Verifies the AndroidDevice object's instrument command is correct - with options. - """ - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - stdout = adb.AdbProxy().instrument( - MOCK_INSTRUMENTATION_PACKAGE, - options=MOCK_INSTRUMENTATION_OPTIONS) - mock_exec_cmd.assert_called_once_with( - ['adb', 'shell', MOCK_OPTIONS_INSTRUMENTATION_COMMAND], - shell=False, - timeout=None, - stderr=None) - self.assertEqual(stdout, mock_exec_cmd.return_value) - - def test_instrument_with_handler(self): - """Verifies the AndroidDevice object's instrument command is correct - with a handler passed in. - """ - - def mock_handler(raw_line): - pass - - with mock.patch.object(adb.AdbProxy, '_execute_and_process_stdout' - ) as mock_execute_and_process_stdout: - stderr = adb.AdbProxy().instrument(MOCK_INSTRUMENTATION_PACKAGE, - handler=mock_handler) - mock_execute_and_process_stdout.assert_called_once_with( - ['adb', 'shell', MOCK_BASIC_INSTRUMENTATION_COMMAND], - shell=False, - handler=mock_handler) - self.assertEqual(stderr, - mock_execute_and_process_stdout.return_value) - - def test_instrument_with_handler_with_runner(self): - """Verifies the AndroidDevice object's instrument command is correct - with a handler passed in and a runner specified. - """ - - def mock_handler(raw_line): - pass - - with mock.patch.object(adb.AdbProxy, '_execute_and_process_stdout' - ) as mock_execute_and_process_stdout: - stderr = adb.AdbProxy().instrument( - MOCK_INSTRUMENTATION_PACKAGE, - runner=MOCK_INSTRUMENTATION_RUNNER, - handler=mock_handler) - mock_execute_and_process_stdout.assert_called_once_with( - ['adb', 'shell', MOCK_RUNNER_INSTRUMENTATION_COMMAND], - shell=False, - handler=mock_handler) - self.assertEqual(stderr, - mock_execute_and_process_stdout.return_value) - - def test_instrument_with_handler_with_options(self): - """Verifies the AndroidDevice object's instrument command is correct - with a handler passed in and options. - """ - - def mock_handler(raw_line): - pass - - with mock.patch.object(adb.AdbProxy, '_execute_and_process_stdout' - ) as mock_execute_and_process_stdout: - stderr = adb.AdbProxy().instrument( - MOCK_INSTRUMENTATION_PACKAGE, - options=MOCK_INSTRUMENTATION_OPTIONS, - handler=mock_handler) - mock_execute_and_process_stdout.assert_called_once_with( - ['adb', 'shell', MOCK_OPTIONS_INSTRUMENTATION_COMMAND], - shell=False, - handler=mock_handler) - self.assertEqual(stderr, - mock_execute_and_process_stdout.return_value) - - @mock.patch.object(adb.AdbProxy, '_exec_cmd') - def test_root_success(self, mock_exec_cmd): - mock_exec_cmd.return_value = MOCK_ROOT_SUCCESS_OUTPUT - output = adb.AdbProxy().root() - mock_exec_cmd.assert_called_once_with( - ['adb', 'root'], - shell=False, - timeout=None, - stderr=None) - self.assertEqual(output, MOCK_ROOT_SUCCESS_OUTPUT) - - @mock.patch('time.sleep', return_value=mock.MagicMock()) - @mock.patch.object(adb.AdbProxy, '_exec_cmd') - def test_root_success_with_retry(self, mock_exec_cmd, mock_sleep): - mock_exec_cmd.side_effect = [ - adb.AdbError('adb root', '', MOCK_ROOT_ERROR_OUTPUT, 1), - MOCK_ROOT_SUCCESS_OUTPUT] - output = adb.AdbProxy().root() - mock_exec_cmd.assert_called_with( - ['adb', 'root'], - shell=False, - timeout=None, - stderr=None) - self.assertEqual(output, MOCK_ROOT_SUCCESS_OUTPUT) - self.assertEqual(mock_sleep.call_count, 1) - mock_sleep.assert_called_with(10) - - @mock.patch('time.sleep', return_value=mock.MagicMock()) - @mock.patch.object(adb.AdbProxy, '_exec_cmd') - def test_root_raises_adb_error_when_all_retries_failed(self, mock_exec_cmd, - mock_sleep): - mock_exec_cmd.side_effect = adb.AdbError('adb root', - '', - MOCK_ROOT_ERROR_OUTPUT, - 1) - expected_msg = ('Error executing adb cmd "adb root". ' - 'ret: 1, stdout: , stderr: %s' % - MOCK_ROOT_ERROR_OUTPUT) - with self.assertRaisesRegex(adb.AdbError, expected_msg): - adb.AdbProxy().root() - mock_exec_cmd.assert_called_with( - ['adb', 'root'], - shell=False, - timeout=None, - stderr=None) - self.assertEqual(mock_sleep.call_count, 2) - mock_sleep.assert_called_with(10) - - def test_has_shell_command_called_correctly(self): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT - adb.AdbProxy().has_shell_command(MOCK_SHELL_COMMAND) - mock_exec_cmd.assert_called_once_with( - ['adb', 'shell', 'command', '-v', MOCK_SHELL_COMMAND], - shell=False, - timeout=None, - stderr=None) - - def test_has_shell_command_with_existing_command(self): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - mock_exec_cmd.return_value = MOCK_COMMAND_OUTPUT - self.assertTrue( - adb.AdbProxy().has_shell_command(MOCK_SHELL_COMMAND)) - - def test_has_shell_command_with_missing_command_on_older_devices(self): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT - mock_exec_cmd.side_effect = adb.AdbError( - MOCK_ADB_SHELL_COMMAND_CHECK, '', '', 0) - self.assertFalse( - adb.AdbProxy().has_shell_command(MOCK_SHELL_COMMAND)) - - def test_has_shell_command_with_missing_command_on_newer_devices(self): - with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: - mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT - mock_exec_cmd.side_effect = adb.AdbError( - MOCK_ADB_SHELL_COMMAND_CHECK, '', '', 1) - self.assertFalse( - adb.AdbProxy().has_shell_command(MOCK_SHELL_COMMAND)) - - @mock.patch.object(adb.AdbProxy, 'getprop') - @mock.patch.object(adb.AdbProxy, '_exec_cmd') - def test_current_user_id_25_and_above(self, mock_exec_cmd, mock_getprop): - mock_getprop.return_value = b'25' - mock_exec_cmd.return_value = b'123' - user_id = adb.AdbProxy().current_user_id - mock_exec_cmd.assert_called_once_with( - ['adb', 'shell', 'am', 'get-current-user'], - shell=False, - stderr=None, - timeout=None) - self.assertEqual(user_id, 123) - - @mock.patch.object(adb.AdbProxy, 'getprop') - @mock.patch.object(adb.AdbProxy, '_exec_cmd') - def test_current_user_id_between_21_and_24(self, mock_exec_cmd, - mock_getprop): - mock_getprop.return_value = b'23' - mock_exec_cmd.return_value = (b'Users:\n' - b'UserInfo{123:Owner:13} serialNo=0\n' - b'Created: <unknown>\n' - b'Last logged in: +1h22m12s497ms ago\n' - b'UserInfo{456:Owner:14} serialNo=0\n' - b'Created: <unknown>\n' - b'Last logged in: +1h01m12s497ms ago\n') - user_id = adb.AdbProxy().current_user_id - mock_exec_cmd.assert_called_once_with( - ['adb', 'shell', 'dumpsys', 'user'], - shell=False, - stderr=None, - timeout=None) - self.assertEqual(user_id, 123) + def mock_handler(raw_line): + pass + + with mock.patch.object(adb.AdbProxy, '_execute_and_process_stdout' + ) as mock_execute_and_process_stdout: + stderr = adb.AdbProxy().instrument( + MOCK_INSTRUMENTATION_PACKAGE, + options=MOCK_INSTRUMENTATION_OPTIONS, + handler=mock_handler) + mock_execute_and_process_stdout.assert_called_once_with( + ['adb', 'shell', MOCK_OPTIONS_INSTRUMENTATION_COMMAND], + shell=False, + handler=mock_handler) + self.assertEqual(stderr, + mock_execute_and_process_stdout.return_value) + + @mock.patch.object(adb.AdbProxy, '_exec_cmd') + def test_root_success(self, mock_exec_cmd): + mock_exec_cmd.return_value = MOCK_ROOT_SUCCESS_OUTPUT + output = adb.AdbProxy().root() + mock_exec_cmd.assert_called_once_with( + ['adb', 'root'], + shell=False, + timeout=None, + stderr=None) + self.assertEqual(output, MOCK_ROOT_SUCCESS_OUTPUT) + + @mock.patch('time.sleep', return_value=mock.MagicMock()) + @mock.patch.object(adb.AdbProxy, '_exec_cmd') + def test_root_success_with_retry(self, mock_exec_cmd, mock_sleep): + mock_exec_cmd.side_effect = [ + adb.AdbError('adb root', '', MOCK_ROOT_ERROR_OUTPUT, 1), + MOCK_ROOT_SUCCESS_OUTPUT] + output = adb.AdbProxy().root() + mock_exec_cmd.assert_called_with( + ['adb', 'root'], + shell=False, + timeout=None, + stderr=None) + self.assertEqual(output, MOCK_ROOT_SUCCESS_OUTPUT) + self.assertEqual(mock_sleep.call_count, 1) + mock_sleep.assert_called_with(10) + + @mock.patch('time.sleep', return_value=mock.MagicMock()) + @mock.patch.object(adb.AdbProxy, '_exec_cmd') + def test_root_raises_adb_error_when_all_retries_failed(self, mock_exec_cmd, + mock_sleep): + mock_exec_cmd.side_effect = adb.AdbError('adb root', + '', + MOCK_ROOT_ERROR_OUTPUT, + 1) + expected_msg = ('Error executing adb cmd "adb root". ' + 'ret: 1, stdout: , stderr: %s' % + MOCK_ROOT_ERROR_OUTPUT) + with self.assertRaisesRegex(adb.AdbError, expected_msg): + adb.AdbProxy().root() + mock_exec_cmd.assert_called_with( + ['adb', 'root'], + shell=False, + timeout=None, + stderr=None) + self.assertEqual(mock_sleep.call_count, 2) + mock_sleep.assert_called_with(10) + + def test_has_shell_command_called_correctly(self): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT + adb.AdbProxy().has_shell_command(MOCK_SHELL_COMMAND) + mock_exec_cmd.assert_called_once_with( + ['adb', 'shell', 'command', '-v', MOCK_SHELL_COMMAND], + shell=False, + timeout=None, + stderr=None) + + def test_has_shell_command_with_existing_command(self): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + mock_exec_cmd.return_value = MOCK_COMMAND_OUTPUT + self.assertTrue( + adb.AdbProxy().has_shell_command(MOCK_SHELL_COMMAND)) + + def test_has_shell_command_with_missing_command_on_older_devices(self): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT + mock_exec_cmd.side_effect = adb.AdbError( + MOCK_ADB_SHELL_COMMAND_CHECK, '', '', 0) + self.assertFalse( + adb.AdbProxy().has_shell_command(MOCK_SHELL_COMMAND)) + + def test_has_shell_command_with_missing_command_on_newer_devices(self): + with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd: + mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT + mock_exec_cmd.side_effect = adb.AdbError( + MOCK_ADB_SHELL_COMMAND_CHECK, '', '', 1) + self.assertFalse( + adb.AdbProxy().has_shell_command(MOCK_SHELL_COMMAND)) + + @mock.patch.object(adb.AdbProxy, 'getprop') + @mock.patch.object(adb.AdbProxy, '_exec_cmd') + def test_current_user_id_25_and_above(self, mock_exec_cmd, mock_getprop): + mock_getprop.return_value = b'25' + mock_exec_cmd.return_value = b'123' + user_id = adb.AdbProxy().current_user_id + mock_exec_cmd.assert_called_once_with( + ['adb', 'shell', 'am', 'get-current-user'], + shell=False, + stderr=None, + timeout=None) + self.assertEqual(user_id, 123) + + @mock.patch.object(adb.AdbProxy, 'getprop') + @mock.patch.object(adb.AdbProxy, '_exec_cmd') + def test_current_user_id_between_21_and_24(self, mock_exec_cmd, + mock_getprop): + mock_getprop.return_value = b'23' + mock_exec_cmd.return_value = (b'Users:\n' + b'UserInfo{123:Owner:13} serialNo=0\n' + b'Created: <unknown>\n' + b'Last logged in: +1h22m12s497ms ago\n' + b'UserInfo{456:Owner:14} serialNo=0\n' + b'Created: <unknown>\n' + b'Last logged in: +1h01m12s497ms ago\n') + user_id = adb.AdbProxy().current_user_id + mock_exec_cmd.assert_called_once_with( + ['adb', 'shell', 'dumpsys', 'user'], + shell=False, + stderr=None, + timeout=None) + self.assertEqual(user_id, 123) if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/callback_handler_test.py b/tests/mobly/controllers/android_device_lib/callback_handler_test.py index b00e127..9476056 100755 --- a/tests/mobly/controllers/android_device_lib/callback_handler_test.py +++ b/tests/mobly/controllers/android_device_lib/callback_handler_test.py @@ -20,129 +20,129 @@ from mobly.controllers.android_device_lib import jsonrpc_client_base MOCK_CALLBACK_ID = "1-0" MOCK_RAW_EVENT = { - 'callbackId': '2-1', - 'name': 'AsyncTaskResult', - 'time': 20460228696, - 'data': { - 'exampleData': "Here's a simple event.", - 'successful': True, - 'secretNumber': 12 - } + 'callbackId': '2-1', + 'name': 'AsyncTaskResult', + 'time': 20460228696, + 'data': { + 'exampleData': "Here's a simple event.", + 'successful': True, + 'secretNumber': 12 + } } class CallbackHandlerTest(unittest.TestCase): - """Unit tests for mobly.controllers.android_device_lib.callback_handler. + """Unit tests for mobly.controllers.android_device_lib.callback_handler. + """ + + def test_timeout_value(self): + self.assertGreaterEqual(jsonrpc_client_base._SOCKET_READ_TIMEOUT, + callback_handler.MAX_TIMEOUT) + + def test_callback_id_property(self): + mock_event_client = mock.Mock() + handler = callback_handler.CallbackHandler( + callback_id=MOCK_CALLBACK_ID, + event_client=mock_event_client, + ret_value=None, + method_name=None, + ad=mock.Mock()) + self.assertEqual(handler.callback_id, MOCK_CALLBACK_ID) + with self.assertRaisesRegex(AttributeError, "can't set attribute"): + handler.callback_id = 'ha' + + def test_event_dict_to_snippet_event(self): + mock_event_client = mock.Mock() + mock_event_client.eventWaitAndGet = mock.Mock( + return_value=MOCK_RAW_EVENT) + handler = callback_handler.CallbackHandler( + callback_id=MOCK_CALLBACK_ID, + event_client=mock_event_client, + ret_value=None, + method_name=None, + ad=mock.Mock()) + event = handler.waitAndGet('ha') + self.assertEqual(event.name, MOCK_RAW_EVENT['name']) + self.assertEqual(event.creation_time, MOCK_RAW_EVENT['time']) + self.assertEqual(event.data, MOCK_RAW_EVENT['data']) + self.assertEqual(event.callback_id, MOCK_RAW_EVENT['callbackId']) + + def test_wait_and_get_timeout(self): + mock_event_client = mock.Mock() + java_timeout_msg = ('com.google.android.mobly.snippet.event.' + 'EventSnippet$EventSnippetException: timeout.') + mock_event_client.eventWaitAndGet = mock.Mock( + side_effect=jsonrpc_client_base.ApiError(mock.Mock(), + java_timeout_msg)) + handler = callback_handler.CallbackHandler( + callback_id=MOCK_CALLBACK_ID, + event_client=mock_event_client, + ret_value=None, + method_name=None, + ad=mock.Mock()) + expected_msg = 'Timed out after waiting .*s for event "ha" .*' + with self.assertRaisesRegex(callback_handler.TimeoutError, + expected_msg): + handler.waitAndGet('ha') + + def test_wait_for_event(self): + mock_event_client = mock.Mock() + mock_event_client.eventWaitAndGet = mock.Mock( + return_value=MOCK_RAW_EVENT) + handler = callback_handler.CallbackHandler( + callback_id=MOCK_CALLBACK_ID, + event_client=mock_event_client, + ret_value=None, + method_name=None, + ad=mock.Mock()) + + def some_condition(event): + return event.data['successful'] + + event = handler.waitForEvent('AsyncTaskResult', some_condition, 0.01) + + def test_wait_for_event_negative(self): + mock_event_client = mock.Mock() + mock_event_client.eventWaitAndGet = mock.Mock( + return_value=MOCK_RAW_EVENT) + handler = callback_handler.CallbackHandler( + callback_id=MOCK_CALLBACK_ID, + event_client=mock_event_client, + ret_value=None, + method_name=None, + ad=mock.Mock()) + expected_msg = ( + 'Timed out after 0.01s waiting for an "AsyncTaskResult" event that' + ' satisfies the predicate "some_condition".') + + def some_condition(event): + return False + + with self.assertRaisesRegex(callback_handler.TimeoutError, + expected_msg): + handler.waitForEvent('AsyncTaskResult', some_condition, 0.01) + + def test_wait_for_event_max_timeout(self): + """waitForEvent should not raise the timeout exceed threshold error. """ + mock_event_client = mock.Mock() + mock_event_client.eventWaitAndGet = mock.Mock( + return_value=MOCK_RAW_EVENT) + handler = callback_handler.CallbackHandler( + callback_id=MOCK_CALLBACK_ID, + event_client=mock_event_client, + ret_value=None, + method_name=None, + ad=mock.Mock()) - def test_timeout_value(self): - self.assertGreaterEqual(jsonrpc_client_base._SOCKET_READ_TIMEOUT, - callback_handler.MAX_TIMEOUT) - - def test_callback_id_property(self): - mock_event_client = mock.Mock() - handler = callback_handler.CallbackHandler( - callback_id=MOCK_CALLBACK_ID, - event_client=mock_event_client, - ret_value=None, - method_name=None, - ad=mock.Mock()) - self.assertEqual(handler.callback_id, MOCK_CALLBACK_ID) - with self.assertRaisesRegex(AttributeError, "can't set attribute"): - handler.callback_id = 'ha' - - def test_event_dict_to_snippet_event(self): - mock_event_client = mock.Mock() - mock_event_client.eventWaitAndGet = mock.Mock( - return_value=MOCK_RAW_EVENT) - handler = callback_handler.CallbackHandler( - callback_id=MOCK_CALLBACK_ID, - event_client=mock_event_client, - ret_value=None, - method_name=None, - ad=mock.Mock()) - event = handler.waitAndGet('ha') - self.assertEqual(event.name, MOCK_RAW_EVENT['name']) - self.assertEqual(event.creation_time, MOCK_RAW_EVENT['time']) - self.assertEqual(event.data, MOCK_RAW_EVENT['data']) - self.assertEqual(event.callback_id, MOCK_RAW_EVENT['callbackId']) - - def test_wait_and_get_timeout(self): - mock_event_client = mock.Mock() - java_timeout_msg = ('com.google.android.mobly.snippet.event.' - 'EventSnippet$EventSnippetException: timeout.') - mock_event_client.eventWaitAndGet = mock.Mock( - side_effect=jsonrpc_client_base.ApiError(mock.Mock(), - java_timeout_msg)) - handler = callback_handler.CallbackHandler( - callback_id=MOCK_CALLBACK_ID, - event_client=mock_event_client, - ret_value=None, - method_name=None, - ad=mock.Mock()) - expected_msg = 'Timed out after waiting .*s for event "ha" .*' - with self.assertRaisesRegex(callback_handler.TimeoutError, - expected_msg): - handler.waitAndGet('ha') - - def test_wait_for_event(self): - mock_event_client = mock.Mock() - mock_event_client.eventWaitAndGet = mock.Mock( - return_value=MOCK_RAW_EVENT) - handler = callback_handler.CallbackHandler( - callback_id=MOCK_CALLBACK_ID, - event_client=mock_event_client, - ret_value=None, - method_name=None, - ad=mock.Mock()) - - def some_condition(event): - return event.data['successful'] - - event = handler.waitForEvent('AsyncTaskResult', some_condition, 0.01) - - def test_wait_for_event_negative(self): - mock_event_client = mock.Mock() - mock_event_client.eventWaitAndGet = mock.Mock( - return_value=MOCK_RAW_EVENT) - handler = callback_handler.CallbackHandler( - callback_id=MOCK_CALLBACK_ID, - event_client=mock_event_client, - ret_value=None, - method_name=None, - ad=mock.Mock()) - expected_msg = ( - 'Timed out after 0.01s waiting for an "AsyncTaskResult" event that' - ' satisfies the predicate "some_condition".') - - def some_condition(event): - return False - - with self.assertRaisesRegex(callback_handler.TimeoutError, - expected_msg): - handler.waitForEvent('AsyncTaskResult', some_condition, 0.01) - - def test_wait_for_event_max_timeout(self): - """waitForEvent should not raise the timeout exceed threshold error. - """ - mock_event_client = mock.Mock() - mock_event_client.eventWaitAndGet = mock.Mock( - return_value=MOCK_RAW_EVENT) - handler = callback_handler.CallbackHandler( - callback_id=MOCK_CALLBACK_ID, - event_client=mock_event_client, - ret_value=None, - method_name=None, - ad=mock.Mock()) - - def some_condition(event): - return event.data['successful'] - - big_timeout = callback_handler.MAX_TIMEOUT * 2 - # This line should not raise. - event = handler.waitForEvent( - 'AsyncTaskResult', some_condition, timeout=big_timeout) + def some_condition(event): + return event.data['successful'] + + big_timeout = callback_handler.MAX_TIMEOUT * 2 + # This line should not raise. + event = handler.waitForEvent( + 'AsyncTaskResult', some_condition, timeout=big_timeout) if __name__ == "__main__": - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/errors_test.py b/tests/mobly/controllers/android_device_lib/errors_test.py index d88c254..57b87b3 100755 --- a/tests/mobly/controllers/android_device_lib/errors_test.py +++ b/tests/mobly/controllers/android_device_lib/errors_test.py @@ -20,30 +20,30 @@ from mobly.controllers.android_device_lib import errors class ErrorsTest(unittest.TestCase): - def test_device_error(self): - device = mock.MagicMock() - device.__repr__ = lambda _: '[MockDevice]' - exception = errors.DeviceError(device, 'Some error message.') - self.assertEqual(str(exception), '[MockDevice] Some error message.') - - def test_service_error(self): - device = mock.MagicMock() - device.__repr__ = lambda _: '[MockDevice]' - exception = errors.ServiceError(device, 'Some error message.') - self.assertEqual( - str(exception), '[MockDevice]::Service<None> Some error message.') - - def test_subclass_service_error(self): - class Error(errors.ServiceError): - SERVICE_TYPE = 'SomeType' - - device = mock.MagicMock() - device.__repr__ = lambda _: '[MockDevice]' - exception = Error(device, 'Some error message.') - self.assertEqual( - str(exception), - '[MockDevice]::Service<SomeType> Some error message.') + def test_device_error(self): + device = mock.MagicMock() + device.__repr__ = lambda _: '[MockDevice]' + exception = errors.DeviceError(device, 'Some error message.') + self.assertEqual(str(exception), '[MockDevice] Some error message.') + + def test_service_error(self): + device = mock.MagicMock() + device.__repr__ = lambda _: '[MockDevice]' + exception = errors.ServiceError(device, 'Some error message.') + self.assertEqual( + str(exception), '[MockDevice]::Service<None> Some error message.') + + def test_subclass_service_error(self): + class Error(errors.ServiceError): + SERVICE_TYPE = 'SomeType' + + device = mock.MagicMock() + device.__repr__ = lambda _: '[MockDevice]' + exception = Error(device, 'Some error message.') + self.assertEqual( + str(exception), + '[MockDevice]::Service<SomeType> Some error message.') if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/jsonrpc_client_base_test.py b/tests/mobly/controllers/android_device_lib/jsonrpc_client_base_test.py index 583c52c..aef3c73 100755 --- a/tests/mobly/controllers/android_device_lib/jsonrpc_client_base_test.py +++ b/tests/mobly/controllers/android_device_lib/jsonrpc_client_base_test.py @@ -24,288 +24,288 @@ from tests.lib import jsonrpc_client_test_base class FakeRpcClient(jsonrpc_client_base.JsonRpcClientBase): - def __init__(self): - super(FakeRpcClient, self).__init__( - app_name='FakeRpcClient', ad=mock.Mock()) + def __init__(self): + super(FakeRpcClient, self).__init__( + app_name='FakeRpcClient', ad=mock.Mock()) class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase): - """Unit tests for mobly.controllers.android_device_lib.jsonrpc_client_base. + """Unit tests for mobly.controllers.android_device_lib.jsonrpc_client_base. + """ + + @mock.patch('socket.create_connection') + def test_open_timeout_io_error(self, mock_create_connection): + """Test socket timeout with io error + + Test that if the net socket gives an io error, then the client + will eventually exit with an IOError. + """ + mock_create_connection.side_effect = IOError() + with self.assertRaises(IOError): + client = FakeRpcClient() + client.connect() + + @mock.patch('socket.create_connection') + def test_connect_timeout(self, mock_create_connection): + """Test socket timeout + + Test that a timeout exception will be raised if the socket gives a + timeout. + """ + mock_create_connection.side_effect = socket.timeout + with self.assertRaises(socket.timeout): + client = FakeRpcClient() + client.connect() + + @mock.patch('socket.create_connection') + def test_handshake_error(self, mock_create_connection): + """Test error in jsonrpc handshake + + Test that if there is an error in the jsonrpc handshake then a protocol + error will be raised. + """ + self.setup_mock_socket_file(mock_create_connection, resp=None) + client = FakeRpcClient() + with self.assertRaisesRegex( + jsonrpc_client_base.ProtocolError, + jsonrpc_client_base.ProtocolError.NO_RESPONSE_FROM_HANDSHAKE): + client.connect() + + @mock.patch('socket.create_connection') + def test_connect_handshake(self, mock_create_connection): + """Test client handshake + + Test that at the end of a handshake with no errors the client object + has the correct parameters. + """ + self.setup_mock_socket_file(mock_create_connection) + client = FakeRpcClient() + client.connect() + self.assertEqual(client.uid, 1) + + @mock.patch('socket.create_connection') + def test_connect_handshake_unknown_status(self, mock_create_connection): + """Test handshake with unknown status response + + Test that when the handshake is given an unknown status then the client + will not be given a uid. + """ + self.setup_mock_socket_file( + mock_create_connection, resp=self.MOCK_RESP_UNKNOWN_STATUS) + client = FakeRpcClient() + client.connect() + self.assertEqual(client.uid, jsonrpc_client_base.UNKNOWN_UID) + + @mock.patch('socket.create_connection') + def test_rpc_error_response(self, mock_create_connection): + """Test rpc that is given an error response + + Test that when an rpc receives a response with an error will raised + an api error. + """ + fake_file = self.setup_mock_socket_file(mock_create_connection) + + client = FakeRpcClient() + client.connect() + + fake_file.resp = self.MOCK_RESP_WITH_ERROR + + with self.assertRaisesRegex(jsonrpc_client_base.ApiError, '1'): + client.some_rpc(1, 2, 3) + + @mock.patch('socket.create_connection') + def test_rpc_callback_response(self, mock_create_connection): + """Test rpc that is given a callback response. + + Test that when an rpc receives a callback response, a callback object is + created correctly. + """ + fake_file = self.setup_mock_socket_file(mock_create_connection) + + client = FakeRpcClient() + client.connect() + + fake_file.resp = self.MOCK_RESP_WITH_CALLBACK + client._event_client = mock.Mock() + + callback = client.some_rpc(1, 2, 3) + self.assertEqual(callback.ret_value, 123) + self.assertEqual(callback._id, '1-0') + + @mock.patch('socket.create_connection') + def test_rpc_id_mismatch(self, mock_create_connection): + """Test rpc that returns a different id than expected + + Test that if an rpc returns with an id that is different than what + is expected will give a protocl error. + """ + fake_file = self.setup_mock_socket_file(mock_create_connection) + + client = FakeRpcClient() + client.connect() + + fake_file.resp = (self.MOCK_RESP_TEMPLATE % 52).encode('utf8') + + with self.assertRaisesRegex( + jsonrpc_client_base.ProtocolError, + jsonrpc_client_base.ProtocolError.MISMATCHED_API_ID): + client.some_rpc(1, 2, 3) + + @mock.patch('socket.create_connection') + def test_rpc_no_response(self, mock_create_connection): + """Test rpc that does not get a response + + Test that when an rpc does not get a response it throws a protocol + error. """ + fake_file = self.setup_mock_socket_file(mock_create_connection) - @mock.patch('socket.create_connection') - def test_open_timeout_io_error(self, mock_create_connection): - """Test socket timeout with io error - - Test that if the net socket gives an io error, then the client - will eventually exit with an IOError. - """ - mock_create_connection.side_effect = IOError() - with self.assertRaises(IOError): - client = FakeRpcClient() - client.connect() - - @mock.patch('socket.create_connection') - def test_connect_timeout(self, mock_create_connection): - """Test socket timeout - - Test that a timeout exception will be raised if the socket gives a - timeout. - """ - mock_create_connection.side_effect = socket.timeout - with self.assertRaises(socket.timeout): - client = FakeRpcClient() - client.connect() - - @mock.patch('socket.create_connection') - def test_handshake_error(self, mock_create_connection): - """Test error in jsonrpc handshake - - Test that if there is an error in the jsonrpc handshake then a protocol - error will be raised. - """ - self.setup_mock_socket_file(mock_create_connection, resp=None) - client = FakeRpcClient() - with self.assertRaisesRegex( - jsonrpc_client_base.ProtocolError, - jsonrpc_client_base.ProtocolError.NO_RESPONSE_FROM_HANDSHAKE): - client.connect() - - @mock.patch('socket.create_connection') - def test_connect_handshake(self, mock_create_connection): - """Test client handshake - - Test that at the end of a handshake with no errors the client object - has the correct parameters. - """ - self.setup_mock_socket_file(mock_create_connection) - client = FakeRpcClient() - client.connect() - self.assertEqual(client.uid, 1) - - @mock.patch('socket.create_connection') - def test_connect_handshake_unknown_status(self, mock_create_connection): - """Test handshake with unknown status response - - Test that when the handshake is given an unknown status then the client - will not be given a uid. - """ - self.setup_mock_socket_file( - mock_create_connection, resp=self.MOCK_RESP_UNKNOWN_STATUS) - client = FakeRpcClient() - client.connect() - self.assertEqual(client.uid, jsonrpc_client_base.UNKNOWN_UID) - - @mock.patch('socket.create_connection') - def test_rpc_error_response(self, mock_create_connection): - """Test rpc that is given an error response - - Test that when an rpc receives a response with an error will raised - an api error. - """ - fake_file = self.setup_mock_socket_file(mock_create_connection) - - client = FakeRpcClient() - client.connect() - - fake_file.resp = self.MOCK_RESP_WITH_ERROR - - with self.assertRaisesRegex(jsonrpc_client_base.ApiError, '1'): - client.some_rpc(1, 2, 3) - - @mock.patch('socket.create_connection') - def test_rpc_callback_response(self, mock_create_connection): - """Test rpc that is given a callback response. - - Test that when an rpc receives a callback response, a callback object is - created correctly. - """ - fake_file = self.setup_mock_socket_file(mock_create_connection) - - client = FakeRpcClient() - client.connect() - - fake_file.resp = self.MOCK_RESP_WITH_CALLBACK - client._event_client = mock.Mock() - - callback = client.some_rpc(1, 2, 3) - self.assertEqual(callback.ret_value, 123) - self.assertEqual(callback._id, '1-0') - - @mock.patch('socket.create_connection') - def test_rpc_id_mismatch(self, mock_create_connection): - """Test rpc that returns a different id than expected - - Test that if an rpc returns with an id that is different than what - is expected will give a protocl error. - """ - fake_file = self.setup_mock_socket_file(mock_create_connection) - - client = FakeRpcClient() - client.connect() - - fake_file.resp = (self.MOCK_RESP_TEMPLATE % 52).encode('utf8') - - with self.assertRaisesRegex( - jsonrpc_client_base.ProtocolError, - jsonrpc_client_base.ProtocolError.MISMATCHED_API_ID): - client.some_rpc(1, 2, 3) - - @mock.patch('socket.create_connection') - def test_rpc_no_response(self, mock_create_connection): - """Test rpc that does not get a response - - Test that when an rpc does not get a response it throws a protocol - error. - """ - fake_file = self.setup_mock_socket_file(mock_create_connection) + client = FakeRpcClient() + client.connect() - client = FakeRpcClient() - client.connect() - - fake_file.resp = None + fake_file.resp = None - with self.assertRaisesRegex( - jsonrpc_client_base.ProtocolError, - jsonrpc_client_base.ProtocolError.NO_RESPONSE_FROM_SERVER): - client.some_rpc(1, 2, 3) + with self.assertRaisesRegex( + jsonrpc_client_base.ProtocolError, + jsonrpc_client_base.ProtocolError.NO_RESPONSE_FROM_SERVER): + client.some_rpc(1, 2, 3) - @mock.patch('socket.create_connection') - def test_rpc_send_to_socket(self, mock_create_connection): - """Test rpc sending and recieving + @mock.patch('socket.create_connection') + def test_rpc_send_to_socket(self, mock_create_connection): + """Test rpc sending and recieving - Tests that when an rpc is sent and received the corrent data - is used. - """ - fake_file = self.setup_mock_socket_file(mock_create_connection) + Tests that when an rpc is sent and received the corrent data + is used. + """ + fake_file = self.setup_mock_socket_file(mock_create_connection) - client = FakeRpcClient() - client.connect() + client = FakeRpcClient() + client.connect() - result = client.some_rpc(1, 2, 3) - self.assertEqual(result, 123) + result = client.some_rpc(1, 2, 3) + self.assertEqual(result, 123) - expected = {'id': 0, 'method': 'some_rpc', 'params': [1, 2, 3]} - actual = json.loads(fake_file.last_write.decode('utf-8')) + expected = {'id': 0, 'method': 'some_rpc', 'params': [1, 2, 3]} + actual = json.loads(fake_file.last_write.decode('utf-8')) - self.assertEqual(expected, actual) + self.assertEqual(expected, actual) - @mock.patch('socket.create_connection') - def test_rpc_send_to_socket_without_callback(self, mock_create_connection): - """Test rpc sending and recieving with Rpc protocol before callback was - added to the resp message. + @mock.patch('socket.create_connection') + def test_rpc_send_to_socket_without_callback(self, mock_create_connection): + """Test rpc sending and recieving with Rpc protocol before callback was + added to the resp message. - Logic is the same as test_rpc_send_to_socket. - """ - fake_file = self.setup_mock_socket_file( - mock_create_connection, resp=self.MOCK_RESP_WITHOUT_CALLBACK) + Logic is the same as test_rpc_send_to_socket. + """ + fake_file = self.setup_mock_socket_file( + mock_create_connection, resp=self.MOCK_RESP_WITHOUT_CALLBACK) + + client = FakeRpcClient() + client.connect() - client = FakeRpcClient() - client.connect() + result = client.some_rpc(1, 2, 3) + self.assertEqual(result, 123) - result = client.some_rpc(1, 2, 3) - self.assertEqual(result, 123) + expected = {'id': 0, 'method': 'some_rpc', 'params': [1, 2, 3]} + actual = json.loads(fake_file.last_write.decode('utf-8')) - expected = {'id': 0, 'method': 'some_rpc', 'params': [1, 2, 3]} - actual = json.loads(fake_file.last_write.decode('utf-8')) + self.assertEqual(expected, actual) - self.assertEqual(expected, actual) + @mock.patch('socket.create_connection') + def test_rpc_call_increment_counter(self, mock_create_connection): + """Test rpc counter - @mock.patch('socket.create_connection') - def test_rpc_call_increment_counter(self, mock_create_connection): - """Test rpc counter + Test that with each rpc call the counter is incremented by 1. + """ + fake_file = self.setup_mock_socket_file(mock_create_connection) - Test that with each rpc call the counter is incremented by 1. - """ - fake_file = self.setup_mock_socket_file(mock_create_connection) + client = FakeRpcClient() + client.connect() - client = FakeRpcClient() - client.connect() + for i in range(0, 10): + fake_file.resp = (self.MOCK_RESP_TEMPLATE % i).encode('utf-8') + client.some_rpc() - for i in range(0, 10): - fake_file.resp = (self.MOCK_RESP_TEMPLATE % i).encode('utf-8') - client.some_rpc() + self.assertEqual(next(client._counter), 10) - self.assertEqual(next(client._counter), 10) + @mock.patch('socket.create_connection') + def test_rpc_verbose_logging_with_long_string(self, + mock_create_connection): + """Test rpc response fully write into DEBUG level log.""" + fake_file = self.setup_mock_socket_file(mock_create_connection) + testing_rpc_response = self.generate_rpc_response(4000) + fake_file.resp = testing_rpc_response - @mock.patch('socket.create_connection') - def test_rpc_verbose_logging_with_long_string(self, - mock_create_connection): - """Test rpc response fully write into DEBUG level log.""" - fake_file = self.setup_mock_socket_file(mock_create_connection) - testing_rpc_response = self.generate_rpc_response(4000) - fake_file.resp = testing_rpc_response + client = FakeRpcClient() + client.connect() - client = FakeRpcClient() - client.connect() + response = client._client_receive() + self.assertEqual(response, testing_rpc_response) - response = client._client_receive() - self.assertEqual(response, testing_rpc_response) + client.log.debug.assert_called_with('Snippet received: %s', + testing_rpc_response) - client.log.debug.assert_called_with('Snippet received: %s', - testing_rpc_response) + @mock.patch('socket.create_connection') + def test_rpc_truncated_logging_short_response(self, + mock_create_connection): + """Test rpc response will full logged when length is short.""" + fake_file = self.setup_mock_socket_file(mock_create_connection) + testing_rpc_response = self.generate_rpc_response( + int(jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH / 2)) + fake_file.resp = testing_rpc_response - @mock.patch('socket.create_connection') - def test_rpc_truncated_logging_short_response(self, - mock_create_connection): - """Test rpc response will full logged when length is short.""" - fake_file = self.setup_mock_socket_file(mock_create_connection) - testing_rpc_response = self.generate_rpc_response( - int(jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH / 2)) - fake_file.resp = testing_rpc_response + client = FakeRpcClient() + client.connect() - client = FakeRpcClient() - client.connect() + client.set_snippet_client_verbose_logging(False) + response = client._client_receive() - client.set_snippet_client_verbose_logging(False) - response = client._client_receive() + self.assertEqual(response, testing_rpc_response) + client.log.debug.assert_called_with('Snippet received: %s', + testing_rpc_response) - self.assertEqual(response, testing_rpc_response) - client.log.debug.assert_called_with('Snippet received: %s', - testing_rpc_response) + @mock.patch('socket.create_connection') + def test_rpc_truncated_logging_fit_size_response(self, + mock_create_connection): + """Test rpc response will full logged when length is equal to threshold. + """ + fake_file = self.setup_mock_socket_file(mock_create_connection) + testing_rpc_response = self.generate_rpc_response( + jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH) + fake_file.resp = testing_rpc_response - @mock.patch('socket.create_connection') - def test_rpc_truncated_logging_fit_size_response(self, - mock_create_connection): - """Test rpc response will full logged when length is equal to threshold. - """ - fake_file = self.setup_mock_socket_file(mock_create_connection) - testing_rpc_response = self.generate_rpc_response( - jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH) - fake_file.resp = testing_rpc_response + client = FakeRpcClient() + client.connect() - client = FakeRpcClient() - client.connect() + client.set_snippet_client_verbose_logging(False) + response = client._client_receive() - client.set_snippet_client_verbose_logging(False) - response = client._client_receive() + self.assertEqual(response, testing_rpc_response) + client.log.debug.assert_called_with('Snippet received: %s', + testing_rpc_response) - self.assertEqual(response, testing_rpc_response) - client.log.debug.assert_called_with('Snippet received: %s', - testing_rpc_response) + @mock.patch('socket.create_connection') + def test_rpc_truncated_logging_long_response(self, mock_create_connection): + """Test rpc response truncated with given length in DEBUG level log.""" + fake_file = self.setup_mock_socket_file(mock_create_connection) + resp_len = jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH * 40 + testing_rpc_response = self.generate_rpc_response(resp_len) + fake_file.resp = testing_rpc_response - @mock.patch('socket.create_connection') - def test_rpc_truncated_logging_long_response(self, mock_create_connection): - """Test rpc response truncated with given length in DEBUG level log.""" - fake_file = self.setup_mock_socket_file(mock_create_connection) - resp_len = jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH * 40 - testing_rpc_response = self.generate_rpc_response(resp_len) - fake_file.resp = testing_rpc_response - - client = FakeRpcClient() - client.connect() + client = FakeRpcClient() + client.connect() - client.set_snippet_client_verbose_logging(False) - response = client._client_receive() + client.set_snippet_client_verbose_logging(False) + response = client._client_receive() - self.assertEqual(response, testing_rpc_response) - # DEBUG level log should truncated by given length. - client.log.debug.assert_called_with( - 'Snippet received: %s... %d chars are truncated', - testing_rpc_response - [:jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH], - resp_len - jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH) + self.assertEqual(response, testing_rpc_response) + # DEBUG level log should truncated by given length. + client.log.debug.assert_called_with( + 'Snippet received: %s... %d chars are truncated', + testing_rpc_response + [:jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH], + resp_len - jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH) if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/jsonrpc_shell_base_test.py b/tests/mobly/controllers/android_device_lib/jsonrpc_shell_base_test.py index 677cb89..fb9db4f 100755 --- a/tests/mobly/controllers/android_device_lib/jsonrpc_shell_base_test.py +++ b/tests/mobly/controllers/android_device_lib/jsonrpc_shell_base_test.py @@ -22,70 +22,70 @@ from mobly.controllers.android_device_lib import jsonrpc_shell_base class JsonRpcClientBaseTest(unittest.TestCase): - """Unit tests for mobly.controllers.android_device_lib.jsonrpc_shell_base. - """ + """Unit tests for mobly.controllers.android_device_lib.jsonrpc_shell_base. + """ - @mock.patch.object(android_device, 'list_adb_devices') - @mock.patch.object(android_device, 'get_instances') - @mock.patch.object(os, 'environ', new={}) - def test_load_device(self, mock_get_instances, mock_list_adb_devices): - mock_list_adb_devices.return_value = ['1234', '4312'] - mock_device = mock.MagicMock(spec=android_device.AndroidDevice) - mock_get_instances.return_value = [mock_device] - json_shell = jsonrpc_shell_base.JsonRpcShellBase() - json_shell.load_device(serial='1234') - self.assertEqual(json_shell._ad, mock_device) + @mock.patch.object(android_device, 'list_adb_devices') + @mock.patch.object(android_device, 'get_instances') + @mock.patch.object(os, 'environ', new={}) + def test_load_device(self, mock_get_instances, mock_list_adb_devices): + mock_list_adb_devices.return_value = ['1234', '4312'] + mock_device = mock.MagicMock(spec=android_device.AndroidDevice) + mock_get_instances.return_value = [mock_device] + json_shell = jsonrpc_shell_base.JsonRpcShellBase() + json_shell.load_device(serial='1234') + self.assertEqual(json_shell._ad, mock_device) - @mock.patch.object(android_device, 'list_adb_devices') - @mock.patch.object(android_device, 'get_instances') - @mock.patch.object(os, 'environ', new={}) - def test_load_device_when_one_device(self, mock_get_instances, - mock_list_adb_devices): - mock_list_adb_devices.return_value = ['1234'] - mock_device = mock.MagicMock(spec=android_device.AndroidDevice) - mock_get_instances.return_value = [mock_device] - json_shell = jsonrpc_shell_base.JsonRpcShellBase() - json_shell.load_device() - self.assertEqual(json_shell._ad, mock_device) + @mock.patch.object(android_device, 'list_adb_devices') + @mock.patch.object(android_device, 'get_instances') + @mock.patch.object(os, 'environ', new={}) + def test_load_device_when_one_device(self, mock_get_instances, + mock_list_adb_devices): + mock_list_adb_devices.return_value = ['1234'] + mock_device = mock.MagicMock(spec=android_device.AndroidDevice) + mock_get_instances.return_value = [mock_device] + json_shell = jsonrpc_shell_base.JsonRpcShellBase() + json_shell.load_device() + self.assertEqual(json_shell._ad, mock_device) - @mock.patch.object(android_device, 'list_adb_devices') - @mock.patch.object(android_device, 'get_instances') - @mock.patch.object(os, 'environ', new={'ANDROID_SERIAL': '1234'}) - def test_load_device_when_android_serial(self, mock_get_instances, - mock_list_adb_devices): - mock_list_adb_devices.return_value = ['1234', '4321'] - mock_device = mock.MagicMock(spec=android_device.AndroidDevice) - mock_get_instances.return_value = [mock_device] - json_shell = jsonrpc_shell_base.JsonRpcShellBase() - json_shell.load_device() - self.assertEqual(json_shell._ad, mock_device) + @mock.patch.object(android_device, 'list_adb_devices') + @mock.patch.object(android_device, 'get_instances') + @mock.patch.object(os, 'environ', new={'ANDROID_SERIAL': '1234'}) + def test_load_device_when_android_serial(self, mock_get_instances, + mock_list_adb_devices): + mock_list_adb_devices.return_value = ['1234', '4321'] + mock_device = mock.MagicMock(spec=android_device.AndroidDevice) + mock_get_instances.return_value = [mock_device] + json_shell = jsonrpc_shell_base.JsonRpcShellBase() + json_shell.load_device() + self.assertEqual(json_shell._ad, mock_device) - @mock.patch.object(android_device, 'list_adb_devices') - def test_load_device_when_no_devices(self, mock_list_adb_devices): - mock_list_adb_devices.return_value = [] - json_shell = jsonrpc_shell_base.JsonRpcShellBase() - with self.assertRaisesRegex(jsonrpc_shell_base.Error, - 'No adb device found!'): - json_shell.load_device() + @mock.patch.object(android_device, 'list_adb_devices') + def test_load_device_when_no_devices(self, mock_list_adb_devices): + mock_list_adb_devices.return_value = [] + json_shell = jsonrpc_shell_base.JsonRpcShellBase() + with self.assertRaisesRegex(jsonrpc_shell_base.Error, + 'No adb device found!'): + json_shell.load_device() - @mock.patch.object(android_device, 'list_adb_devices') - @mock.patch.object(os, 'environ', new={}) - def test_load_device_when_unspecified_device(self, mock_list_adb_devices): - mock_list_adb_devices.return_value = ['1234', '4321'] - json_shell = jsonrpc_shell_base.JsonRpcShellBase() - with self.assertRaisesRegex(jsonrpc_shell_base.Error, - 'Expected one phone.*'): - json_shell.load_device() + @mock.patch.object(android_device, 'list_adb_devices') + @mock.patch.object(os, 'environ', new={}) + def test_load_device_when_unspecified_device(self, mock_list_adb_devices): + mock_list_adb_devices.return_value = ['1234', '4321'] + json_shell = jsonrpc_shell_base.JsonRpcShellBase() + with self.assertRaisesRegex(jsonrpc_shell_base.Error, + 'Expected one phone.*'): + json_shell.load_device() - @mock.patch.object(android_device, 'list_adb_devices') - @mock.patch.object(os, 'environ', new={}) - def test_load_device_when_device_not_found(self, mock_list_adb_devices): - mock_list_adb_devices.return_value = ['4321'] - json_shell = jsonrpc_shell_base.JsonRpcShellBase() - with self.assertRaisesRegex(jsonrpc_shell_base.Error, - 'Device "1234" is not found by adb.'): - json_shell.load_device(serial='1234') + @mock.patch.object(android_device, 'list_adb_devices') + @mock.patch.object(os, 'environ', new={}) + def test_load_device_when_device_not_found(self, mock_list_adb_devices): + mock_list_adb_devices.return_value = ['4321'] + json_shell = jsonrpc_shell_base.JsonRpcShellBase() + with self.assertRaisesRegex(jsonrpc_shell_base.Error, + 'Device "1234" is not found by adb.'): + json_shell.load_device(serial='1234') if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/service_manager_test.py b/tests/mobly/controllers/android_device_lib/service_manager_test.py index c989e83..90efb1d 100755 --- a/tests/mobly/controllers/android_device_lib/service_manager_test.py +++ b/tests/mobly/controllers/android_device_lib/service_manager_test.py @@ -23,452 +23,452 @@ from mobly.controllers.android_device_lib.services import base_service class MockService(base_service.BaseService): - def __init__(self, device, configs=None): - self._device = device - self._configs = configs - self._alive = False - self.start_func = mock.MagicMock() - self.stop_func = mock.MagicMock() - self.pause_func = mock.MagicMock() - self.resume_func = mock.MagicMock() + def __init__(self, device, configs=None): + self._device = device + self._configs = configs + self._alive = False + self.start_func = mock.MagicMock() + self.stop_func = mock.MagicMock() + self.pause_func = mock.MagicMock() + self.resume_func = mock.MagicMock() - @property - def is_alive(self): - return self._alive + @property + def is_alive(self): + return self._alive - def start(self, configs=None): - self.start_func(configs) - self._alive = True + def start(self, configs=None): + self.start_func(configs) + self._alive = True - def stop(self): - self.stop_func() - self._alive = False + def stop(self): + self.stop_func() + self._alive = False - def pause(self): - self.pause_func() - self._alive = False + def pause(self): + self.pause_func() + self._alive = False - def resume(self): - self.resume_func() - self._alive = True + def resume(self): + self.resume_func() + self._alive = True class ServiceManagerTest(unittest.TestCase): - def setUp(self): - # Reset hidden global `expects` state. - if sys.version_info < (3, 0): - reload(expects) - else: - import importlib - importlib.reload(expects) - - def assert_recorded_one_error(self, message): - self.assertEqual(expects.recorder.error_count, 1) - for _, error in ( - expects.DEFAULT_TEST_RESULT_RECORD.extra_errors.items()): - self.assertIn(message, error.details) - - def test_service_manager_instantiation(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - - def test_register(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service', MockService) - service = manager.mock_service - self.assertTrue(service) - self.assertTrue(service.is_alive) - self.assertTrue(manager.is_any_alive) - self.assertEqual(service.alias, 'mock_service') - self.assertEqual(service.start_func.call_count, 1) - - def test_register_with_configs(self): - mock_configs = mock.MagicMock() - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service', MockService, configs=mock_configs) - service = manager.mock_service - self.assertTrue(service) - self.assertEqual(service._configs, mock_configs) - self.assertEqual(service.start_func.call_count, 1) - - def test_register_do_not_start_service(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service', MockService, start_service=False) - service = manager.mock_service - self.assertTrue(service) - self.assertFalse(service.is_alive) - self.assertFalse(manager.is_any_alive) - self.assertEqual(service.start_func.call_count, 0) - - def test_register_not_a_class(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - with self.assertRaisesRegex(service_manager.Error, - '.* is not a class!'): - manager.register('mock_service', base_service) - - def test_register_wrong_subclass_type(self): - class MyClass(object): - pass - - manager = service_manager.ServiceManager(mock.MagicMock()) - with self.assertRaisesRegex(service_manager.Error, - '.* is not a subclass of BaseService!'): - manager.register('mock_service', MyClass) - - def test_register_dup_alias(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service', MockService) - msg = '.* A service is already registered with alias "mock_service"' - with self.assertRaisesRegex(service_manager.Error, msg): - manager.register('mock_service', MockService) - - def test_for_each(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - service1.ha = mock.MagicMock() - service2.ha = mock.MagicMock() - manager.for_each(lambda service: service.ha()) - service1.ha.assert_called_with() - service2.ha.assert_called_with() - - def test_for_each_modify_during_iteration(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - service1.ha = mock.MagicMock() - service2.ha = mock.MagicMock() - manager.for_each(lambda service: manager._service_objects.pop(service. - alias)) - self.assertFalse(manager._service_objects) - - def test_for_each_one_fail(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - service1.ha = mock.MagicMock() - service1.ha.side_effect = Exception('Failure in service1.') - service2.ha = mock.MagicMock() - manager.for_each(lambda service: service.ha()) - service1.ha.assert_called_with() - service2.ha.assert_called_with() - self.assert_recorded_one_error('Failure in service1.') - - def test_create_output_excerpts_all(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - manager.register('mock_service3', MockService) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - service3 = manager.mock_service3 - service1.create_output_excerpts = mock.MagicMock() - service2.create_output_excerpts = mock.MagicMock() - service3.create_output_excerpts = mock.MagicMock() - service1.create_output_excerpts.return_value = ['path/to/1.txt'] - service2.create_output_excerpts.return_value = [ - 'path/to/2-1.txt', 'path/to/2-2.txt' - ] - service3.create_output_excerpts.return_value = [] - mock_test_info = mock.MagicMock(output_path='path/to') - result = manager.create_output_excerpts_all(mock_test_info) - self.assertEqual(result['mock_service1'], ['path/to/1.txt']) - self.assertEqual(result['mock_service2'], - ['path/to/2-1.txt', 'path/to/2-2.txt']) - self.assertEqual(result['mock_service3'], []) - - def test_unregister(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service', MockService) - service = manager.mock_service - manager.unregister('mock_service') - self.assertFalse(manager.is_any_alive) - self.assertFalse(service.is_alive) - self.assertEqual(service.stop_func.call_count, 1) - - def test_unregister_not_started_service(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service', MockService, start_service=False) - service = manager.mock_service - manager.unregister('mock_service') - self.assertFalse(manager.is_any_alive) - self.assertFalse(service.is_alive) - self.assertEqual(service.stop_func.call_count, 0) - - def test_unregister_non_existent(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - with self.assertRaisesRegex( - service_manager.Error, - '.* No service is registered with alias "mock_service"'): - manager.unregister('mock_service') - - def test_unregister_handle_error_from_stop(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service', MockService) - service = manager.mock_service - service.stop_func.side_effect = Exception('Something failed in stop.') - manager.unregister('mock_service') - self.assert_recorded_one_error( - 'Failed to stop service instance "mock_service".') - - def test_unregister_all(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - manager.unregister_all() - self.assertFalse(manager.is_any_alive) - self.assertFalse(service1.is_alive) - self.assertFalse(service2.is_alive) - self.assertEqual(service1.stop_func.call_count, 1) - self.assertEqual(service2.stop_func.call_count, 1) - - def test_unregister_all_with_some_failed(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service1.stop_func.side_effect = Exception('Something failed in stop.') - service2 = manager.mock_service2 - manager.unregister_all() - self.assertFalse(manager.is_any_alive) - self.assertTrue(service1.is_alive) - self.assertFalse(service2.is_alive) - self.assert_recorded_one_error( - 'Failed to stop service instance "mock_service1".') - - def test_start_all(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService, start_service=False) - manager.register('mock_service2', MockService, start_service=False) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - mock_call_tracker = mock.Mock() - mock_call_tracker.start1 = service1.start_func - mock_call_tracker.start2 = service2.start_func - manager.start_all() - self.assertTrue(service1.is_alive) - self.assertTrue(service2.is_alive) - self.assertEqual(service1.start_func.call_count, 1) - self.assertEqual(service2.start_func.call_count, 1) - self.assertEqual(mock_call_tracker.mock_calls, - [mock.call.start1(None), - mock.call.start2(None)]) - - def test_start_all_with_already_started_services(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService, start_service=False) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - manager.start_all() - manager.start_all() - self.assertTrue(service1.is_alive) - self.assertTrue(service2.is_alive) - self.assertEqual(service1.start_func.call_count, 1) - self.assertEqual(service2.start_func.call_count, 1) - - def test_start_all_with_some_failed(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService, start_service=False) - manager.register('mock_service2', MockService, start_service=False) - service1 = manager.mock_service1 - service1.start_func.side_effect = Exception( - 'Something failed in start.') - service2 = manager.mock_service2 - manager.start_all() - self.assertFalse(service1.is_alive) - self.assertTrue(service2.is_alive) - self.assert_recorded_one_error( - 'Failed to start service "mock_service1"') - - def test_stop_all(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - mock_call_tracker = mock.Mock() - mock_call_tracker.stop1 = service1.stop_func - mock_call_tracker.stop2 = service2.stop_func - manager.stop_all() - self.assertFalse(service1.is_alive) - self.assertFalse(service2.is_alive) - self.assertEqual( - mock_call_tracker.mock_calls, - [mock.call.stop2(), mock.call.stop1()]) - self.assertEqual(service1.start_func.call_count, 1) - self.assertEqual(service2.start_func.call_count, 1) - self.assertEqual(service1.stop_func.call_count, 1) - self.assertEqual(service2.stop_func.call_count, 1) - - def test_stop_all_with_already_stopped_services(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService, start_service=False) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - manager.stop_all() - manager.stop_all() - self.assertFalse(service1.is_alive) - self.assertFalse(service2.is_alive) - self.assertEqual(service1.start_func.call_count, 1) - self.assertEqual(service2.start_func.call_count, 0) - self.assertEqual(service1.stop_func.call_count, 1) - self.assertEqual(service2.stop_func.call_count, 0) - - def test_stop_all_with_some_failed(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service1.stop_func.side_effect = Exception( - 'Something failed in start.') - service2 = manager.mock_service2 - manager.stop_all() - self.assertTrue(service1.is_alive) - self.assertFalse(service2.is_alive) - self.assert_recorded_one_error( - 'Failed to stop service "mock_service1"') - - def test_start_all_and_stop_all_serveral_times(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService, start_service=False) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - manager.stop_all() - manager.start_all() - manager.stop_all() - manager.start_all() - manager.stop_all() - manager.start_all() - self.assertTrue(service1.is_alive) - self.assertTrue(service2.is_alive) - self.assertEqual(service1.start_func.call_count, 4) - self.assertEqual(service2.start_func.call_count, 3) - self.assertEqual(service1.stop_func.call_count, 3) - self.assertEqual(service2.stop_func.call_count, 2) - - def test_pause_all(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - mock_call_tracker = mock.Mock() - mock_call_tracker.pause1 = service1.pause_func - mock_call_tracker.pause2 = service2.pause_func - manager.pause_all() - self.assertEqual( - mock_call_tracker.mock_calls, - [mock.call.pause2(), mock.call.pause1()]) - self.assertEqual(service1.pause_func.call_count, 1) - self.assertEqual(service2.pause_func.call_count, 1) - self.assertEqual(service1.resume_func.call_count, 0) - self.assertEqual(service2.resume_func.call_count, 0) - - def test_pause_all_with_some_failed(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service1.pause_func.side_effect = Exception( - 'Something failed in pause.') - service2 = manager.mock_service2 - manager.pause_all() - self.assertEqual(service1.pause_func.call_count, 1) - self.assertEqual(service2.pause_func.call_count, 1) - self.assertEqual(service1.resume_func.call_count, 0) - self.assertEqual(service2.resume_func.call_count, 0) - self.assert_recorded_one_error( - 'Failed to pause service "mock_service1".') - - def test_resume_all(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service2 = manager.mock_service2 - mock_call_tracker = mock.Mock() - mock_call_tracker.resume1 = service1.resume_func - mock_call_tracker.resume2 = service2.resume_func - manager.pause_all() - manager.resume_all() - self.assertEqual( - mock_call_tracker.mock_calls, - [mock.call.resume1(), mock.call.resume2()]) - self.assertEqual(service1.pause_func.call_count, 1) - self.assertEqual(service2.pause_func.call_count, 1) - self.assertEqual(service1.resume_func.call_count, 1) - self.assertEqual(service2.resume_func.call_count, 1) - - def test_resume_all_with_some_failed(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - service1 = manager.mock_service1 - service1.resume_func.side_effect = Exception( - 'Something failed in resume.') - service2 = manager.mock_service2 - manager.pause_all() - manager.resume_all() - self.assertEqual(service1.pause_func.call_count, 1) - self.assertEqual(service2.pause_func.call_count, 1) - self.assertEqual(service1.resume_func.call_count, 1) - self.assertEqual(service2.resume_func.call_count, 1) - self.assert_recorded_one_error( - 'Failed to resume service "mock_service1".') - - def test_list_live_services(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService, start_service=False) - manager.register('mock_service2', MockService) - aliases = manager.list_live_services() - self.assertEqual(aliases, ['mock_service2']) - manager.stop_all() - aliases = manager.list_live_services() - self.assertEqual(aliases, []) - - def test_start_services(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService, start_service=False) - manager.register('mock_service2', MockService, start_service=False) - manager.start_services(['mock_service2']) - aliases = manager.list_live_services() - self.assertEqual(aliases, ['mock_service2']) - - def test_start_services_non_existent(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - msg = ('.* No service is registered under the name "mock_service", ' - 'cannot start.') - with self.assertRaisesRegex(service_manager.Error, msg): - manager.start_services(['mock_service']) - - def test_resume_services(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - manager.register('mock_service1', MockService) - manager.register('mock_service2', MockService) - manager.pause_all() - aliases = manager.list_live_services() - self.assertEqual(aliases, []) - manager.resume_services(['mock_service2']) - aliases = manager.list_live_services() - self.assertEqual(aliases, ['mock_service2']) - - def test_resume_services_non_existent(self): - manager = service_manager.ServiceManager(mock.MagicMock()) - msg = ('.* No service is registered under the name "mock_service", ' - 'cannot resume.') - with self.assertRaisesRegex(service_manager.Error, msg): - manager.resume_services(['mock_service']) + def setUp(self): + # Reset hidden global `expects` state. + if sys.version_info < (3, 0): + reload(expects) + else: + import importlib + importlib.reload(expects) + + def assert_recorded_one_error(self, message): + self.assertEqual(expects.recorder.error_count, 1) + for _, error in ( + expects.DEFAULT_TEST_RESULT_RECORD.extra_errors.items()): + self.assertIn(message, error.details) + + def test_service_manager_instantiation(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + + def test_register(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service', MockService) + service = manager.mock_service + self.assertTrue(service) + self.assertTrue(service.is_alive) + self.assertTrue(manager.is_any_alive) + self.assertEqual(service.alias, 'mock_service') + self.assertEqual(service.start_func.call_count, 1) + + def test_register_with_configs(self): + mock_configs = mock.MagicMock() + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service', MockService, configs=mock_configs) + service = manager.mock_service + self.assertTrue(service) + self.assertEqual(service._configs, mock_configs) + self.assertEqual(service.start_func.call_count, 1) + + def test_register_do_not_start_service(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service', MockService, start_service=False) + service = manager.mock_service + self.assertTrue(service) + self.assertFalse(service.is_alive) + self.assertFalse(manager.is_any_alive) + self.assertEqual(service.start_func.call_count, 0) + + def test_register_not_a_class(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + with self.assertRaisesRegex(service_manager.Error, + '.* is not a class!'): + manager.register('mock_service', base_service) + + def test_register_wrong_subclass_type(self): + class MyClass(object): + pass + + manager = service_manager.ServiceManager(mock.MagicMock()) + with self.assertRaisesRegex(service_manager.Error, + '.* is not a subclass of BaseService!'): + manager.register('mock_service', MyClass) + + def test_register_dup_alias(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service', MockService) + msg = '.* A service is already registered with alias "mock_service"' + with self.assertRaisesRegex(service_manager.Error, msg): + manager.register('mock_service', MockService) + + def test_for_each(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + service1.ha = mock.MagicMock() + service2.ha = mock.MagicMock() + manager.for_each(lambda service: service.ha()) + service1.ha.assert_called_with() + service2.ha.assert_called_with() + + def test_for_each_modify_during_iteration(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + service1.ha = mock.MagicMock() + service2.ha = mock.MagicMock() + manager.for_each(lambda service: manager._service_objects.pop(service. + alias)) + self.assertFalse(manager._service_objects) + + def test_for_each_one_fail(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + service1.ha = mock.MagicMock() + service1.ha.side_effect = Exception('Failure in service1.') + service2.ha = mock.MagicMock() + manager.for_each(lambda service: service.ha()) + service1.ha.assert_called_with() + service2.ha.assert_called_with() + self.assert_recorded_one_error('Failure in service1.') + + def test_create_output_excerpts_all(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + manager.register('mock_service3', MockService) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + service3 = manager.mock_service3 + service1.create_output_excerpts = mock.MagicMock() + service2.create_output_excerpts = mock.MagicMock() + service3.create_output_excerpts = mock.MagicMock() + service1.create_output_excerpts.return_value = ['path/to/1.txt'] + service2.create_output_excerpts.return_value = [ + 'path/to/2-1.txt', 'path/to/2-2.txt' + ] + service3.create_output_excerpts.return_value = [] + mock_test_info = mock.MagicMock(output_path='path/to') + result = manager.create_output_excerpts_all(mock_test_info) + self.assertEqual(result['mock_service1'], ['path/to/1.txt']) + self.assertEqual(result['mock_service2'], + ['path/to/2-1.txt', 'path/to/2-2.txt']) + self.assertEqual(result['mock_service3'], []) + + def test_unregister(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service', MockService) + service = manager.mock_service + manager.unregister('mock_service') + self.assertFalse(manager.is_any_alive) + self.assertFalse(service.is_alive) + self.assertEqual(service.stop_func.call_count, 1) + + def test_unregister_not_started_service(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service', MockService, start_service=False) + service = manager.mock_service + manager.unregister('mock_service') + self.assertFalse(manager.is_any_alive) + self.assertFalse(service.is_alive) + self.assertEqual(service.stop_func.call_count, 0) + + def test_unregister_non_existent(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + with self.assertRaisesRegex( + service_manager.Error, + '.* No service is registered with alias "mock_service"'): + manager.unregister('mock_service') + + def test_unregister_handle_error_from_stop(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service', MockService) + service = manager.mock_service + service.stop_func.side_effect = Exception('Something failed in stop.') + manager.unregister('mock_service') + self.assert_recorded_one_error( + 'Failed to stop service instance "mock_service".') + + def test_unregister_all(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + manager.unregister_all() + self.assertFalse(manager.is_any_alive) + self.assertFalse(service1.is_alive) + self.assertFalse(service2.is_alive) + self.assertEqual(service1.stop_func.call_count, 1) + self.assertEqual(service2.stop_func.call_count, 1) + + def test_unregister_all_with_some_failed(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service1.stop_func.side_effect = Exception('Something failed in stop.') + service2 = manager.mock_service2 + manager.unregister_all() + self.assertFalse(manager.is_any_alive) + self.assertTrue(service1.is_alive) + self.assertFalse(service2.is_alive) + self.assert_recorded_one_error( + 'Failed to stop service instance "mock_service1".') + + def test_start_all(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService, start_service=False) + manager.register('mock_service2', MockService, start_service=False) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + mock_call_tracker = mock.Mock() + mock_call_tracker.start1 = service1.start_func + mock_call_tracker.start2 = service2.start_func + manager.start_all() + self.assertTrue(service1.is_alive) + self.assertTrue(service2.is_alive) + self.assertEqual(service1.start_func.call_count, 1) + self.assertEqual(service2.start_func.call_count, 1) + self.assertEqual(mock_call_tracker.mock_calls, + [mock.call.start1(None), + mock.call.start2(None)]) + + def test_start_all_with_already_started_services(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService, start_service=False) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + manager.start_all() + manager.start_all() + self.assertTrue(service1.is_alive) + self.assertTrue(service2.is_alive) + self.assertEqual(service1.start_func.call_count, 1) + self.assertEqual(service2.start_func.call_count, 1) + + def test_start_all_with_some_failed(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService, start_service=False) + manager.register('mock_service2', MockService, start_service=False) + service1 = manager.mock_service1 + service1.start_func.side_effect = Exception( + 'Something failed in start.') + service2 = manager.mock_service2 + manager.start_all() + self.assertFalse(service1.is_alive) + self.assertTrue(service2.is_alive) + self.assert_recorded_one_error( + 'Failed to start service "mock_service1"') + + def test_stop_all(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + mock_call_tracker = mock.Mock() + mock_call_tracker.stop1 = service1.stop_func + mock_call_tracker.stop2 = service2.stop_func + manager.stop_all() + self.assertFalse(service1.is_alive) + self.assertFalse(service2.is_alive) + self.assertEqual( + mock_call_tracker.mock_calls, + [mock.call.stop2(), mock.call.stop1()]) + self.assertEqual(service1.start_func.call_count, 1) + self.assertEqual(service2.start_func.call_count, 1) + self.assertEqual(service1.stop_func.call_count, 1) + self.assertEqual(service2.stop_func.call_count, 1) + + def test_stop_all_with_already_stopped_services(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService, start_service=False) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + manager.stop_all() + manager.stop_all() + self.assertFalse(service1.is_alive) + self.assertFalse(service2.is_alive) + self.assertEqual(service1.start_func.call_count, 1) + self.assertEqual(service2.start_func.call_count, 0) + self.assertEqual(service1.stop_func.call_count, 1) + self.assertEqual(service2.stop_func.call_count, 0) + + def test_stop_all_with_some_failed(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service1.stop_func.side_effect = Exception( + 'Something failed in start.') + service2 = manager.mock_service2 + manager.stop_all() + self.assertTrue(service1.is_alive) + self.assertFalse(service2.is_alive) + self.assert_recorded_one_error( + 'Failed to stop service "mock_service1"') + + def test_start_all_and_stop_all_serveral_times(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService, start_service=False) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + manager.stop_all() + manager.start_all() + manager.stop_all() + manager.start_all() + manager.stop_all() + manager.start_all() + self.assertTrue(service1.is_alive) + self.assertTrue(service2.is_alive) + self.assertEqual(service1.start_func.call_count, 4) + self.assertEqual(service2.start_func.call_count, 3) + self.assertEqual(service1.stop_func.call_count, 3) + self.assertEqual(service2.stop_func.call_count, 2) + + def test_pause_all(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + mock_call_tracker = mock.Mock() + mock_call_tracker.pause1 = service1.pause_func + mock_call_tracker.pause2 = service2.pause_func + manager.pause_all() + self.assertEqual( + mock_call_tracker.mock_calls, + [mock.call.pause2(), mock.call.pause1()]) + self.assertEqual(service1.pause_func.call_count, 1) + self.assertEqual(service2.pause_func.call_count, 1) + self.assertEqual(service1.resume_func.call_count, 0) + self.assertEqual(service2.resume_func.call_count, 0) + + def test_pause_all_with_some_failed(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service1.pause_func.side_effect = Exception( + 'Something failed in pause.') + service2 = manager.mock_service2 + manager.pause_all() + self.assertEqual(service1.pause_func.call_count, 1) + self.assertEqual(service2.pause_func.call_count, 1) + self.assertEqual(service1.resume_func.call_count, 0) + self.assertEqual(service2.resume_func.call_count, 0) + self.assert_recorded_one_error( + 'Failed to pause service "mock_service1".') + + def test_resume_all(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service2 = manager.mock_service2 + mock_call_tracker = mock.Mock() + mock_call_tracker.resume1 = service1.resume_func + mock_call_tracker.resume2 = service2.resume_func + manager.pause_all() + manager.resume_all() + self.assertEqual( + mock_call_tracker.mock_calls, + [mock.call.resume1(), mock.call.resume2()]) + self.assertEqual(service1.pause_func.call_count, 1) + self.assertEqual(service2.pause_func.call_count, 1) + self.assertEqual(service1.resume_func.call_count, 1) + self.assertEqual(service2.resume_func.call_count, 1) + + def test_resume_all_with_some_failed(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + service1 = manager.mock_service1 + service1.resume_func.side_effect = Exception( + 'Something failed in resume.') + service2 = manager.mock_service2 + manager.pause_all() + manager.resume_all() + self.assertEqual(service1.pause_func.call_count, 1) + self.assertEqual(service2.pause_func.call_count, 1) + self.assertEqual(service1.resume_func.call_count, 1) + self.assertEqual(service2.resume_func.call_count, 1) + self.assert_recorded_one_error( + 'Failed to resume service "mock_service1".') + + def test_list_live_services(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService, start_service=False) + manager.register('mock_service2', MockService) + aliases = manager.list_live_services() + self.assertEqual(aliases, ['mock_service2']) + manager.stop_all() + aliases = manager.list_live_services() + self.assertEqual(aliases, []) + + def test_start_services(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService, start_service=False) + manager.register('mock_service2', MockService, start_service=False) + manager.start_services(['mock_service2']) + aliases = manager.list_live_services() + self.assertEqual(aliases, ['mock_service2']) + + def test_start_services_non_existent(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + msg = ('.* No service is registered under the name "mock_service", ' + 'cannot start.') + with self.assertRaisesRegex(service_manager.Error, msg): + manager.start_services(['mock_service']) + + def test_resume_services(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + manager.register('mock_service1', MockService) + manager.register('mock_service2', MockService) + manager.pause_all() + aliases = manager.list_live_services() + self.assertEqual(aliases, []) + manager.resume_services(['mock_service2']) + aliases = manager.list_live_services() + self.assertEqual(aliases, ['mock_service2']) + + def test_resume_services_non_existent(self): + manager = service_manager.ServiceManager(mock.MagicMock()) + msg = ('.* No service is registered under the name "mock_service", ' + 'cannot resume.') + with self.assertRaisesRegex(service_manager.Error, msg): + manager.resume_services(['mock_service']) if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/services/base_service_test.py b/tests/mobly/controllers/android_device_lib/services/base_service_test.py index e97848d..b8474d2 100755 --- a/tests/mobly/controllers/android_device_lib/services/base_service_test.py +++ b/tests/mobly/controllers/android_device_lib/services/base_service_test.py @@ -18,14 +18,14 @@ from mobly.controllers.android_device_lib.services import base_service class BaseServiceTest(unittest.TestCase): - def setUp(self): - self.mock_device = mock.MagicMock() - self.service = base_service.BaseService(self.mock_device) + def setUp(self): + self.mock_device = mock.MagicMock() + self.service = base_service.BaseService(self.mock_device) - def test_alias(self): - self.service.alias = 'SomeService' - self.assertEqual(self.service.alias, 'SomeService') + def test_alias(self): + self.service.alias = 'SomeService' + self.assertEqual(self.service.alias, 'SomeService') if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/services/logcat_test.py b/tests/mobly/controllers/android_device_lib/services/logcat_test.py index 4401c9a..1a59b77 100755 --- a/tests/mobly/controllers/android_device_lib/services/logcat_test.py +++ b/tests/mobly/controllers/android_device_lib/services/logcat_test.py @@ -31,24 +31,24 @@ from tests.lib import mock_android_device # The expected result of the cat adb operation. MOCK_ADB_LOGCAT_CAT_RESULT = [ - '02-29 14:02:21.456 4454 Something\n', - '02-29 14:02:21.789 4454 Something again\n' + '02-29 14:02:21.456 4454 Something\n', + '02-29 14:02:21.789 4454 Something again\n' ] # A mocked piece of adb logcat output. MOCK_ADB_LOGCAT = (u'02-29 14:02:19.123 4454 Nothing\n' - u'%s' - u'02-29 14:02:22.123 4454 Something again and again\n' - ) % u''.join(MOCK_ADB_LOGCAT_CAT_RESULT) + u'%s' + u'02-29 14:02:22.123 4454 Something again and again\n' + ) % u''.join(MOCK_ADB_LOGCAT_CAT_RESULT) # The expected result of the cat adb operation. MOCK_ADB_UNICODE_LOGCAT_CAT_RESULT = [ - '02-29 14:02:21.456 4454 Something \u901a\n', - '02-29 14:02:21.789 4454 Something again\n' + '02-29 14:02:21.456 4454 Something \u901a\n', + '02-29 14:02:21.789 4454 Something again\n' ] # A mocked piece of adb logcat output. MOCK_ADB_UNICODE_LOGCAT = ( - u'02-29 14:02:19.123 4454 Nothing\n' - u'%s' - u'02-29 14:02:22.123 4454 Something again and again\n' + u'02-29 14:02:19.123 4454 Nothing\n' + u'%s' + u'02-29 14:02:22.123 4454 Something again and again\n' ) % u''.join(MOCK_ADB_UNICODE_LOGCAT_CAT_RESULT) # Mock start and end time of the adb cat. @@ -57,456 +57,456 @@ MOCK_ADB_LOGCAT_END_TIME = '02-29 14:02:22.000' # Mock AdbError for missing logpersist scripts MOCK_LOGPERSIST_STOP_MISSING_ADB_ERROR = adb.AdbError( - 'logpersist.stop --clear', b'', - '/system/bin/sh: logpersist.stop: not found', 0) + 'logpersist.stop --clear', b'', + '/system/bin/sh: logpersist.stop: not found', 0) MOCK_LOGPERSIST_START_MISSING_ADB_ERROR = adb.AdbError( - 'logpersist.start --clear', b'', - b'/system/bin/sh: logpersist.stop: not found', 0) + 'logpersist.start --clear', b'', + b'/system/bin/sh: logpersist.stop: not found', 0) class LogcatTest(unittest.TestCase): - """Tests for Logcat service and its integration with AndroidDevice.""" - - def setUp(self): - # Set log_path to logging since mobly logger setup is not called. - if not hasattr(logging, 'log_path'): - setattr(logging, 'log_path', '/tmp/logs') - # Creates a temp dir to be used by tests in this test class. - self.tmp_dir = tempfile.mkdtemp() - - def tearDown(self): - """Removes the temp dir. - """ - shutil.rmtree(self.tmp_dir) - - def AssertFileContains(self, content, file_path): - with open(file_path, 'r') as f: - output = f.read() - self.assertIn(content, output) - - def AssertFileDoesNotContain(self, content, file_path): - with open(file_path, 'r') as f: - output = f.read() - self.assertNotIn(content, output) - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock_android_device.MockAdbProxy('1')) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - @mock.patch('mobly.utils.create_dir') - @mock.patch('mobly.utils.start_standing_subprocess', - return_value='process') - @mock.patch('mobly.utils.stop_standing_subprocess') - @mock.patch.object(logcat.Logcat, '_open_logcat_file') - @mock.patch('mobly.logger.get_log_file_timestamp') - def test_start_and_stop(self, get_timestamp_mock, open_logcat_mock, - stop_proc_mock, start_proc_mock, create_dir_mock, - FastbootProxy, MockAdbProxy): - """Verifies the steps of collecting adb logcat on an AndroidDevice - object, including various function calls and the expected behaviors of - the calls. - """ - mock_serial = '1' - get_timestamp_mock.return_value = '123' - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad) - logcat_service.start() - # Verify start did the correct operations. - self.assertTrue(logcat_service._adb_logcat_process) - expected_log_path = os.path.join( - logging.log_path, 'AndroidDevice%s' % ad.serial, - 'logcat,%s,fakemodel,123.txt' % ad.serial) - create_dir_mock.assert_called_with(os.path.dirname(expected_log_path)) - adb_cmd = ' "adb" -s %s logcat -v threadtime -T 1 >> %s' - start_proc_mock.assert_called_with( - adb_cmd % (ad.serial, '"%s" ' % expected_log_path), shell=True) - self.assertEqual(logcat_service.adb_logcat_file_path, - expected_log_path) - expected_msg = ( - 'Logcat thread is already running, cannot start another' - ' one.') - # Expect error if start is called back to back. - with self.assertRaisesRegex(logcat.Error, expected_msg): - logcat_service.start() - # Verify stop did the correct operations. - logcat_service.stop() - stop_proc_mock.assert_called_with('process') - self.assertIsNone(logcat_service._adb_logcat_process) - self.assertEqual(logcat_service.adb_logcat_file_path, - expected_log_path) - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock_android_device.MockAdbProxy('1')) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - @mock.patch('mobly.utils.create_dir') - @mock.patch('mobly.utils.start_standing_subprocess', - return_value='process') - @mock.patch('mobly.utils.stop_standing_subprocess') - @mock.patch.object(logcat.Logcat, '_open_logcat_file') - def test_update_config(self, open_logcat_mock, stop_proc_mock, - start_proc_mock, create_dir_mock, FastbootProxy, + """Tests for Logcat service and its integration with AndroidDevice.""" + + def setUp(self): + # Set log_path to logging since mobly logger setup is not called. + if not hasattr(logging, 'log_path'): + setattr(logging, 'log_path', '/tmp/logs') + # Creates a temp dir to be used by tests in this test class. + self.tmp_dir = tempfile.mkdtemp() + + def tearDown(self): + """Removes the temp dir. + """ + shutil.rmtree(self.tmp_dir) + + def AssertFileContains(self, content, file_path): + with open(file_path, 'r') as f: + output = f.read() + self.assertIn(content, output) + + def AssertFileDoesNotContain(self, content, file_path): + with open(file_path, 'r') as f: + output = f.read() + self.assertNotIn(content, output) + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', + return_value=mock_android_device.MockAdbProxy('1')) + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + @mock.patch('mobly.utils.create_dir') + @mock.patch('mobly.utils.start_standing_subprocess', + return_value='process') + @mock.patch('mobly.utils.stop_standing_subprocess') + @mock.patch.object(logcat.Logcat, '_open_logcat_file') + @mock.patch('mobly.logger.get_log_file_timestamp') + def test_start_and_stop(self, get_timestamp_mock, open_logcat_mock, + stop_proc_mock, start_proc_mock, create_dir_mock, + FastbootProxy, MockAdbProxy): + """Verifies the steps of collecting adb logcat on an AndroidDevice + object, including various function calls and the expected behaviors of + the calls. + """ + mock_serial = '1' + get_timestamp_mock.return_value = '123' + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad) + logcat_service.start() + # Verify start did the correct operations. + self.assertTrue(logcat_service._adb_logcat_process) + expected_log_path = os.path.join( + logging.log_path, 'AndroidDevice%s' % ad.serial, + 'logcat,%s,fakemodel,123.txt' % ad.serial) + create_dir_mock.assert_called_with(os.path.dirname(expected_log_path)) + adb_cmd = ' "adb" -s %s logcat -v threadtime -T 1 >> %s' + start_proc_mock.assert_called_with( + adb_cmd % (ad.serial, '"%s" ' % expected_log_path), shell=True) + self.assertEqual(logcat_service.adb_logcat_file_path, + expected_log_path) + expected_msg = ( + 'Logcat thread is already running, cannot start another' + ' one.') + # Expect error if start is called back to back. + with self.assertRaisesRegex(logcat.Error, expected_msg): + logcat_service.start() + # Verify stop did the correct operations. + logcat_service.stop() + stop_proc_mock.assert_called_with('process') + self.assertIsNone(logcat_service._adb_logcat_process) + self.assertEqual(logcat_service.adb_logcat_file_path, + expected_log_path) + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', + return_value=mock_android_device.MockAdbProxy('1')) + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + @mock.patch('mobly.utils.create_dir') + @mock.patch('mobly.utils.start_standing_subprocess', + return_value='process') + @mock.patch('mobly.utils.stop_standing_subprocess') + @mock.patch.object(logcat.Logcat, '_open_logcat_file') + def test_update_config(self, open_logcat_mock, stop_proc_mock, + start_proc_mock, create_dir_mock, FastbootProxy, + MockAdbProxy): + mock_serial = '1' + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad) + logcat_service.start() + logcat_service.stop() + new_log_params = '-a -b -c' + new_file_path = 'some/path/log.txt' + new_config = logcat.Config(logcat_params=new_log_params, + output_file_path=new_file_path) + logcat_service.update_config(new_config) + logcat_service.start() + self.assertTrue(logcat_service._adb_logcat_process) + create_dir_mock.assert_has_calls([mock.call('some/path')]) + expected_adb_cmd = (' "adb" -s 1 logcat -v threadtime -T 1 -a -b -c >> ' + '"some/path/log.txt" ') + start_proc_mock.assert_called_with(expected_adb_cmd, shell=True) + self.assertEqual(logcat_service.adb_logcat_file_path, + 'some/path/log.txt') + logcat_service.stop() + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', + return_value=mock_android_device.MockAdbProxy('1')) + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + @mock.patch('mobly.utils.create_dir') + @mock.patch('mobly.utils.start_standing_subprocess', + return_value='process') + @mock.patch('mobly.utils.stop_standing_subprocess') + @mock.patch.object(logcat.Logcat, '_open_logcat_file') + def test_update_config_while_running(self, open_logcat_mock, stop_proc_mock, + start_proc_mock, create_dir_mock, + FastbootProxy, MockAdbProxy): + mock_serial = '1' + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad) + logcat_service.start() + new_config = logcat.Config(logcat_params='-blah', + output_file_path='some/path/file.txt') + with self.assertRaisesRegex( + logcat.Error, + 'Logcat thread is already running, cannot start another one'): + logcat_service.update_config(new_config) + self.assertTrue(logcat_service.is_alive) + logcat_service.stop() + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', + return_value=mock_android_device.MockAdbProxy('1')) + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + @mock.patch('mobly.utils.create_dir') + @mock.patch('mobly.utils.start_standing_subprocess', + return_value='process') + @mock.patch('mobly.utils.stop_standing_subprocess') + @mock.patch.object(logcat.Logcat, '_open_logcat_file') + @mock.patch( + 'mobly.controllers.android_device_lib.services.logcat.Logcat.clear_adb_log', + return_value=mock_android_device.MockAdbProxy('1')) + def test_pause_and_resume(self, clear_adb_mock, open_logcat_mock, + stop_proc_mock, start_proc_mock, create_dir_mock, + FastbootProxy, MockAdbProxy): + mock_serial = '1' + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad, logcat.Config(clear_log=True)) + logcat_service.start() + clear_adb_mock.assert_called_once_with() + self.assertTrue(logcat_service.is_alive) + logcat_service.pause() + self.assertFalse(logcat_service.is_alive) + stop_proc_mock.assert_called_with('process') + self.assertIsNone(logcat_service._adb_logcat_process) + clear_adb_mock.reset_mock() + logcat_service.resume() + self.assertTrue(logcat_service.is_alive) + clear_adb_mock.assert_not_called() + logcat_service.stop() + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', + return_value=mock_android_device.MockAdbProxy('1')) + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + @mock.patch('mobly.utils.start_standing_subprocess', + return_value='process') + @mock.patch('mobly.utils.stop_standing_subprocess') + @mock.patch( + 'mobly.controllers.android_device_lib.services.logcat.Logcat.clear_adb_log', + return_value=mock_android_device.MockAdbProxy('1')) + def test_logcat_service_create_output_excerpts(self, clear_adb_mock, + stop_proc_mock, + start_proc_mock, + FastbootProxy, MockAdbProxy): - mock_serial = '1' - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad) - logcat_service.start() - logcat_service.stop() - new_log_params = '-a -b -c' - new_file_path = 'some/path/log.txt' - new_config = logcat.Config(logcat_params=new_log_params, - output_file_path=new_file_path) - logcat_service.update_config(new_config) - logcat_service.start() - self.assertTrue(logcat_service._adb_logcat_process) - create_dir_mock.assert_has_calls([mock.call('some/path')]) - expected_adb_cmd = (' "adb" -s 1 logcat -v threadtime -T 1 -a -b -c >> ' - '"some/path/log.txt" ') - start_proc_mock.assert_called_with(expected_adb_cmd, shell=True) - self.assertEqual(logcat_service.adb_logcat_file_path, - 'some/path/log.txt') - logcat_service.stop() - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock_android_device.MockAdbProxy('1')) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - @mock.patch('mobly.utils.create_dir') - @mock.patch('mobly.utils.start_standing_subprocess', - return_value='process') - @mock.patch('mobly.utils.stop_standing_subprocess') - @mock.patch.object(logcat.Logcat, '_open_logcat_file') - def test_update_config_while_running(self, open_logcat_mock, stop_proc_mock, - start_proc_mock, create_dir_mock, - FastbootProxy, MockAdbProxy): - mock_serial = '1' - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad) - logcat_service.start() - new_config = logcat.Config(logcat_params='-blah', - output_file_path='some/path/file.txt') - with self.assertRaisesRegex( - logcat.Error, - 'Logcat thread is already running, cannot start another one'): - logcat_service.update_config(new_config) - self.assertTrue(logcat_service.is_alive) - logcat_service.stop() - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock_android_device.MockAdbProxy('1')) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - @mock.patch('mobly.utils.create_dir') - @mock.patch('mobly.utils.start_standing_subprocess', - return_value='process') - @mock.patch('mobly.utils.stop_standing_subprocess') - @mock.patch.object(logcat.Logcat, '_open_logcat_file') - @mock.patch( - 'mobly.controllers.android_device_lib.services.logcat.Logcat.clear_adb_log', + mock_serial = '1' + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad) + logcat_service._start() + + def _write_logcat_file_and_assert_excerpts_exists(logcat_file_content, + test_begin_time, + test_name): + with open(logcat_service.adb_logcat_file_path, 'a') as f: + f.write(logcat_file_content) + test_output_dir = os.path.join(self.tmp_dir, test_name) + mock_record = mock.MagicMock() + mock_record.begin_time = test_begin_time + test_run_info = runtime_test_info.RuntimeTestInfo(test_name, + test_output_dir, + mock_record) + actual_path = logcat_service.create_output_excerpts(test_run_info)[0] + expected_path = os.path.join( + test_output_dir, '{test_name}-{test_begin_time}'.format( + test_name=test_name, test_begin_time=test_begin_time), + 'logcat,{mock_serial},fakemodel,{test_name}-{test_begin_time}.txt' + .format( + mock_serial=mock_serial, + test_name=test_name, + test_begin_time=test_begin_time)) + self.assertEqual(actual_path, expected_path) + self.assertTrue(os.path.exists(expected_path)) + return expected_path + + # Generate logs before the file pointer is created. + # This message will not be captured in the excerpt. + NOT_IN_EXCERPT = 'Not in excerpt.\n' + with open(logcat_service.adb_logcat_file_path, 'a') as f: + f.write(NOT_IN_EXCERPT) + # With the file pointer created, generate logs and make an excerpt. + logcat_service._open_logcat_file() + FILE_CONTENT = 'Some log.\n' + expected_path1 = _write_logcat_file_and_assert_excerpts_exists( + logcat_file_content=FILE_CONTENT, + test_begin_time=123, + test_name='test_foo', + ) + self.AssertFileContains(FILE_CONTENT, expected_path1) + self.AssertFileDoesNotContain(NOT_IN_EXCERPT, expected_path1) + # Generate some new logs and do another excerpt. + FILE_CONTENT = 'Some more logs!!!\n' + expected_path2 = _write_logcat_file_and_assert_excerpts_exists( + logcat_file_content=FILE_CONTENT, + test_begin_time=456, + test_name='test_bar', + ) + self.AssertFileContains(FILE_CONTENT, expected_path2) + self.AssertFileDoesNotContain(FILE_CONTENT, expected_path1) + # Simulate devices accidentally go offline, logcat service stopped. + logcat_service.stop() + FILE_CONTENT = 'Whatever logs\n' + expected_path3 = _write_logcat_file_and_assert_excerpts_exists( + logcat_file_content=FILE_CONTENT, + test_begin_time=789, + test_name='test_offline', + ) + self.assertEqual(os.stat(expected_path3).st_size, 0) + + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', return_value=mock_android_device.MockAdbProxy('1')) - def test_pause_and_resume(self, clear_adb_mock, open_logcat_mock, - stop_proc_mock, start_proc_mock, create_dir_mock, - FastbootProxy, MockAdbProxy): - mock_serial = '1' - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad, logcat.Config(clear_log=True)) - logcat_service.start() - clear_adb_mock.assert_called_once_with() - self.assertTrue(logcat_service.is_alive) - logcat_service.pause() - self.assertFalse(logcat_service.is_alive) - stop_proc_mock.assert_called_with('process') - self.assertIsNone(logcat_service._adb_logcat_process) - clear_adb_mock.reset_mock() - logcat_service.resume() - self.assertTrue(logcat_service.is_alive) - clear_adb_mock.assert_not_called() - logcat_service.stop() - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock_android_device.MockAdbProxy('1')) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - @mock.patch('mobly.utils.start_standing_subprocess', - return_value='process') - @mock.patch('mobly.utils.stop_standing_subprocess') - @mock.patch( - 'mobly.controllers.android_device_lib.services.logcat.Logcat.clear_adb_log', + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + @mock.patch('mobly.utils.create_dir') + @mock.patch('mobly.utils.start_standing_subprocess', + return_value='process') + @mock.patch('mobly.utils.stop_standing_subprocess') + @mock.patch.object(logcat.Logcat, '_open_logcat_file') + @mock.patch('mobly.logger.get_log_file_timestamp') + def test_take_logcat_with_extra_params(self, get_timestamp_mock, + open_logcat_mock, stop_proc_mock, + start_proc_mock, create_dir_mock, + FastbootProxy, MockAdbProxy): + """Verifies the steps of collecting adb logcat on an AndroidDevice + object, including various function calls and the expected behaviors of + the calls. + """ + mock_serial = '1' + get_timestamp_mock.return_value = '123' + ad = android_device.AndroidDevice(serial=mock_serial) + configs = logcat.Config() + configs.logcat_params = '-b radio' + logcat_service = logcat.Logcat(ad, configs) + logcat_service.start() + # Verify start did the correct operations. + self.assertTrue(logcat_service._adb_logcat_process) + expected_log_path = os.path.join( + logging.log_path, 'AndroidDevice%s' % ad.serial, + 'logcat,%s,fakemodel,123.txt' % ad.serial) + create_dir_mock.assert_called_with(os.path.dirname(expected_log_path)) + adb_cmd = ' "adb" -s %s logcat -v threadtime -T 1 -b radio >> %s' + start_proc_mock.assert_called_with( + adb_cmd % (ad.serial, '"%s" ' % expected_log_path), shell=True) + self.assertEqual(logcat_service.adb_logcat_file_path, + expected_log_path) + logcat_service.stop() + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', return_value=mock_android_device.MockAdbProxy('1')) - def test_logcat_service_create_output_excerpts(self, clear_adb_mock, - stop_proc_mock, - start_proc_mock, - FastbootProxy, - MockAdbProxy): - mock_serial = '1' - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad) - logcat_service._start() - - def _write_logcat_file_and_assert_excerpts_exists(logcat_file_content, - test_begin_time, - test_name): - with open(logcat_service.adb_logcat_file_path, 'a') as f: - f.write(logcat_file_content) - test_output_dir = os.path.join(self.tmp_dir, test_name) - mock_record = mock.MagicMock() - mock_record.begin_time = test_begin_time - test_run_info = runtime_test_info.RuntimeTestInfo(test_name, - test_output_dir, - mock_record) - actual_path = logcat_service.create_output_excerpts(test_run_info)[0] - expected_path = os.path.join( - test_output_dir, '{test_name}-{test_begin_time}'.format( - test_name=test_name, test_begin_time=test_begin_time), - 'logcat,{mock_serial},fakemodel,{test_name}-{test_begin_time}.txt' - .format( - mock_serial=mock_serial, - test_name=test_name, - test_begin_time=test_begin_time)) - self.assertEqual(actual_path, expected_path) - self.assertTrue(os.path.exists(expected_path)) - return expected_path - - # Generate logs before the file pointer is created. - # This message will not be captured in the excerpt. - NOT_IN_EXCERPT = 'Not in excerpt.\n' - with open(logcat_service.adb_logcat_file_path, 'a') as f: - f.write(NOT_IN_EXCERPT) - # With the file pointer created, generate logs and make an excerpt. - logcat_service._open_logcat_file() - FILE_CONTENT = 'Some log.\n' - expected_path1 = _write_logcat_file_and_assert_excerpts_exists( - logcat_file_content=FILE_CONTENT, - test_begin_time=123, - test_name='test_foo', - ) - self.AssertFileContains(FILE_CONTENT, expected_path1) - self.AssertFileDoesNotContain(NOT_IN_EXCERPT, expected_path1) - # Generate some new logs and do another excerpt. - FILE_CONTENT = 'Some more logs!!!\n' - expected_path2 = _write_logcat_file_and_assert_excerpts_exists( - logcat_file_content=FILE_CONTENT, - test_begin_time=456, - test_name='test_bar', - ) - self.AssertFileContains(FILE_CONTENT, expected_path2) - self.AssertFileDoesNotContain(FILE_CONTENT, expected_path1) - # Simulate devices accidentally go offline, logcat service stopped. - logcat_service.stop() - FILE_CONTENT = 'Whatever logs\n' - expected_path3 = _write_logcat_file_and_assert_excerpts_exists( - logcat_file_content=FILE_CONTENT, - test_begin_time=789, - test_name='test_offline', - ) - self.assertEqual(os.stat(expected_path3).st_size, 0) - - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock_android_device.MockAdbProxy('1')) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - @mock.patch('mobly.utils.create_dir') - @mock.patch('mobly.utils.start_standing_subprocess', - return_value='process') - @mock.patch('mobly.utils.stop_standing_subprocess') - @mock.patch.object(logcat.Logcat, '_open_logcat_file') - @mock.patch('mobly.logger.get_log_file_timestamp') - def test_take_logcat_with_extra_params(self, get_timestamp_mock, - open_logcat_mock, stop_proc_mock, - start_proc_mock, create_dir_mock, - FastbootProxy, MockAdbProxy): - """Verifies the steps of collecting adb logcat on an AndroidDevice - object, including various function calls and the expected behaviors of - the calls. - """ - mock_serial = '1' - get_timestamp_mock.return_value = '123' - ad = android_device.AndroidDevice(serial=mock_serial) - configs = logcat.Config() - configs.logcat_params = '-b radio' - logcat_service = logcat.Logcat(ad, configs) - logcat_service.start() - # Verify start did the correct operations. - self.assertTrue(logcat_service._adb_logcat_process) - expected_log_path = os.path.join( - logging.log_path, 'AndroidDevice%s' % ad.serial, - 'logcat,%s,fakemodel,123.txt' % ad.serial) - create_dir_mock.assert_called_with(os.path.dirname(expected_log_path)) - adb_cmd = ' "adb" -s %s logcat -v threadtime -T 1 -b radio >> %s' - start_proc_mock.assert_called_with( - adb_cmd % (ad.serial, '"%s" ' % expected_log_path), shell=True) - self.assertEqual(logcat_service.adb_logcat_file_path, - expected_log_path) - logcat_service.stop() - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock_android_device.MockAdbProxy('1')) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - def test_instantiation(self, MockFastboot, MockAdbProxy): - """Verifies the AndroidDevice object's basic attributes are correctly - set after instantiation. - """ - mock_serial = 1 - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad) - self.assertIsNone(logcat_service._adb_logcat_process) - self.assertIsNone(logcat_service.adb_logcat_file_path) - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock.MagicMock()) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - def test__enable_logpersist_with_logpersist(self, MockFastboot, - MockAdbProxy): - mock_serial = '1' - mock_adb_proxy = MockAdbProxy.return_value - mock_adb_proxy.getprops.return_value = { - 'ro.build.id': 'AB42', - 'ro.build.type': 'userdebug', - 'ro.debuggable': '1', - } - mock_adb_proxy.has_shell_command.side_effect = lambda command: { - 'logpersist.start': True, - 'logpersist.stop': True, - }[command] - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad) - logcat_service._enable_logpersist() - mock_adb_proxy.shell.assert_has_calls([ - mock.call('logpersist.stop --clear'), - mock.call('logpersist.start'), - ]) - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock.MagicMock()) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - def test__enable_logpersist_with_user_build_device(self, MockFastboot, - MockAdbProxy): - mock_serial = '1' - mock_adb_proxy = MockAdbProxy.return_value - mock_adb_proxy.getprops.return_value = { - 'ro.build.id': 'AB42', - 'ro.build.type': 'user', - 'ro.debuggable': '0', - } - mock_adb_proxy.has_shell_command.side_effect = lambda command: { - 'logpersist.start': True, - 'logpersist.stop': True, - }[command] - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad) - logcat_service._enable_logpersist() - mock_adb_proxy.shell.assert_not_called() - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock.MagicMock()) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - def test__enable_logpersist_with_missing_all_logpersist( - self, MockFastboot, MockAdbProxy): - def adb_shell_helper(command): - if command == 'logpersist.start': - raise MOCK_LOGPERSIST_START_MISSING_ADB_ERROR - elif command == 'logpersist.stop --clear': - raise MOCK_LOGPERSIST_STOP_MISSING_ADB_ERROR - else: - return b'' - - mock_serial = '1' - mock_adb_proxy = MockAdbProxy.return_value - mock_adb_proxy.getprops.return_value = { - 'ro.build.id': 'AB42', - 'ro.build.type': 'userdebug', - 'ro.debuggable': '1', - } - mock_adb_proxy.has_shell_command.side_effect = lambda command: { - 'logpersist.start': False, - 'logpersist.stop': False, - }[command] - mock_adb_proxy.shell.side_effect = adb_shell_helper - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad) - logcat_service._enable_logpersist() - mock_adb_proxy.shell.assert_not_called() - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock.MagicMock()) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - def test__enable_logpersist_with_missing_logpersist_stop( - self, MockFastboot, MockAdbProxy): - def adb_shell_helper(command): - if command == 'logpersist.stop --clear': - raise MOCK_LOGPERSIST_STOP_MISSING_ADB_ERROR - else: - return b'' - - mock_serial = '1' - mock_adb_proxy = MockAdbProxy.return_value - mock_adb_proxy.getprops.return_value = { - 'ro.build.id': 'AB42', - 'ro.build.type': 'userdebug', - 'ro.debuggable': '1', - } - mock_adb_proxy.has_shell_command.side_effect = lambda command: { - 'logpersist.start': True, - 'logpersist.stop': False, - }[command] - mock_adb_proxy.shell.side_effect = adb_shell_helper - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad) - logcat_service._enable_logpersist() - mock_adb_proxy.shell.assert_has_calls([ - mock.call('logpersist.stop --clear'), - ]) - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', - return_value=mock.MagicMock()) - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - def test__enable_logpersist_with_missing_logpersist_start( - self, MockFastboot, MockAdbProxy): - def adb_shell_helper(command): - if command == 'logpersist.start': - raise MOCK_LOGPERSIST_START_MISSING_ADB_ERROR - else: - return b'' - - mock_serial = '1' - mock_adb_proxy = MockAdbProxy.return_value - mock_adb_proxy.getprops.return_value = { - 'ro.build.id': 'AB42', - 'ro.build.type': 'userdebug', - 'ro.debuggable': '1', - } - mock_adb_proxy.has_shell_command.side_effect = lambda command: { - 'logpersist.start': False, - 'logpersist.stop': True, - }[command] - mock_adb_proxy.shell.side_effect = adb_shell_helper - ad = android_device.AndroidDevice(serial=mock_serial) - logcat_service = logcat.Logcat(ad) - logcat_service._enable_logpersist() - mock_adb_proxy.shell.assert_not_called() - - @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy') - @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', - return_value=mock_android_device.MockFastbootProxy('1')) - def test_clear_adb_log(self, MockFastboot, MockAdbProxy): - mock_serial = '1' - ad = android_device.AndroidDevice(serial=mock_serial) - ad.adb.logcat = mock.MagicMock() - ad.adb.logcat.side_effect = adb.AdbError( - cmd='cmd', - stdout=b'', - stderr=b'failed to clear "main" log', - ret_code=1) - logcat_service = logcat.Logcat(ad) - logcat_service.clear_adb_log() + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + def test_instantiation(self, MockFastboot, MockAdbProxy): + """Verifies the AndroidDevice object's basic attributes are correctly + set after instantiation. + """ + mock_serial = 1 + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad) + self.assertIsNone(logcat_service._adb_logcat_process) + self.assertIsNone(logcat_service.adb_logcat_file_path) + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', + return_value=mock.MagicMock()) + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + def test__enable_logpersist_with_logpersist(self, MockFastboot, + MockAdbProxy): + mock_serial = '1' + mock_adb_proxy = MockAdbProxy.return_value + mock_adb_proxy.getprops.return_value = { + 'ro.build.id': 'AB42', + 'ro.build.type': 'userdebug', + 'ro.debuggable': '1', + } + mock_adb_proxy.has_shell_command.side_effect = lambda command: { + 'logpersist.start': True, + 'logpersist.stop': True, + }[command] + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad) + logcat_service._enable_logpersist() + mock_adb_proxy.shell.assert_has_calls([ + mock.call('logpersist.stop --clear'), + mock.call('logpersist.start'), + ]) + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', + return_value=mock.MagicMock()) + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + def test__enable_logpersist_with_user_build_device(self, MockFastboot, + MockAdbProxy): + mock_serial = '1' + mock_adb_proxy = MockAdbProxy.return_value + mock_adb_proxy.getprops.return_value = { + 'ro.build.id': 'AB42', + 'ro.build.type': 'user', + 'ro.debuggable': '0', + } + mock_adb_proxy.has_shell_command.side_effect = lambda command: { + 'logpersist.start': True, + 'logpersist.stop': True, + }[command] + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad) + logcat_service._enable_logpersist() + mock_adb_proxy.shell.assert_not_called() + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', + return_value=mock.MagicMock()) + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + def test__enable_logpersist_with_missing_all_logpersist( + self, MockFastboot, MockAdbProxy): + def adb_shell_helper(command): + if command == 'logpersist.start': + raise MOCK_LOGPERSIST_START_MISSING_ADB_ERROR + elif command == 'logpersist.stop --clear': + raise MOCK_LOGPERSIST_STOP_MISSING_ADB_ERROR + else: + return b'' + + mock_serial = '1' + mock_adb_proxy = MockAdbProxy.return_value + mock_adb_proxy.getprops.return_value = { + 'ro.build.id': 'AB42', + 'ro.build.type': 'userdebug', + 'ro.debuggable': '1', + } + mock_adb_proxy.has_shell_command.side_effect = lambda command: { + 'logpersist.start': False, + 'logpersist.stop': False, + }[command] + mock_adb_proxy.shell.side_effect = adb_shell_helper + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad) + logcat_service._enable_logpersist() + mock_adb_proxy.shell.assert_not_called() + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', + return_value=mock.MagicMock()) + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + def test__enable_logpersist_with_missing_logpersist_stop( + self, MockFastboot, MockAdbProxy): + def adb_shell_helper(command): + if command == 'logpersist.stop --clear': + raise MOCK_LOGPERSIST_STOP_MISSING_ADB_ERROR + else: + return b'' + + mock_serial = '1' + mock_adb_proxy = MockAdbProxy.return_value + mock_adb_proxy.getprops.return_value = { + 'ro.build.id': 'AB42', + 'ro.build.type': 'userdebug', + 'ro.debuggable': '1', + } + mock_adb_proxy.has_shell_command.side_effect = lambda command: { + 'logpersist.start': True, + 'logpersist.stop': False, + }[command] + mock_adb_proxy.shell.side_effect = adb_shell_helper + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad) + logcat_service._enable_logpersist() + mock_adb_proxy.shell.assert_has_calls([ + mock.call('logpersist.stop --clear'), + ]) + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy', + return_value=mock.MagicMock()) + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + def test__enable_logpersist_with_missing_logpersist_start( + self, MockFastboot, MockAdbProxy): + def adb_shell_helper(command): + if command == 'logpersist.start': + raise MOCK_LOGPERSIST_START_MISSING_ADB_ERROR + else: + return b'' + + mock_serial = '1' + mock_adb_proxy = MockAdbProxy.return_value + mock_adb_proxy.getprops.return_value = { + 'ro.build.id': 'AB42', + 'ro.build.type': 'userdebug', + 'ro.debuggable': '1', + } + mock_adb_proxy.has_shell_command.side_effect = lambda command: { + 'logpersist.start': False, + 'logpersist.stop': True, + }[command] + mock_adb_proxy.shell.side_effect = adb_shell_helper + ad = android_device.AndroidDevice(serial=mock_serial) + logcat_service = logcat.Logcat(ad) + logcat_service._enable_logpersist() + mock_adb_proxy.shell.assert_not_called() + + @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy') + @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy', + return_value=mock_android_device.MockFastbootProxy('1')) + def test_clear_adb_log(self, MockFastboot, MockAdbProxy): + mock_serial = '1' + ad = android_device.AndroidDevice(serial=mock_serial) + ad.adb.logcat = mock.MagicMock() + ad.adb.logcat.side_effect = adb.AdbError( + cmd='cmd', + stdout=b'', + stderr=b'failed to clear "main" log', + ret_code=1) + logcat_service = logcat.Logcat(ad) + logcat_service.clear_adb_log() if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/services/sl4a_service_test.py b/tests/mobly/controllers/android_device_lib/services/sl4a_service_test.py index 9205918..42ee25c 100755 --- a/tests/mobly/controllers/android_device_lib/services/sl4a_service_test.py +++ b/tests/mobly/controllers/android_device_lib/services/sl4a_service_test.py @@ -20,49 +20,49 @@ from mobly.controllers.android_device_lib import service_manager @mock.patch('mobly.controllers.android_device_lib.sl4a_client.Sl4aClient') class Sl4aServiceTest(unittest.TestCase): - """Tests for the sl4a service.""" + """Tests for the sl4a service.""" - def test_instantiation(self, _): - service = sl4a_service.Sl4aService(mock.MagicMock()) - self.assertFalse(service.is_alive) + def test_instantiation(self, _): + service = sl4a_service.Sl4aService(mock.MagicMock()) + self.assertFalse(service.is_alive) - def test_start(self, mock_sl4a_client_class): - mock_client = mock_sl4a_client_class.return_value - service = sl4a_service.Sl4aService(mock.MagicMock()) - service.start() - mock_client.start_app_and_connect.assert_called_once_with() - self.assertTrue(service.is_alive) + def test_start(self, mock_sl4a_client_class): + mock_client = mock_sl4a_client_class.return_value + service = sl4a_service.Sl4aService(mock.MagicMock()) + service.start() + mock_client.start_app_and_connect.assert_called_once_with() + self.assertTrue(service.is_alive) - def test_stop(self, mock_sl4a_client_class): - mock_client = mock_sl4a_client_class.return_value - service = sl4a_service.Sl4aService(mock.MagicMock()) - service.start() - service.stop() - mock_client.stop_app.assert_called_once_with() - self.assertFalse(service.is_alive) + def test_stop(self, mock_sl4a_client_class): + mock_client = mock_sl4a_client_class.return_value + service = sl4a_service.Sl4aService(mock.MagicMock()) + service.start() + service.stop() + mock_client.stop_app.assert_called_once_with() + self.assertFalse(service.is_alive) - def test_pause(self, mock_sl4a_client_class): - mock_client = mock_sl4a_client_class.return_value - service = sl4a_service.Sl4aService(mock.MagicMock()) - service.start() - service.pause() - mock_client.stop_event_dispatcher.assert_called_once_with() - mock_client.clear_host_port.assert_called_once_with() + def test_pause(self, mock_sl4a_client_class): + mock_client = mock_sl4a_client_class.return_value + service = sl4a_service.Sl4aService(mock.MagicMock()) + service.start() + service.pause() + mock_client.stop_event_dispatcher.assert_called_once_with() + mock_client.clear_host_port.assert_called_once_with() - def test_resume(self, mock_sl4a_client_class): - mock_client = mock_sl4a_client_class.return_value - service = sl4a_service.Sl4aService(mock.MagicMock()) - service.start() - service.pause() - service.resume() - mock_client.restore_app_connection.assert_called_once_with() + def test_resume(self, mock_sl4a_client_class): + mock_client = mock_sl4a_client_class.return_value + service = sl4a_service.Sl4aService(mock.MagicMock()) + service.start() + service.pause() + service.resume() + mock_client.restore_app_connection.assert_called_once_with() - def test_register_with_service_manager(self, _): - mock_device = mock.MagicMock() - manager = service_manager.ServiceManager(mock_device) - manager.register('sl4a', sl4a_service.Sl4aService) - self.assertTrue(manager.sl4a) + def test_register_with_service_manager(self, _): + mock_device = mock.MagicMock() + manager = service_manager.ServiceManager(mock_device) + manager.register('sl4a', sl4a_service.Sl4aService) + self.assertTrue(manager.sl4a) if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/services/snippet_management_service_test.py b/tests/mobly/controllers/android_device_lib/services/snippet_management_service_test.py index e542382..974972a 100755 --- a/tests/mobly/controllers/android_device_lib/services/snippet_management_service_test.py +++ b/tests/mobly/controllers/android_device_lib/services/snippet_management_service_test.py @@ -21,158 +21,158 @@ SNIPPET_CLIENT_CLASS_PATH = 'mobly.controllers.android_device_lib.snippet_client class SnippetManagementServiceTest(unittest.TestCase): - """Tests for the snippet management service.""" - - def test_empty_manager_start_stop(self): - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.start() - # When no client is registered, manager is never alive. - self.assertFalse(manager.is_alive) - manager.stop() - self.assertFalse(manager.is_alive) - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_get_snippet_client(self, mock_class): - mock_client = mock_class.return_value - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - self.assertEqual(manager.get_snippet_client('foo'), mock_client) - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_get_snippet_client_fail(self, _): - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - self.assertIsNone(manager.get_snippet_client('foo')) - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_stop_with_live_client(self, mock_class): - mock_client = mock_class.return_value - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - mock_client.start_app_and_connect.assert_called_once_with() - manager.stop() - mock_client.stop_app.assert_called_once_with() - mock_client.stop_app.reset_mock() - mock_client.is_alive = False - self.assertFalse(manager.is_alive) - manager.stop() - mock_client.stop_app.assert_not_called() - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_add_snippet_client_dup_name(self, _): - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - msg = ('.* Name "foo" is already registered with package ".*", it ' - 'cannot be used again.') - with self.assertRaisesRegex(snippet_management_service.Error, msg): - manager.add_snippet_client('foo', MOCK_PACKAGE + 'ha') - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_add_snippet_client_dup_package(self, mock_class): - mock_client = mock_class.return_value - mock_client.package = MOCK_PACKAGE - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - msg = ('Snippet package "com.mock.package" has already been loaded ' - 'under name "foo".') - with self.assertRaisesRegex(snippet_management_service.Error, msg): - manager.add_snippet_client('bar', MOCK_PACKAGE) - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_remove_snippet_client(self, mock_class): - mock_client = mock.MagicMock() - mock_class.return_value = mock_client - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - manager.remove_snippet_client('foo') - msg = 'No snippet client is registered with name "foo".' - with self.assertRaisesRegex(snippet_management_service.Error, msg): - manager.foo.do_something() - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_remove_snippet_client(self, mock_class): - mock_client = mock.MagicMock() - mock_class.return_value = mock_client - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - with self.assertRaisesRegex( - snippet_management_service.Error, - 'No snippet client is registered with name "foo".'): - manager.remove_snippet_client('foo') - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_start_with_live_service(self, mock_class): - mock_client = mock_class.return_value - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - mock_client.start_app_and_connect.reset_mock() - mock_client.is_alive = True - manager.start() - mock_client.start_app_and_connect.assert_not_called() - self.assertTrue(manager.is_alive) - mock_client.is_alive = False - manager.start() - mock_client.start_app_and_connect.assert_called_once_with() - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_pause(self, mock_class): - mock_client = mock_class.return_value - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - manager.pause() - mock_client.clear_host_port.assert_called_once_with() - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_resume_positive_case(self, mock_class): - mock_client = mock_class.return_value - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - mock_client.is_alive = True - mock_client.host_port = None - manager.resume() - mock_client.restore_app_connection.assert_called_once_with() - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_resume_alive_with_host_port(self, mock_class): - mock_client = mock_class.return_value - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - mock_client.is_alive = True - mock_client.host_port = 1 - manager.resume() - mock_client.restore_app_connection.assert_not_called() - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_resume_not_alive_no_host_port(self, mock_class): - mock_client = mock_class.return_value - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - mock_client.is_alive = False - mock_client.host_port = None - manager.resume() - mock_client.restore_app_connection.assert_not_called() - - @mock.patch(SNIPPET_CLIENT_CLASS_PATH) - def test_attribute_access(self, mock_class): - mock_client = mock.MagicMock() - mock_class.return_value = mock_client - manager = snippet_management_service.SnippetManagementService( - mock.MagicMock()) - manager.add_snippet_client('foo', MOCK_PACKAGE) - manager.foo.ha('param') - mock_client.ha.assert_called_once_with('param') + """Tests for the snippet management service.""" + + def test_empty_manager_start_stop(self): + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.start() + # When no client is registered, manager is never alive. + self.assertFalse(manager.is_alive) + manager.stop() + self.assertFalse(manager.is_alive) + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_get_snippet_client(self, mock_class): + mock_client = mock_class.return_value + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + self.assertEqual(manager.get_snippet_client('foo'), mock_client) + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_get_snippet_client_fail(self, _): + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + self.assertIsNone(manager.get_snippet_client('foo')) + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_stop_with_live_client(self, mock_class): + mock_client = mock_class.return_value + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + mock_client.start_app_and_connect.assert_called_once_with() + manager.stop() + mock_client.stop_app.assert_called_once_with() + mock_client.stop_app.reset_mock() + mock_client.is_alive = False + self.assertFalse(manager.is_alive) + manager.stop() + mock_client.stop_app.assert_not_called() + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_add_snippet_client_dup_name(self, _): + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + msg = ('.* Name "foo" is already registered with package ".*", it ' + 'cannot be used again.') + with self.assertRaisesRegex(snippet_management_service.Error, msg): + manager.add_snippet_client('foo', MOCK_PACKAGE + 'ha') + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_add_snippet_client_dup_package(self, mock_class): + mock_client = mock_class.return_value + mock_client.package = MOCK_PACKAGE + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + msg = ('Snippet package "com.mock.package" has already been loaded ' + 'under name "foo".') + with self.assertRaisesRegex(snippet_management_service.Error, msg): + manager.add_snippet_client('bar', MOCK_PACKAGE) + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_remove_snippet_client(self, mock_class): + mock_client = mock.MagicMock() + mock_class.return_value = mock_client + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + manager.remove_snippet_client('foo') + msg = 'No snippet client is registered with name "foo".' + with self.assertRaisesRegex(snippet_management_service.Error, msg): + manager.foo.do_something() + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_remove_snippet_client(self, mock_class): + mock_client = mock.MagicMock() + mock_class.return_value = mock_client + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + with self.assertRaisesRegex( + snippet_management_service.Error, + 'No snippet client is registered with name "foo".'): + manager.remove_snippet_client('foo') + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_start_with_live_service(self, mock_class): + mock_client = mock_class.return_value + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + mock_client.start_app_and_connect.reset_mock() + mock_client.is_alive = True + manager.start() + mock_client.start_app_and_connect.assert_not_called() + self.assertTrue(manager.is_alive) + mock_client.is_alive = False + manager.start() + mock_client.start_app_and_connect.assert_called_once_with() + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_pause(self, mock_class): + mock_client = mock_class.return_value + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + manager.pause() + mock_client.clear_host_port.assert_called_once_with() + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_resume_positive_case(self, mock_class): + mock_client = mock_class.return_value + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + mock_client.is_alive = True + mock_client.host_port = None + manager.resume() + mock_client.restore_app_connection.assert_called_once_with() + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_resume_alive_with_host_port(self, mock_class): + mock_client = mock_class.return_value + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + mock_client.is_alive = True + mock_client.host_port = 1 + manager.resume() + mock_client.restore_app_connection.assert_not_called() + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_resume_not_alive_no_host_port(self, mock_class): + mock_client = mock_class.return_value + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + mock_client.is_alive = False + mock_client.host_port = None + manager.resume() + mock_client.restore_app_connection.assert_not_called() + + @mock.patch(SNIPPET_CLIENT_CLASS_PATH) + def test_attribute_access(self, mock_class): + mock_client = mock.MagicMock() + mock_class.return_value = mock_client + manager = snippet_management_service.SnippetManagementService( + mock.MagicMock()) + manager.add_snippet_client('foo', MOCK_PACKAGE) + manager.foo.ha('param') + mock_client.ha.assert_called_once_with('param') if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/sl4a_client_test.py b/tests/mobly/controllers/android_device_lib/sl4a_client_test.py index e786b03..feff163 100755 --- a/tests/mobly/controllers/android_device_lib/sl4a_client_test.py +++ b/tests/mobly/controllers/android_device_lib/sl4a_client_test.py @@ -26,58 +26,58 @@ from tests.lib import mock_android_device class Sl4aClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase): - """Unit tests for mobly.controllers.android_device_lib.sl4a_client. - """ + """Unit tests for mobly.controllers.android_device_lib.sl4a_client. + """ - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.start_standing_subprocess') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - def test_start_app_and_connect(self, mock_get_port, - mock_start_standing_subprocess, - mock_create_connection): - self.setup_mock_socket_file(mock_create_connection) - self._setup_mock_instrumentation_cmd( - mock_start_standing_subprocess, resp_lines=[b'\n']) - client = self._make_client() - client.start_app_and_connect() - self.assertEqual(8080, client.device_port) + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.start_standing_subprocess') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + def test_start_app_and_connect(self, mock_get_port, + mock_start_standing_subprocess, + mock_create_connection): + self.setup_mock_socket_file(mock_create_connection) + self._setup_mock_instrumentation_cmd( + mock_start_standing_subprocess, resp_lines=[b'\n']) + client = self._make_client() + client.start_app_and_connect() + self.assertEqual(8080, client.device_port) - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.start_standing_subprocess') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - def test_app_not_installed(self, mock_get_port, - mock_start_standing_subprocess, - mock_create_connection): - self.setup_mock_socket_file(mock_create_connection) - self._setup_mock_instrumentation_cmd( - mock_start_standing_subprocess, resp_lines=[b'\n']) - client = self._make_client( - adb_proxy=mock_android_device.MockAdbProxy()) - with self.assertRaisesRegex(jsonrpc_client_base.AppStartError, - '.* SL4A is not installed on .*'): - client.start_app_and_connect() + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.start_standing_subprocess') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + def test_app_not_installed(self, mock_get_port, + mock_start_standing_subprocess, + mock_create_connection): + self.setup_mock_socket_file(mock_create_connection) + self._setup_mock_instrumentation_cmd( + mock_start_standing_subprocess, resp_lines=[b'\n']) + client = self._make_client( + adb_proxy=mock_android_device.MockAdbProxy()) + with self.assertRaisesRegex(jsonrpc_client_base.AppStartError, + '.* SL4A is not installed on .*'): + client.start_app_and_connect() - def _make_client(self, adb_proxy=None): - adb_proxy = adb_proxy or mock_android_device.MockAdbProxy( - installed_packages=['com.googlecode.android_scripting']) - ad = mock.Mock() - ad.adb = adb_proxy - ad.build_info = { - 'build_version_codename': - ad.adb.getprop('ro.build.version.codename'), - 'build_version_sdk': ad.adb.getprop('ro.build.version.sdk'), - } - return sl4a_client.Sl4aClient(ad=ad) + def _make_client(self, adb_proxy=None): + adb_proxy = adb_proxy or mock_android_device.MockAdbProxy( + installed_packages=['com.googlecode.android_scripting']) + ad = mock.Mock() + ad.adb = adb_proxy + ad.build_info = { + 'build_version_codename': + ad.adb.getprop('ro.build.version.codename'), + 'build_version_sdk': ad.adb.getprop('ro.build.version.sdk'), + } + return sl4a_client.Sl4aClient(ad=ad) - def _setup_mock_instrumentation_cmd(self, mock_start_standing_subprocess, - resp_lines): - mock_proc = mock_start_standing_subprocess() - mock_proc.stdout.readline.side_effect = resp_lines + def _setup_mock_instrumentation_cmd(self, mock_start_standing_subprocess, + resp_lines): + mock_proc = mock_start_standing_subprocess() + mock_proc.stdout.readline.side_effect = resp_lines if __name__ == "__main__": - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/snippet_client_test.py b/tests/mobly/controllers/android_device_lib/snippet_client_test.py index cb62345..412edcb 100755 --- a/tests/mobly/controllers/android_device_lib/snippet_client_test.py +++ b/tests/mobly/controllers/android_device_lib/snippet_client_test.py @@ -32,485 +32,485 @@ MOCK_USER_ID = 0 def get_print_function_name(): - """Gets the name of the print function for mocking. + """Gets the name of the print function for mocking. - Returns: - A str representing the print function to mock. - """ - if sys.version_info >= (3, 0): - return 'builtins.print' - else: - return '__builtin__.print' + Returns: + A str representing the print function to mock. + """ + if sys.version_info >= (3, 0): + return 'builtins.print' + else: + return '__builtin__.print' class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase): - """Unit tests for mobly.controllers.android_device_lib.snippet_client. - """ - - def test_check_app_installed_normal(self): - sc = self._make_client() - sc._check_app_installed() - - def test_check_app_installed_fail_app_not_installed(self): - sc = self._make_client(mock_android_device.MockAdbProxy()) - expected_msg = '.* %s is not installed.' % MOCK_PACKAGE_NAME - with self.assertRaisesRegex(snippet_client.AppStartPreCheckError, - expected_msg): - sc._check_app_installed() - - def test_check_app_installed_fail_not_instrumented(self): - sc = self._make_client( - mock_android_device.MockAdbProxy( - installed_packages=[MOCK_PACKAGE_NAME])) - expected_msg = ('.* %s is installed, but it is not instrumented.' % - MOCK_PACKAGE_NAME) - with self.assertRaisesRegex(snippet_client.AppStartPreCheckError, - expected_msg): - sc._check_app_installed() - - def test_check_app_installed_fail_target_not_installed(self): - sc = self._make_client( - mock_android_device.MockAdbProxy(instrumented_packages=[( - MOCK_PACKAGE_NAME, - snippet_client._INSTRUMENTATION_RUNNER_PACKAGE, - MOCK_MISSING_PACKAGE_NAME)])) - expected_msg = ('.* Instrumentation target %s is not installed.' % - MOCK_MISSING_PACKAGE_NAME) - with self.assertRaisesRegex(snippet_client.AppStartPreCheckError, - expected_msg): - sc._check_app_installed() - - @mock.patch('socket.create_connection') - def test_snippet_start(self, mock_create_connection): - self.setup_mock_socket_file(mock_create_connection) - client = self._make_client() - client.connect() - result = client.testSnippetCall() - self.assertEqual(123, result) - - @mock.patch('socket.create_connection') - def test_snippet_start_event_client(self, mock_create_connection): - fake_file = self.setup_mock_socket_file(mock_create_connection) - client = self._make_client() - client.host_port = 123 # normally picked by start_app_and_connect - client.connect() - fake_file.resp = self.MOCK_RESP_WITH_CALLBACK - callback = client.testSnippetCall() - self.assertEqual(123, callback.ret_value) - self.assertEqual('1-0', callback._id) - - # Check to make sure the event client is using the same port as the - # main client. - self.assertEqual(123, callback._event_client.host_port) - - fake_file.resp = self.MOCK_RESP_WITH_ERROR - with self.assertRaisesRegex(jsonrpc_client_base.ApiError, '1'): - callback.getAll('eventName') - - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - def test_snippet_restore_event_client(self, mock_get_port, - mock_create_connection): - mock_get_port.return_value = 789 - fake_file = self.setup_mock_socket_file(mock_create_connection) - client = self._make_client() - client.host_port = 123 # normally picked by start_app_and_connect - client.device_port = 456 - client.connect() - fake_file.resp = self.MOCK_RESP_WITH_CALLBACK - callback = client.testSnippetCall() - - # before reconnect, clients use previously selected ports - self.assertEqual(123, client.host_port) - self.assertEqual(456, client.device_port) - self.assertEqual(123, callback._event_client.host_port) - self.assertEqual(456, callback._event_client.device_port) - - # after reconnect, if host port specified, clients use specified port - client.restore_app_connection(port=321) - self.assertEqual(321, client.host_port) - self.assertEqual(456, client.device_port) - self.assertEqual(321, callback._event_client.host_port) - self.assertEqual(456, callback._event_client.device_port) - - # after reconnect, if host port not specified, clients use selected - # available port - client.restore_app_connection() - self.assertEqual(789, client.host_port) - self.assertEqual(456, client.device_port) - self.assertEqual(789, callback._event_client.host_port) - self.assertEqual(456, callback._event_client.device_port) - - # if unable to reconnect for any reason, a - # jsonrpc_client_base.AppRestoreConnectionError is raised. - mock_create_connection.side_effect = IOError('socket timed out') - with self.assertRaisesRegex( - jsonrpc_client_base.AppRestoreConnectionError, - ('Failed to restore app connection for %s at host port %s, ' - 'device port %s') % (MOCK_PACKAGE_NAME, 789, 456)): - client.restore_app_connection() - - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.start_standing_subprocess') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - def test_snippet_start_app_and_connect(self, mock_get_port, - mock_start_standing_subprocess, - mock_create_connection): - self.setup_mock_socket_file(mock_create_connection) - self._setup_mock_instrumentation_cmd( - mock_start_standing_subprocess, - resp_lines=[ - b'SNIPPET START, PROTOCOL 1 0\n', - b'SNIPPET SERVING, PORT 123\n', - ]) - client = self._make_client() - client.start_app_and_connect() - self.assertEqual(123, client.device_port) - self.assertTrue(client.is_alive) - - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.stop_standing_subprocess') - def test_snippet_stop_app(self, mock_stop_standing_subprocess, - mock_create_connection): - adb_proxy = mock.MagicMock() - adb_proxy.shell.return_value = b'OK (0 tests)' - client = self._make_client(adb_proxy) - client.stop_app() - self.assertFalse(client.is_alive) - - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'SnippetClient.disconnect') - def test_snippet_stop_app_raises(self, mock_disconnect, - mock_create_connection): - mock_disconnect.side_effect = Exception('ha') - adb_proxy = mock.MagicMock() - adb_proxy.shell.return_value = b'OK (0 tests)' - client = self._make_client(adb_proxy) - client.host_port = 1 - with self.assertRaisesRegex(Exception, 'ha'): - client.stop_app() - adb_proxy.forward.assert_called_once_with(['--remove', 'tcp:1']) - - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.start_standing_subprocess') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - @mock.patch( - 'mobly.controllers.android_device_lib.snippet_client.SnippetClient.' - 'disable_hidden_api_blacklist') - @mock.patch( - 'mobly.controllers.android_device_lib.snippet_client.SnippetClient.' - 'stop_app') - def test_start_app_and_connect_precheck_fail( - self, mock_stop, mock_precheck, mock_get_port, - mock_start_standing_subprocess, mock_create_connection): - self.setup_mock_socket_file(mock_create_connection) - self._setup_mock_instrumentation_cmd( - mock_start_standing_subprocess, - resp_lines=[ - b'SNIPPET START, PROTOCOL 1 0\n', - b'SNIPPET SERVING, PORT 123\n', - ]) - client = self._make_client() - mock_precheck.side_effect = snippet_client.AppStartPreCheckError( - client.ad, 'ha') - with self.assertRaisesRegex(snippet_client.AppStartPreCheckError, - 'ha'): - client.start_app_and_connect() - mock_stop.assert_not_called() - self.assertFalse(client.is_alive) - - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.start_standing_subprocess') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - @mock.patch( - 'mobly.controllers.android_device_lib.snippet_client.SnippetClient._start_app_and_connect' - ) - @mock.patch( - 'mobly.controllers.android_device_lib.snippet_client.SnippetClient.stop_app' - ) - def test_start_app_and_connect_generic_error( - self, mock_stop, mock_start, mock_get_port, - mock_start_standing_subprocess, mock_create_connection): - self.setup_mock_socket_file(mock_create_connection) - self._setup_mock_instrumentation_cmd( - mock_start_standing_subprocess, - resp_lines=[ - b'SNIPPET START, PROTOCOL 1 0\n', - b'SNIPPET SERVING, PORT 123\n', - ]) - client = self._make_client() - mock_start.side_effect = Exception('ha') - with self.assertRaisesRegex(Exception, 'ha'): - client.start_app_and_connect() - mock_stop.assert_called_once_with() - self.assertFalse(client.is_alive) - - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.start_standing_subprocess') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - @mock.patch( - 'mobly.controllers.android_device_lib.snippet_client.SnippetClient._start_app_and_connect' - ) - @mock.patch( - 'mobly.controllers.android_device_lib.snippet_client.SnippetClient.stop_app' - ) - def test_start_app_and_connect_fail_stop_also_fail( - self, mock_stop, mock_start, mock_get_port, - mock_start_standing_subprocess, mock_create_connection): - self.setup_mock_socket_file(mock_create_connection) - self._setup_mock_instrumentation_cmd( - mock_start_standing_subprocess, - resp_lines=[ - b'SNIPPET START, PROTOCOL 1 0\n', - b'SNIPPET SERVING, PORT 123\n', - ]) - client = self._make_client() - mock_start.side_effect = Exception('Some error') - mock_stop.side_effect = Exception('Another error') - with self.assertRaisesRegex(Exception, 'Some error'): - client.start_app_and_connect() - mock_stop.assert_called_once_with() - self.assertFalse(client.is_alive) - - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'SnippetClient._do_start_app') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'SnippetClient._check_app_installed') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'SnippetClient._read_protocol_line') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'SnippetClient.connect') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - def test_snippet_start_on_sdk_21(self, mock_get_port, mock_connect, - mock_read_protocol_line, - mock_check_app_installed, - mock_do_start_app): - """Check that `--user` is not added to start command on SDK < 24.""" - - def _mocked_shell(arg): - if 'setsid' in arg: - raise adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code') - else: - return b'nohup' - - mock_get_port.return_value = 123 - mock_read_protocol_line.side_effect = [ - 'SNIPPET START, PROTOCOL 1 234', - 'SNIPPET SERVING, PORT 1234', - 'SNIPPET START, PROTOCOL 1 234', - 'SNIPPET SERVING, PORT 1234', - 'SNIPPET START, PROTOCOL 1 234', - 'SNIPPET SERVING, PORT 1234', - ] - - # Test 'setsid' exists - client = self._make_client() - client._ad.build_info['build_version_sdk'] = 21 - client._adb.shell = mock.Mock(return_value=b'setsid') - client.start_app_and_connect() - cmd_setsid = '%s am instrument -w -e action start %s/%s' % ( - snippet_client._SETSID_COMMAND, MOCK_PACKAGE_NAME, - snippet_client._INSTRUMENTATION_RUNNER_PACKAGE) - mock_do_start_app.assert_has_calls([mock.call(cmd_setsid)]) - - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'SnippetClient._do_start_app') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'SnippetClient._check_app_installed') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'SnippetClient._read_protocol_line') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'SnippetClient.connect') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - def test_snippet_start_app_and_connect_persistent_session( - self, mock_get_port, mock_connect, mock_read_protocol_line, - mock_check_app_installed, mock_do_start_app): - def _mocked_shell(arg): - if 'setsid' in arg: - raise adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code') - else: - return b'nohup' - - mock_get_port.return_value = 123 - mock_read_protocol_line.side_effect = [ - 'SNIPPET START, PROTOCOL 1 234', - 'SNIPPET SERVING, PORT 1234', - 'SNIPPET START, PROTOCOL 1 234', - 'SNIPPET SERVING, PORT 1234', - 'SNIPPET START, PROTOCOL 1 234', - 'SNIPPET SERVING, PORT 1234', - ] - - # Test 'setsid' exists - client = self._make_client() - client._adb.shell = mock.Mock(return_value=b'setsid') - client.start_app_and_connect() - cmd_setsid = '%s am instrument --user %s -w -e action start %s/%s' % ( - snippet_client._SETSID_COMMAND, MOCK_USER_ID, MOCK_PACKAGE_NAME, - snippet_client._INSTRUMENTATION_RUNNER_PACKAGE) - mock_do_start_app.assert_has_calls([mock.call(cmd_setsid)]) - - # Test 'setsid' does not exist, but 'nohup' exsits - client = self._make_client() - client._adb.shell = _mocked_shell - client.start_app_and_connect() - cmd_nohup = '%s am instrument --user %s -w -e action start %s/%s' % ( - snippet_client._NOHUP_COMMAND, MOCK_USER_ID, MOCK_PACKAGE_NAME, - snippet_client._INSTRUMENTATION_RUNNER_PACKAGE) - mock_do_start_app.assert_has_calls( - [mock.call(cmd_setsid), - mock.call(cmd_nohup)]) - - # Test both 'setsid' and 'nohup' do not exist - client._adb.shell = mock.Mock( - side_effect=adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code')) - client = self._make_client() - client.start_app_and_connect() - cmd_not_persist = ' am instrument --user %s -w -e action start %s/%s' % ( - MOCK_USER_ID, MOCK_PACKAGE_NAME, - snippet_client._INSTRUMENTATION_RUNNER_PACKAGE) - mock_do_start_app.assert_has_calls([ - mock.call(cmd_setsid), - mock.call(cmd_nohup), - mock.call(cmd_not_persist) - ]) - - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.start_standing_subprocess') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - def test_snippet_start_app_crash(self, mock_get_port, - mock_start_standing_subprocess, - mock_create_connection): - mock_get_port.return_value = 456 - self.setup_mock_socket_file(mock_create_connection) - self._setup_mock_instrumentation_cmd( - mock_start_standing_subprocess, - resp_lines=[ - b'INSTRUMENTATION_RESULT: shortMsg=Process crashed.\n' - ]) - client = self._make_client() - with self.assertRaisesRegex( - snippet_client.ProtocolVersionError, - 'INSTRUMENTATION_RESULT: shortMsg=Process crashed.'): - client.start_app_and_connect() - - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.start_standing_subprocess') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - def test_snippet_start_app_and_connect_unknown_protocol( - self, mock_get_port, mock_start_standing_subprocess): - mock_get_port.return_value = 789 - self._setup_mock_instrumentation_cmd( - mock_start_standing_subprocess, - resp_lines=[b'SNIPPET START, PROTOCOL 99 0\n']) - client = self._make_client() - with self.assertRaisesRegex(snippet_client.ProtocolVersionError, - 'SNIPPET START, PROTOCOL 99 0'): - client.start_app_and_connect() - - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.start_standing_subprocess') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - def test_snippet_start_app_and_connect_header_junk( - self, mock_get_port, mock_start_standing_subprocess, - mock_create_connection): - self.setup_mock_socket_file(mock_create_connection) - self._setup_mock_instrumentation_cmd( - mock_start_standing_subprocess, - resp_lines=[ - b'This is some header junk\n', - b'Some phones print arbitrary output\n', - b'SNIPPET START, PROTOCOL 1 0\n', - b'Maybe in the middle too\n', - b'SNIPPET SERVING, PORT 123\n', - ]) - client = self._make_client() - client.start_app_and_connect() - self.assertEqual(123, client.device_port) - - @mock.patch('socket.create_connection') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.start_standing_subprocess') - @mock.patch('mobly.controllers.android_device_lib.snippet_client.' - 'utils.get_available_host_port') - def test_snippet_start_app_and_connect_no_valid_line( - self, mock_get_port, mock_start_standing_subprocess, - mock_create_connection): - mock_get_port.return_value = 456 - self.setup_mock_socket_file(mock_create_connection) - self._setup_mock_instrumentation_cmd( - mock_start_standing_subprocess, - resp_lines=[ - b'This is some header junk\n', - b'Some phones print arbitrary output\n', - b'', # readline uses '' to mark EOF - ]) - client = self._make_client() - with self.assertRaisesRegex(jsonrpc_client_base.AppStartError, - 'Unexpected EOF waiting for app to start'): - client.start_app_and_connect() - - @mock.patch(get_print_function_name()) - def test_help_rpc_when_printing_by_default(self, mock_print): - client = self._make_client() - mock_rpc = mock.MagicMock() - client._rpc = mock_rpc - - result = client.help() - mock_rpc.assert_called_once_with('help') - self.assertEqual(None, result) - mock_print.assert_called_once_with(mock_rpc.return_value) - - @mock.patch(get_print_function_name()) - def test_help_rpc_when_not_printing(self, mock_print): - client = self._make_client() - mock_rpc = mock.MagicMock() - client._rpc = mock_rpc - - result = client.help(print_output=False) - mock_rpc.assert_called_once_with('help') - self.assertEqual(mock_rpc.return_value, result) - mock_print.assert_not_called() - - def _make_client(self, adb_proxy=None): - adb_proxy = adb_proxy or mock_android_device.MockAdbProxy( - instrumented_packages=[( - MOCK_PACKAGE_NAME, - snippet_client._INSTRUMENTATION_RUNNER_PACKAGE, - MOCK_PACKAGE_NAME)]) - ad = mock.Mock() - ad.adb = adb_proxy - ad.adb.current_user_id = MOCK_USER_ID - ad.build_info = { - 'build_version_codename': - ad.adb.getprop('ro.build.version.codename'), - 'build_version_sdk': ad.adb.getprop('ro.build.version.sdk'), - } - return snippet_client.SnippetClient(package=MOCK_PACKAGE_NAME, ad=ad) - - def _setup_mock_instrumentation_cmd(self, mock_start_standing_subprocess, - resp_lines): - mock_proc = mock_start_standing_subprocess() - mock_proc.stdout.readline.side_effect = resp_lines + """Unit tests for mobly.controllers.android_device_lib.snippet_client. + """ + + def test_check_app_installed_normal(self): + sc = self._make_client() + sc._check_app_installed() + + def test_check_app_installed_fail_app_not_installed(self): + sc = self._make_client(mock_android_device.MockAdbProxy()) + expected_msg = '.* %s is not installed.' % MOCK_PACKAGE_NAME + with self.assertRaisesRegex(snippet_client.AppStartPreCheckError, + expected_msg): + sc._check_app_installed() + + def test_check_app_installed_fail_not_instrumented(self): + sc = self._make_client( + mock_android_device.MockAdbProxy( + installed_packages=[MOCK_PACKAGE_NAME])) + expected_msg = ('.* %s is installed, but it is not instrumented.' % + MOCK_PACKAGE_NAME) + with self.assertRaisesRegex(snippet_client.AppStartPreCheckError, + expected_msg): + sc._check_app_installed() + + def test_check_app_installed_fail_target_not_installed(self): + sc = self._make_client( + mock_android_device.MockAdbProxy(instrumented_packages=[( + MOCK_PACKAGE_NAME, + snippet_client._INSTRUMENTATION_RUNNER_PACKAGE, + MOCK_MISSING_PACKAGE_NAME)])) + expected_msg = ('.* Instrumentation target %s is not installed.' % + MOCK_MISSING_PACKAGE_NAME) + with self.assertRaisesRegex(snippet_client.AppStartPreCheckError, + expected_msg): + sc._check_app_installed() + + @mock.patch('socket.create_connection') + def test_snippet_start(self, mock_create_connection): + self.setup_mock_socket_file(mock_create_connection) + client = self._make_client() + client.connect() + result = client.testSnippetCall() + self.assertEqual(123, result) + + @mock.patch('socket.create_connection') + def test_snippet_start_event_client(self, mock_create_connection): + fake_file = self.setup_mock_socket_file(mock_create_connection) + client = self._make_client() + client.host_port = 123 # normally picked by start_app_and_connect + client.connect() + fake_file.resp = self.MOCK_RESP_WITH_CALLBACK + callback = client.testSnippetCall() + self.assertEqual(123, callback.ret_value) + self.assertEqual('1-0', callback._id) + + # Check to make sure the event client is using the same port as the + # main client. + self.assertEqual(123, callback._event_client.host_port) + + fake_file.resp = self.MOCK_RESP_WITH_ERROR + with self.assertRaisesRegex(jsonrpc_client_base.ApiError, '1'): + callback.getAll('eventName') + + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + def test_snippet_restore_event_client(self, mock_get_port, + mock_create_connection): + mock_get_port.return_value = 789 + fake_file = self.setup_mock_socket_file(mock_create_connection) + client = self._make_client() + client.host_port = 123 # normally picked by start_app_and_connect + client.device_port = 456 + client.connect() + fake_file.resp = self.MOCK_RESP_WITH_CALLBACK + callback = client.testSnippetCall() + + # before reconnect, clients use previously selected ports + self.assertEqual(123, client.host_port) + self.assertEqual(456, client.device_port) + self.assertEqual(123, callback._event_client.host_port) + self.assertEqual(456, callback._event_client.device_port) + + # after reconnect, if host port specified, clients use specified port + client.restore_app_connection(port=321) + self.assertEqual(321, client.host_port) + self.assertEqual(456, client.device_port) + self.assertEqual(321, callback._event_client.host_port) + self.assertEqual(456, callback._event_client.device_port) + + # after reconnect, if host port not specified, clients use selected + # available port + client.restore_app_connection() + self.assertEqual(789, client.host_port) + self.assertEqual(456, client.device_port) + self.assertEqual(789, callback._event_client.host_port) + self.assertEqual(456, callback._event_client.device_port) + + # if unable to reconnect for any reason, a + # jsonrpc_client_base.AppRestoreConnectionError is raised. + mock_create_connection.side_effect = IOError('socket timed out') + with self.assertRaisesRegex( + jsonrpc_client_base.AppRestoreConnectionError, + ('Failed to restore app connection for %s at host port %s, ' + 'device port %s') % (MOCK_PACKAGE_NAME, 789, 456)): + client.restore_app_connection() + + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.start_standing_subprocess') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + def test_snippet_start_app_and_connect(self, mock_get_port, + mock_start_standing_subprocess, + mock_create_connection): + self.setup_mock_socket_file(mock_create_connection) + self._setup_mock_instrumentation_cmd( + mock_start_standing_subprocess, + resp_lines=[ + b'SNIPPET START, PROTOCOL 1 0\n', + b'SNIPPET SERVING, PORT 123\n', + ]) + client = self._make_client() + client.start_app_and_connect() + self.assertEqual(123, client.device_port) + self.assertTrue(client.is_alive) + + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.stop_standing_subprocess') + def test_snippet_stop_app(self, mock_stop_standing_subprocess, + mock_create_connection): + adb_proxy = mock.MagicMock() + adb_proxy.shell.return_value = b'OK (0 tests)' + client = self._make_client(adb_proxy) + client.stop_app() + self.assertFalse(client.is_alive) + + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'SnippetClient.disconnect') + def test_snippet_stop_app_raises(self, mock_disconnect, + mock_create_connection): + mock_disconnect.side_effect = Exception('ha') + adb_proxy = mock.MagicMock() + adb_proxy.shell.return_value = b'OK (0 tests)' + client = self._make_client(adb_proxy) + client.host_port = 1 + with self.assertRaisesRegex(Exception, 'ha'): + client.stop_app() + adb_proxy.forward.assert_called_once_with(['--remove', 'tcp:1']) + + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.start_standing_subprocess') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + @mock.patch( + 'mobly.controllers.android_device_lib.snippet_client.SnippetClient.' + 'disable_hidden_api_blacklist') + @mock.patch( + 'mobly.controllers.android_device_lib.snippet_client.SnippetClient.' + 'stop_app') + def test_start_app_and_connect_precheck_fail( + self, mock_stop, mock_precheck, mock_get_port, + mock_start_standing_subprocess, mock_create_connection): + self.setup_mock_socket_file(mock_create_connection) + self._setup_mock_instrumentation_cmd( + mock_start_standing_subprocess, + resp_lines=[ + b'SNIPPET START, PROTOCOL 1 0\n', + b'SNIPPET SERVING, PORT 123\n', + ]) + client = self._make_client() + mock_precheck.side_effect = snippet_client.AppStartPreCheckError( + client.ad, 'ha') + with self.assertRaisesRegex(snippet_client.AppStartPreCheckError, + 'ha'): + client.start_app_and_connect() + mock_stop.assert_not_called() + self.assertFalse(client.is_alive) + + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.start_standing_subprocess') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + @mock.patch( + 'mobly.controllers.android_device_lib.snippet_client.SnippetClient._start_app_and_connect' + ) + @mock.patch( + 'mobly.controllers.android_device_lib.snippet_client.SnippetClient.stop_app' + ) + def test_start_app_and_connect_generic_error( + self, mock_stop, mock_start, mock_get_port, + mock_start_standing_subprocess, mock_create_connection): + self.setup_mock_socket_file(mock_create_connection) + self._setup_mock_instrumentation_cmd( + mock_start_standing_subprocess, + resp_lines=[ + b'SNIPPET START, PROTOCOL 1 0\n', + b'SNIPPET SERVING, PORT 123\n', + ]) + client = self._make_client() + mock_start.side_effect = Exception('ha') + with self.assertRaisesRegex(Exception, 'ha'): + client.start_app_and_connect() + mock_stop.assert_called_once_with() + self.assertFalse(client.is_alive) + + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.start_standing_subprocess') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + @mock.patch( + 'mobly.controllers.android_device_lib.snippet_client.SnippetClient._start_app_and_connect' + ) + @mock.patch( + 'mobly.controllers.android_device_lib.snippet_client.SnippetClient.stop_app' + ) + def test_start_app_and_connect_fail_stop_also_fail( + self, mock_stop, mock_start, mock_get_port, + mock_start_standing_subprocess, mock_create_connection): + self.setup_mock_socket_file(mock_create_connection) + self._setup_mock_instrumentation_cmd( + mock_start_standing_subprocess, + resp_lines=[ + b'SNIPPET START, PROTOCOL 1 0\n', + b'SNIPPET SERVING, PORT 123\n', + ]) + client = self._make_client() + mock_start.side_effect = Exception('Some error') + mock_stop.side_effect = Exception('Another error') + with self.assertRaisesRegex(Exception, 'Some error'): + client.start_app_and_connect() + mock_stop.assert_called_once_with() + self.assertFalse(client.is_alive) + + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'SnippetClient._do_start_app') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'SnippetClient._check_app_installed') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'SnippetClient._read_protocol_line') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'SnippetClient.connect') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + def test_snippet_start_on_sdk_21(self, mock_get_port, mock_connect, + mock_read_protocol_line, + mock_check_app_installed, + mock_do_start_app): + """Check that `--user` is not added to start command on SDK < 24.""" + + def _mocked_shell(arg): + if 'setsid' in arg: + raise adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code') + else: + return b'nohup' + + mock_get_port.return_value = 123 + mock_read_protocol_line.side_effect = [ + 'SNIPPET START, PROTOCOL 1 234', + 'SNIPPET SERVING, PORT 1234', + 'SNIPPET START, PROTOCOL 1 234', + 'SNIPPET SERVING, PORT 1234', + 'SNIPPET START, PROTOCOL 1 234', + 'SNIPPET SERVING, PORT 1234', + ] + + # Test 'setsid' exists + client = self._make_client() + client._ad.build_info['build_version_sdk'] = 21 + client._adb.shell = mock.Mock(return_value=b'setsid') + client.start_app_and_connect() + cmd_setsid = '%s am instrument -w -e action start %s/%s' % ( + snippet_client._SETSID_COMMAND, MOCK_PACKAGE_NAME, + snippet_client._INSTRUMENTATION_RUNNER_PACKAGE) + mock_do_start_app.assert_has_calls([mock.call(cmd_setsid)]) + + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'SnippetClient._do_start_app') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'SnippetClient._check_app_installed') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'SnippetClient._read_protocol_line') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'SnippetClient.connect') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + def test_snippet_start_app_and_connect_persistent_session( + self, mock_get_port, mock_connect, mock_read_protocol_line, + mock_check_app_installed, mock_do_start_app): + def _mocked_shell(arg): + if 'setsid' in arg: + raise adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code') + else: + return b'nohup' + + mock_get_port.return_value = 123 + mock_read_protocol_line.side_effect = [ + 'SNIPPET START, PROTOCOL 1 234', + 'SNIPPET SERVING, PORT 1234', + 'SNIPPET START, PROTOCOL 1 234', + 'SNIPPET SERVING, PORT 1234', + 'SNIPPET START, PROTOCOL 1 234', + 'SNIPPET SERVING, PORT 1234', + ] + + # Test 'setsid' exists + client = self._make_client() + client._adb.shell = mock.Mock(return_value=b'setsid') + client.start_app_and_connect() + cmd_setsid = '%s am instrument --user %s -w -e action start %s/%s' % ( + snippet_client._SETSID_COMMAND, MOCK_USER_ID, MOCK_PACKAGE_NAME, + snippet_client._INSTRUMENTATION_RUNNER_PACKAGE) + mock_do_start_app.assert_has_calls([mock.call(cmd_setsid)]) + + # Test 'setsid' does not exist, but 'nohup' exsits + client = self._make_client() + client._adb.shell = _mocked_shell + client.start_app_and_connect() + cmd_nohup = '%s am instrument --user %s -w -e action start %s/%s' % ( + snippet_client._NOHUP_COMMAND, MOCK_USER_ID, MOCK_PACKAGE_NAME, + snippet_client._INSTRUMENTATION_RUNNER_PACKAGE) + mock_do_start_app.assert_has_calls( + [mock.call(cmd_setsid), + mock.call(cmd_nohup)]) + + # Test both 'setsid' and 'nohup' do not exist + client._adb.shell = mock.Mock( + side_effect=adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code')) + client = self._make_client() + client.start_app_and_connect() + cmd_not_persist = ' am instrument --user %s -w -e action start %s/%s' % ( + MOCK_USER_ID, MOCK_PACKAGE_NAME, + snippet_client._INSTRUMENTATION_RUNNER_PACKAGE) + mock_do_start_app.assert_has_calls([ + mock.call(cmd_setsid), + mock.call(cmd_nohup), + mock.call(cmd_not_persist) + ]) + + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.start_standing_subprocess') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + def test_snippet_start_app_crash(self, mock_get_port, + mock_start_standing_subprocess, + mock_create_connection): + mock_get_port.return_value = 456 + self.setup_mock_socket_file(mock_create_connection) + self._setup_mock_instrumentation_cmd( + mock_start_standing_subprocess, + resp_lines=[ + b'INSTRUMENTATION_RESULT: shortMsg=Process crashed.\n' + ]) + client = self._make_client() + with self.assertRaisesRegex( + snippet_client.ProtocolVersionError, + 'INSTRUMENTATION_RESULT: shortMsg=Process crashed.'): + client.start_app_and_connect() + + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.start_standing_subprocess') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + def test_snippet_start_app_and_connect_unknown_protocol( + self, mock_get_port, mock_start_standing_subprocess): + mock_get_port.return_value = 789 + self._setup_mock_instrumentation_cmd( + mock_start_standing_subprocess, + resp_lines=[b'SNIPPET START, PROTOCOL 99 0\n']) + client = self._make_client() + with self.assertRaisesRegex(snippet_client.ProtocolVersionError, + 'SNIPPET START, PROTOCOL 99 0'): + client.start_app_and_connect() + + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.start_standing_subprocess') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + def test_snippet_start_app_and_connect_header_junk( + self, mock_get_port, mock_start_standing_subprocess, + mock_create_connection): + self.setup_mock_socket_file(mock_create_connection) + self._setup_mock_instrumentation_cmd( + mock_start_standing_subprocess, + resp_lines=[ + b'This is some header junk\n', + b'Some phones print arbitrary output\n', + b'SNIPPET START, PROTOCOL 1 0\n', + b'Maybe in the middle too\n', + b'SNIPPET SERVING, PORT 123\n', + ]) + client = self._make_client() + client.start_app_and_connect() + self.assertEqual(123, client.device_port) + + @mock.patch('socket.create_connection') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.start_standing_subprocess') + @mock.patch('mobly.controllers.android_device_lib.snippet_client.' + 'utils.get_available_host_port') + def test_snippet_start_app_and_connect_no_valid_line( + self, mock_get_port, mock_start_standing_subprocess, + mock_create_connection): + mock_get_port.return_value = 456 + self.setup_mock_socket_file(mock_create_connection) + self._setup_mock_instrumentation_cmd( + mock_start_standing_subprocess, + resp_lines=[ + b'This is some header junk\n', + b'Some phones print arbitrary output\n', + b'', # readline uses '' to mark EOF + ]) + client = self._make_client() + with self.assertRaisesRegex(jsonrpc_client_base.AppStartError, + 'Unexpected EOF waiting for app to start'): + client.start_app_and_connect() + + @mock.patch(get_print_function_name()) + def test_help_rpc_when_printing_by_default(self, mock_print): + client = self._make_client() + mock_rpc = mock.MagicMock() + client._rpc = mock_rpc + + result = client.help() + mock_rpc.assert_called_once_with('help') + self.assertEqual(None, result) + mock_print.assert_called_once_with(mock_rpc.return_value) + + @mock.patch(get_print_function_name()) + def test_help_rpc_when_not_printing(self, mock_print): + client = self._make_client() + mock_rpc = mock.MagicMock() + client._rpc = mock_rpc + + result = client.help(print_output=False) + mock_rpc.assert_called_once_with('help') + self.assertEqual(mock_rpc.return_value, result) + mock_print.assert_not_called() + + def _make_client(self, adb_proxy=None): + adb_proxy = adb_proxy or mock_android_device.MockAdbProxy( + instrumented_packages=[( + MOCK_PACKAGE_NAME, + snippet_client._INSTRUMENTATION_RUNNER_PACKAGE, + MOCK_PACKAGE_NAME)]) + ad = mock.Mock() + ad.adb = adb_proxy + ad.adb.current_user_id = MOCK_USER_ID + ad.build_info = { + 'build_version_codename': + ad.adb.getprop('ro.build.version.codename'), + 'build_version_sdk': ad.adb.getprop('ro.build.version.sdk'), + } + return snippet_client.SnippetClient(package=MOCK_PACKAGE_NAME, ad=ad) + + def _setup_mock_instrumentation_cmd(self, mock_start_standing_subprocess, + resp_lines): + mock_proc = mock_start_standing_subprocess() + mock_proc.stdout.readline.side_effect = resp_lines if __name__ == "__main__": - unittest.main() + unittest.main() diff --git a/tests/mobly/controllers/android_device_lib/snippet_event_test.py b/tests/mobly/controllers/android_device_lib/snippet_event_test.py index 1b782fe..a995197 100755 --- a/tests/mobly/controllers/android_device_lib/snippet_event_test.py +++ b/tests/mobly/controllers/android_device_lib/snippet_event_test.py @@ -26,16 +26,16 @@ MOCK_DATA = {'foo': 'bar'} class SnippetEventTest(unittest.TestCase): - def test_basic(self): - """Verifies that an event object can be created and logged properly. - """ - event = snippet_event.SnippetEvent(MOCK_CALLBACK_ID, MOCK_EVENT_NAME, - MOCK_CREATION_TIME, MOCK_DATA) - self.assertEqual( - repr(event), - "SnippetEvent(callback_id: myCallbackId, name: onXyzEvent, " - "creation_time: 12345678, data: {'foo': 'bar'})") + def test_basic(self): + """Verifies that an event object can be created and logged properly. + """ + event = snippet_event.SnippetEvent(MOCK_CALLBACK_ID, MOCK_EVENT_NAME, + MOCK_CREATION_TIME, MOCK_DATA) + self.assertEqual( + repr(event), + "SnippetEvent(callback_id: myCallbackId, name: onXyzEvent, " + "creation_time: 12345678, data: {'foo': 'bar'})") if __name__ == "__main__": - unittest.main() + unittest.main() |