# Copyright 2016 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 io
import logging
import mock
import os
import re
import shutil
import tempfile
import yaml
from future.tests.base import unittest

from mobly import config_parser
from mobly import records
from mobly import signals
from mobly import test_runner

from tests.lib import mock_android_device
from tests.lib import mock_controller
from tests.lib import integration_test
from tests.lib import integration2_test
from tests.lib import integration3_test
from tests.lib import multiple_subclasses_module


class TestRunnerTest(unittest.TestCase):
  """This test class has unit tests for the implementation of everything
  under mobly.test_runner.
  """

  def setUp(self):
    self.tmp_dir = tempfile.mkdtemp()
    self.base_mock_test_config = config_parser.TestRunConfig()
    self.base_mock_test_config.testbed_name = 'SampleTestBed'
    self.base_mock_test_config.controller_configs = {}
    self.base_mock_test_config.user_params = {
      'icecream': 42,
      'extra_param': 'haha'
    }
    self.base_mock_test_config.log_path = self.tmp_dir
    self.log_dir = self.base_mock_test_config.log_path
    self.testbed_name = self.base_mock_test_config.testbed_name

  def tearDown(self):
    shutil.rmtree(self.tmp_dir)

  def _assertControllerInfoEqual(self, info, expected_info_dict):
    self.assertEqual(expected_info_dict['Controller Name'],
             info.controller_name)
    self.assertEqual(expected_info_dict['Test Class'], info.test_class)
    self.assertEqual(expected_info_dict['Controller Info'],
             info.controller_info)

  def test_run_twice(self):
    """Verifies that:
    1. Repeated run works properly.
    2. The original configuration is not altered if a test controller
       module modifies configuration.
    """
    mock_test_config = self.base_mock_test_config.copy()
    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
    my_config = [{
      'serial': 'xxxx',
      'magic': 'Magic1'
    }, {
      'serial': 'xxxx',
      'magic': 'Magic2'
    }]
    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
    with tr.mobly_logger():
      tr.add_test_class(mock_test_config,
                integration_test.IntegrationTest)
      tr.run()
    self.assertTrue(
      mock_test_config.controller_configs[mock_ctrlr_config_name][0])
    with tr.mobly_logger():
      tr.run()
    results = tr.results.summary_dict()
    self.assertEqual(results['Requested'], 2)
    self.assertEqual(results['Executed'], 2)
    self.assertEqual(results['Passed'], 2)
    expected_info_dict = {
      'Controller Info': [{
        'MyMagic': {
          'magic': 'Magic1'
        }
      }, {
        'MyMagic': {
          'magic': 'Magic2'
        }
      }],
      'Controller Name':
      'MagicDevice',
      'Test Class':
      'IntegrationTest',
    }
    self._assertControllerInfoEqual(tr.results.controller_info[0],
                    expected_info_dict)
    self._assertControllerInfoEqual(tr.results.controller_info[1],
                    expected_info_dict)
    self.assertNotEqual(tr.results.controller_info[0],
              tr.results.controller_info[1])

  def test_summary_file_entries(self):
    """Verifies the output summary's file format.

    This focuses on the format of the file instead of the content of
    entries, which is covered in base_test_test.
    """
    mock_test_config = self.base_mock_test_config.copy()
    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
    my_config = [{
      'serial': 'xxxx',
      'magic': 'Magic1'
    }, {
      'serial': 'xxxx',
      'magic': 'Magic2'
    }]
    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
    with tr.mobly_logger():
      tr.add_test_class(mock_test_config,
                integration_test.IntegrationTest)
      tr.run()
    summary_path = os.path.join(logging.root_output_path,
                  records.OUTPUT_FILE_SUMMARY)
    with io.open(summary_path, 'r', encoding='utf-8') as f:
      summary_entries = list(yaml.safe_load_all(f))
    self.assertEqual(len(summary_entries), 4)
    # Verify the first entry is the list of test names.
    self.assertEqual(summary_entries[0]['Type'],
             records.TestSummaryEntryType.TEST_NAME_LIST.value)
    self.assertEqual(summary_entries[1]['Type'],
             records.TestSummaryEntryType.RECORD.value)
    self.assertEqual(summary_entries[2]['Type'],
             records.TestSummaryEntryType.CONTROLLER_INFO.value)
    self.assertEqual(summary_entries[3]['Type'],
             records.TestSummaryEntryType.SUMMARY.value)

  def test_run(self):
    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
    self.base_mock_test_config.controller_configs[
      mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = '*'
    with tr.mobly_logger():
      tr.add_test_class(self.base_mock_test_config,
                integration_test.IntegrationTest)
      tr.run()
    results = tr.results.summary_dict()
    self.assertEqual(results['Requested'], 1)
    self.assertEqual(results['Executed'], 1)
    self.assertEqual(results['Passed'], 1)
    self.assertEqual(len(tr.results.executed), 1)
    record = tr.results.executed[0]
    self.assertEqual(record.test_class, 'IntegrationTest')

  def test_run_without_mobly_logger_context(self):
    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
    self.base_mock_test_config.controller_configs[
      mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = '*'
    tr.add_test_class(self.base_mock_test_config,
              integration_test.IntegrationTest)
    tr.run()
    results = tr.results.summary_dict()
    self.assertEqual(results['Requested'], 1)
    self.assertEqual(results['Executed'], 1)
    self.assertEqual(results['Passed'], 1)
    self.assertEqual(len(tr.results.executed), 1)
    record = tr.results.executed[0]
    self.assertEqual(record.test_class, 'IntegrationTest')

  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
        return_value=mock_android_device.MockAdbProxy(1))
  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
        return_value=mock_android_device.MockFastbootProxy(1))
  @mock.patch('mobly.controllers.android_device.list_adb_devices',
        return_value=['1'])
  @mock.patch('mobly.controllers.android_device.get_all_instances',
        return_value=mock_android_device.get_mock_ads(1))
  def test_run_two_test_classes(self, mock_get_all, mock_list_adb,
                  mock_fastboot, mock_adb):
    """Verifies that running more than one test class in one test run works
    properly.

    This requires using a built-in controller module. Using AndroidDevice
    module since it has all the mocks needed already.
    """
    mock_test_config = self.base_mock_test_config.copy()
    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
    my_config = [{
      'serial': 'xxxx',
      'magic': 'Magic1'
    }, {
      'serial': 'xxxx',
      'magic': 'Magic2'
    }]
    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
    mock_test_config.controller_configs['AndroidDevice'] = [{
      'serial': '1'
    }]
    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
    with tr.mobly_logger():
      tr.add_test_class(mock_test_config,
                integration2_test.Integration2Test)
      tr.add_test_class(mock_test_config,
                integration_test.IntegrationTest)
      tr.run()
    results = tr.results.summary_dict()
    self.assertEqual(results['Requested'], 2)
    self.assertEqual(results['Executed'], 2)
    self.assertEqual(results['Passed'], 2)
    self.assertEqual(len(tr.results.executed), 2)
    # Tag of the test class defaults to the class name.
    record1 = tr.results.executed[0]
    record2 = tr.results.executed[1]
    self.assertEqual(record1.test_class, 'Integration2Test')
    self.assertEqual(record2.test_class, 'IntegrationTest')

  def test_run_two_test_classes_different_configs_and_aliases(self):
    """Verifies that running more than one test class in one test run with
    different configs works properly.
    """
    config1 = self.base_mock_test_config.copy()
    config1.controller_configs[
      mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = [{
        'serial': 'xxxx'
      }]
    config2 = config1.copy()
    config2.user_params['icecream'] = 10
    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
    with tr.mobly_logger():
      tr.add_test_class(config1,
                integration_test.IntegrationTest,
                name_suffix='FirstConfig')
      tr.add_test_class(config2,
                integration_test.IntegrationTest,
                name_suffix='SecondConfig')
      tr.run()
    results = tr.results.summary_dict()
    self.assertEqual(results['Requested'], 2)
    self.assertEqual(results['Executed'], 2)
    self.assertEqual(results['Passed'], 1)
    self.assertEqual(results['Failed'], 1)
    self.assertEqual(tr.results.failed[0].details, '10 != 42')
    self.assertEqual(len(tr.results.executed), 2)
    record1 = tr.results.executed[0]
    record2 = tr.results.executed[1]
    self.assertEqual(record1.test_class, 'IntegrationTest_FirstConfig')
    self.assertEqual(record2.test_class, 'IntegrationTest_SecondConfig')

  def test_run_with_abort_all(self):
    mock_test_config = self.base_mock_test_config.copy()
    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
    with tr.mobly_logger():
      tr.add_test_class(mock_test_config,
                integration3_test.Integration3Test)
      with self.assertRaises(signals.TestAbortAll):
        tr.run()
    results = tr.results.summary_dict()
    self.assertEqual(results['Requested'], 1)
    self.assertEqual(results['Executed'], 0)
    self.assertEqual(results['Passed'], 0)
    self.assertEqual(results['Failed'], 0)

  def test_add_test_class_mismatched_log_path(self):
    tr = test_runner.TestRunner('/different/log/dir', self.testbed_name)
    with self.assertRaisesRegex(
        test_runner.Error,
        'TestRunner\'s log folder is "/different/log/dir", but a test '
        r'config with a different log folder \("%s"\) was added.' %
        re.escape(self.log_dir)):
      tr.add_test_class(self.base_mock_test_config,
                integration_test.IntegrationTest)

  def test_add_test_class_mismatched_testbed_name(self):
    tr = test_runner.TestRunner(self.log_dir, 'different_test_bed')
    with self.assertRaisesRegex(
        test_runner.Error,
        'TestRunner\'s test bed is "different_test_bed", but a test '
        r'config with a different test bed \("%s"\) was added.' %
        self.testbed_name):
      tr.add_test_class(self.base_mock_test_config,
                integration_test.IntegrationTest)

  def test_run_no_tests(self):
    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
    with self.assertRaisesRegex(test_runner.Error, 'No tests to execute.'):
      tr.run()

  @mock.patch('mobly.test_runner._find_test_class',
        return_value=type('SampleTest', (), {}))
  @mock.patch('mobly.test_runner.config_parser.load_test_config_file',
        return_value=[config_parser.TestRunConfig()])
  @mock.patch('mobly.test_runner.TestRunner', return_value=mock.MagicMock())
  def test_main_parse_args(self, mock_test_runner, mock_config,
               mock_find_test):
    test_runner.main(['-c', 'some/path/foo.yaml', '-b', 'hello'])
    mock_config.assert_called_with('some/path/foo.yaml', None)

  @mock.patch('mobly.test_runner._find_test_class',
        return_value=integration_test.IntegrationTest)
  @mock.patch('sys.exit')
  def test_main(self, mock_exit, mock_find_test):
    tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
    with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
      f.write(u"""
        TestBeds:
          # A test bed where adb will find Android devices.
          - Name: SampleTestBed
            Controllers:
              MagicDevice: '*'
            TestParams:
              icecream: 42
              extra_param: 'haha'
      """)
    test_runner.main(['-c', tmp_file_path])
    mock_exit.assert_not_called()

  @mock.patch('mobly.test_runner._find_test_class',
        return_value=integration_test.IntegrationTest)
  @mock.patch('sys.exit')
  def test_main_with_failures(self, mock_exit, mock_find_test):
    tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
    with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
      f.write(u"""
        TestBeds:
          # A test bed where adb will find Android devices.
          - Name: SampleTestBed
            Controllers:
              MagicDevice: '*'
      """)
    test_runner.main(['-c', tmp_file_path])
    mock_exit.assert_called_once_with(1)

  def test__find_test_class_when_one_test_class(self):
    with mock.patch.dict('sys.modules', __main__=integration_test):
      test_class = test_runner._find_test_class()
      self.assertEqual(test_class, integration_test.IntegrationTest)

  def test__find_test_class_when_no_test_class(self):
    with self.assertRaises(SystemExit):
      with mock.patch.dict('sys.modules', __main__=mock_controller):
        test_class = test_runner._find_test_class()

  def test__find_test_class_when_multiple_test_classes(self):
    with self.assertRaises(SystemExit):
      with mock.patch.dict('sys.modules',
                 __main__=multiple_subclasses_module):
        test_class = test_runner._find_test_class()

  def test_print_test_names(self):
    mock_test_class = mock.MagicMock()
    mock_cls_instance = mock.MagicMock()
    mock_test_class.return_value = mock_cls_instance
    test_runner._print_test_names(mock_test_class)
    mock_cls_instance.setup_generated_tests.assert_called_once()
    mock_cls_instance.get_existing_test_names.assert_called_once()
    mock_cls_instance._controller_manager.unregister_controllers.assert_called_once(
    )

  def test_print_test_names_with_exception(self):
    mock_test_class = mock.MagicMock()
    mock_cls_instance = mock.MagicMock()
    mock_test_class.return_value = mock_cls_instance
    test_runner._print_test_names(mock_test_class)
    mock_cls_instance.setup_generated_tests.side_effect = Exception(
      'Something went wrong.')
    mock_cls_instance._controller_manager.unregister_controllers.assert_called_once(
    )


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