Skip to content

Commit

Permalink
Deprecate legacy snippet modules after snippet client v2 migration (g…
Browse files Browse the repository at this point in the history
  • Loading branch information
mhaoli authored Jul 20, 2022
1 parent 98273a2 commit 172d0cb
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 112 deletions.
10 changes: 10 additions & 0 deletions mobly/controllers/android_device_lib/callback_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import time

from mobly.controllers.android_device_lib import snippet_event
from mobly.snippet import errors

logging.warning(
'The module mobly.controllers.android_device_lib.callback_handler is '
'deprecated and will be removed in a future version. Use module '
'mobly.controllers.android_device_lib.callback_handler_v2 instead.')

# The max timeout cannot be larger than the max time the socket waits for a
# response message. Otherwise, the socket would timeout before the Rpc call
# does, leaving both server and client in unknown states.
Expand All @@ -31,6 +37,10 @@
class CallbackHandler:
"""The class used to handle a specific group of callback events.
DEPRECATED: Use
mobly.controllers.android_device_lib.callback_handler_v2.CallbackHandlerV2
instead.
All the events handled by a CallbackHandler are originally triggered by one
async Rpc call. All the events are tagged with a callback_id specific to a
call to an AsyncRpc method defined on the server side.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# limitations under the License.
"""Module for the snippet management service."""
from mobly.controllers.android_device_lib import errors
from mobly.controllers.android_device_lib import snippet_client
from mobly.controllers.android_device_lib import snippet_client_v2
from mobly.controllers.android_device_lib.services import base_service

Expand Down Expand Up @@ -42,34 +41,6 @@ def __init__(self, device, configs=None):
self._is_alive = False
self._snippet_clients = {}
super().__init__(device)
self._use_client_v2_switch = None

# TODO(mhaoli): The client v2 switch is transient, we will remove it after we
# complete the migration from v1 to v2.
def _is_using_client_v2(self):
"""Is this service using snippet client V2.
Do not call this function in the constructor, as this function depends on
the device configuration and the device object will load its configuration
right after constructing the services.
NOTE: This is a transient function when we are migrating the snippet client
from v1 to v2. It will be removed after the migration is completed.
Returns:
A bool for whether this service is using snippet client V2.
"""
if self._use_client_v2_switch is None:
device_dimensions = getattr(self._device, 'dimensions', {})
switch_from_dimension = (device_dimensions.get(_CLIENT_V2_CONFIG_KEY,
'true').lower() == 'true')

switch_from_attribute = (getattr(self._device, _CLIENT_V2_CONFIG_KEY,
'true').lower() == 'true')

self._use_client_v2_switch = (switch_from_dimension and
switch_from_attribute)
return self._use_client_v2_switch

@property
def is_alive(self):
Expand Down Expand Up @@ -112,13 +83,8 @@ def add_snippet_client(self, name, package):
self, 'Snippet package "%s" has already been loaded under name'
' "%s".' % (package, snippet_name))

if self._is_using_client_v2():
client = snippet_client_v2.SnippetClientV2(package=package,
ad=self._device)
client.initialize()
else:
client = snippet_client.SnippetClient(package=package, ad=self._device)
client.start_app_and_connect()
client = snippet_client_v2.SnippetClientV2(package=package, ad=self._device)
client.initialize()
self._snippet_clients[name] = client

def remove_snippet_client(self, name):
Expand All @@ -133,20 +99,14 @@ def remove_snippet_client(self, name):
if name not in self._snippet_clients:
raise Error(self._device, MISSING_SNIPPET_CLIENT_MSG % name)
client = self._snippet_clients.pop(name)
if self._is_using_client_v2():
client.stop()
else:
client.stop_app()
client.stop()

def start(self):
"""Starts all the snippet clients under management."""
for client in self._snippet_clients.values():
if not client.is_alive:
self._device.log.debug('Starting SnippetClient<%s>.', client.package)
if self._is_using_client_v2():
client.initialize()
else:
client.start_app_and_connect()
client.initialize()
else:
self._device.log.debug(
'Not startng SnippetClient<%s> because it is already alive.',
Expand All @@ -157,10 +117,7 @@ def stop(self):
for client in self._snippet_clients.values():
if client.is_alive:
self._device.log.debug('Stopping SnippetClient<%s>.', client.package)
if self._is_using_client_v2():
client.stop()
else:
client.stop_app()
client.stop()
else:
self._device.log.debug(
'Not stopping SnippetClient<%s> because it is not alive.',
Expand All @@ -174,20 +131,14 @@ def pause(self):
"""
for client in self._snippet_clients.values():
self._device.log.debug('Pausing SnippetClient<%s>.', client.package)
if self._is_using_client_v2():
client.close_connection()
else:
client.disconnect()
client.close_connection()

def resume(self):
"""Resumes all paused snippet clients."""
for client in self._snippet_clients.values():
if not client.is_alive:
self._device.log.debug('Resuming SnippetClient<%s>.', client.package)
if self._is_using_client_v2():
client.restore_server_connection()
else:
client.restore_app_connection()
client.restore_server_connection()
else:
self._device.log.debug('Not resuming SnippetClient<%s>.',
client.package)
Expand Down
10 changes: 10 additions & 0 deletions mobly/controllers/android_device_lib/snippet_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.
"""JSON RPC interface to Mobly Snippet Lib."""

import logging
import re
import time

Expand All @@ -22,6 +23,11 @@
from mobly.controllers.android_device_lib import jsonrpc_client_base
from mobly.snippet import errors as snippet_errors

logging.warning('The module mobly.controllers.android_device_lib.snippet_client'
' is deprecated and will be removed in a future version. Use'
' module mobly.controllers.android_device_lib.snippet_client_v2'
' instead.')

_INSTRUMENTATION_RUNNER_PACKAGE = (
'com.google.android.mobly.snippet.SnippetRunner')

Expand Down Expand Up @@ -65,6 +71,10 @@
class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
"""A client for interacting with snippet APKs using Mobly Snippet Lib.
DEPRECATED: Use
mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2
instead.
See superclass documentation for a list of public attributes.
For a description of the launch protocols, see the documentation in
Expand Down
9 changes: 9 additions & 0 deletions mobly/controllers/android_device_lib/snippet_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,18 @@
# 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 logging

logging.warning('The module mobly.controllers.android_device_lib.snippet_event '
'is deprecated and will be removed in a future version. Use '
'module mobly.snippet.callback_event instead.')


def from_dict(event_dict):
"""Create a SnippetEvent object from a dictionary.
DEPRECATED: Use mobly.snippet.callback_event.from_dict instead.
Args:
event_dict: a dictionary representing an event.
Expand All @@ -31,6 +38,8 @@ def from_dict(event_dict):
class SnippetEvent:
"""The class that represents callback events for mobly snippet library.
DEPRECATED: Use mobly.snippet.callback_event.CallbackEvent instead.
Attributes:
callback_id: string, the callback ID associated with the event.
name: string, the name of the event.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class SnippetManagementServiceTest(unittest.TestCase):
def test_empty_manager_start_stop(self):
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
manager.start()
# When no client is registered, manager is never alive.
self.assertFalse(manager.is_alive)
Expand All @@ -39,23 +38,20 @@ def test_get_snippet_client(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
manager.add_snippet_client('foo', MOCK_PACKAGE)
self.assertEqual(manager.get_snippet_client('foo'), mock_client)

@mock.patch(SNIPPET_CLIENT_V2_CLASS_PATH)
def test_get_snippet_client_fail(self, _):
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
self.assertIsNone(manager.get_snippet_client('foo'))

@mock.patch(SNIPPET_CLIENT_V2_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._use_client_v2_switch = True
manager.add_snippet_client('foo', MOCK_PACKAGE)
mock_client.initialize.assert_called_once_with()
manager.stop()
Expand All @@ -70,7 +66,6 @@ def test_stop_with_live_client(self, mock_class):
def test_add_snippet_client_dup_name(self, _):
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
manager.add_snippet_client('foo', MOCK_PACKAGE)
msg = ('.* Name "foo" is already registered with package ".*", it '
'cannot be used again.')
Expand All @@ -83,7 +78,6 @@ def test_add_snippet_client_dup_package(self, mock_class):
mock_client.package = MOCK_PACKAGE
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
manager.add_snippet_client('foo', MOCK_PACKAGE)
msg = ('Snippet package "com.mock.package" has already been loaded '
'under name "foo".')
Expand All @@ -96,7 +90,6 @@ def test_remove_snippet_client(self, mock_class):
mock_class.return_value = mock_client
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
manager.add_snippet_client('foo', MOCK_PACKAGE)
manager.remove_snippet_client('foo')
msg = 'No snippet client is registered with name "foo".'
Expand All @@ -109,7 +102,6 @@ def test_remove_snippet_client(self, mock_class):
mock_class.return_value = mock_client
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
with self.assertRaisesRegex(
snippet_management_service.Error,
'No snippet client is registered with name "foo".'):
Expand All @@ -120,7 +112,6 @@ def test_start_with_live_service(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
manager.add_snippet_client('foo', MOCK_PACKAGE)
mock_client.initialize.reset_mock()
mock_client.is_alive = True
Expand All @@ -136,7 +127,6 @@ def test_pause(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
manager.add_snippet_client('foo', MOCK_PACKAGE)
manager.pause()
mock_client.close_connection.assert_called_once_with()
Expand All @@ -146,7 +136,6 @@ def test_resume_positive_case(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
manager.add_snippet_client('foo', MOCK_PACKAGE)
mock_client.is_alive = False
manager.resume()
Expand All @@ -157,7 +146,6 @@ def test_resume_negative_case(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
manager.add_snippet_client('foo', MOCK_PACKAGE)
mock_client.is_alive = True
manager.resume()
Expand All @@ -169,54 +157,10 @@ def test_attribute_access(self, mock_class):
mock_class.return_value = mock_client
manager = snippet_management_service.SnippetManagementService(
mock.MagicMock())
manager._use_client_v2_switch = True
manager.add_snippet_client('foo', MOCK_PACKAGE)
manager.foo.ha('param')
mock_client.ha.assert_called_once_with('param')

# TODO(mhaoli): The client v2 switch is transient, we will remove related
# tests after we complete the migration from v1 to v2.
def test_client_v2_switch_default_value(self):
self._set_device_attribute_and_check_client_v2_switch(
expect_switch_value=True)

def test_client_v2_switch_when_set_device_dimension_to_false(self):
self._set_device_attribute_and_check_client_v2_switch(
expect_switch_value=False,
dimensions={'use_mobly_snippet_client_v2': 'false'})

def test_client_v2_switch_when_set_device_dimension_to_true(self):
self._set_device_attribute_and_check_client_v2_switch(
expect_switch_value=True,
dimensions={'use_mobly_snippet_client_v2': 'true'})

def test_client_v2_switch_when_set_device_attribute_to_false(self):
self._set_device_attribute_and_check_client_v2_switch(
expect_switch_value=False, use_mobly_snippet_client_v2='false')

def test_client_v2_switch_when_set_device_attribute_to_true(self):
self._set_device_attribute_and_check_client_v2_switch(
expect_switch_value=True, use_mobly_snippet_client_v2='true')

def test_client_v2_switch_when_both_attribute_and_dimension_are_false(self):
self._set_device_attribute_and_check_client_v2_switch(
expect_switch_value=False,
use_mobly_snippet_client_v2='false',
dimensions={'use_mobly_snippet_client_v2': 'false'})

def test_client_v2_switch_when_both_attribute_and_dimension_are_true(self):
self._set_device_attribute_and_check_client_v2_switch(
expect_switch_value=True,
use_mobly_snippet_client_v2='true',
dimensions={'use_mobly_snippet_client_v2': 'true'})

def _set_device_attribute_and_check_client_v2_switch(self,
expect_switch_value,
**device_attributes):
mock_device = mock.MagicMock(**device_attributes, spec=['log'])
manager = snippet_management_service.SnippetManagementService(mock_device)
self.assertEqual(expect_switch_value, manager._is_using_client_v2())


if __name__ == '__main__':
unittest.main()

0 comments on commit 172d0cb

Please sign in to comment.