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