blob: 83148ca85ecc0d284893444b70b0d16bf93544f7 [file] [log] [blame]
# Copyright 2018 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.
"""Unit tests for Mobly's ServiceManager."""
import mock
import sys
from future.tests.base import unittest
from mobly import expects
from mobly.controllers.android_device_lib import service_manager
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()
@property
def is_alive(self):
return self._alive
def start(self, configs=None):
self.start_func(configs)
self._alive = True
def stop(self):
self.stop_func()
self._alive = False
def pause(self):
self.pause_func()
self._alive = False
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'])
if __name__ == '__main__':
unittest.main()