# 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()
