# Copyright 2017 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest
from unittest import mock

from mobly.controllers.android_device_lib import adb
from mobly.controllers.android_device_lib import jsonrpc_client_base
from mobly.controllers.android_device_lib import snippet_client
from tests.lib import jsonrpc_client_test_base
from tests.lib import mock_android_device

MOCK_PACKAGE_NAME = 'some.package.name'
MOCK_MISSING_PACKAGE_NAME = 'not.installed'
JSONRPC_BASE_CLASS = (
    'mobly.controllers.android_device_lib.jsonrpc_client_base.JsonRpcClientBase'
)
MOCK_USER_ID = 0


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.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)

  def test_snippet_stop_app_raises(self):
    adb_proxy = mock.MagicMock()
    adb_proxy.shell.return_value = b'OK (0 tests)'
    client = self._make_client(adb_proxy)
    client.host_port = 1
    client._conn = mock.MagicMock()
    # Explicitly making the second side_effect noop to avoid uncaught exception
    # when `__del__` is called after the test is done, which triggers
    # `disconnect`.
    client._conn.close.side_effect = [Exception('ha'), None]
    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.utils.stop_standing_subprocess')
  def test_snippet_stop_app_stops_event_client(
      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)
    event_client = snippet_client.SnippetClient(
        package=MOCK_PACKAGE_NAME, ad=client._ad
    )
    client._event_client = event_client
    event_client_conn = mock.Mock()
    event_client._conn = event_client_conn

    client.stop_app()
    self.assertFalse(client.is_alive)
    event_client_conn.close.assert_called_once()
    self.assertIsNone(client._event_client)
    self.assertIsNone(event_client._conn)

  @mock.patch('socket.create_connection')
  @mock.patch('mobly.utils.stop_standing_subprocess')
  def test_snippet_stop_app_stops_event_client_without_connection(
      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)
    event_client = snippet_client.SnippetClient(
        package=MOCK_PACKAGE_NAME, ad=client._ad
    )
    client._event_client = event_client
    event_client._conn = None

    client.stop_app()
    self.assertFalse(client.is_alive)
    self.assertIsNone(client._event_client)
    self.assertIsNone(event_client._conn)

  @mock.patch('socket.create_connection')
  @mock.patch('mobly.utils.stop_standing_subprocess')
  def test_snippet_stop_app_without_event_client(
      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._event_client = None

    client.stop_app()
    self.assertFalse(client.is_alive)
    self.assertIsNone(client._event_client)

  @mock.patch('socket.create_connection')
  @mock.patch('mobly.utils.stop_standing_subprocess')
  @mock.patch.object(snippet_client.SnippetClient, 'connect')
  def test_event_client_does_not_stop_port_forwarding(
      self, mock_stop_standing_subprocess, mock_create_connection, mock_connect
  ):
    adb_proxy = mock.MagicMock()
    adb_proxy.shell.return_value = b'OK (0 tests)'
    client = self._make_client(adb_proxy)
    client.host_port = 12345
    client.device_port = 67890

    event_client = client._start_event_client()
    # Mock adb proxy of event client to validate forward call
    event_client._ad = mock.MagicMock()
    event_client._adb = event_client._ad.adb
    client._event_client = event_client

    # Verify that neither the stop process nor the deconstructor is trying to
    # stop the port forwarding
    client.stop_app()
    event_client.__del__()

    event_client._adb.forward.assert_not_called()

  @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 = mock.MagicMock()
    client._adb.shell.return_value = b'setsid'
    client._adb.current_user_id = MOCK_USER_ID
    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('builtins.print')
  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('builtins.print')
  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()
