| # 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 controller manager.""" |
| |
| import unittest |
| from unittest import mock |
| |
| from mobly import controller_manager |
| from mobly import signals |
| from tests.lib import mock_controller |
| |
| |
| class ControllerManagerTest(unittest.TestCase): |
| """Unit tests for Mobly's ControllerManager.""" |
| |
| def test_verify_controller_module(self): |
| controller_manager.verify_controller_module(mock_controller) |
| |
| def test_verify_controller_module_null_attr(self): |
| try: |
| tmp = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| mock_controller.MOBLY_CONTROLLER_CONFIG_NAME = None |
| msg = 'Controller interface .* in .* cannot be null.' |
| with self.assertRaisesRegex(signals.ControllerError, msg): |
| controller_manager.verify_controller_module(mock_controller) |
| finally: |
| mock_controller.MOBLY_CONTROLLER_CONFIG_NAME = tmp |
| |
| def test_verify_controller_module_missing_attr(self): |
| try: |
| tmp = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| delattr(mock_controller, 'MOBLY_CONTROLLER_CONFIG_NAME') |
| msg = 'Module .* missing required controller module attribute' |
| with self.assertRaisesRegex(signals.ControllerError, msg): |
| controller_manager.verify_controller_module(mock_controller) |
| finally: |
| setattr(mock_controller, 'MOBLY_CONTROLLER_CONFIG_NAME', tmp) |
| |
| def test_register_controller_no_config(self): |
| c_manager = controller_manager.ControllerManager('SomeClass', {}) |
| with self.assertRaisesRegex(signals.ControllerError, |
| 'No corresponding config found for'): |
| c_manager.register_controller(mock_controller) |
| |
| def test_register_controller_no_config_for_not_required(self): |
| c_manager = controller_manager.ControllerManager('SomeClass', {}) |
| self.assertIsNone( |
| c_manager.register_controller(mock_controller, required=False)) |
| |
| def test_register_controller_dup_register(self): |
| """Verifies correctness of registration, internal tally of controllers |
| objects, and the right error happen when a controller module is |
| registered twice. |
| """ |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| c_manager.register_controller(mock_controller) |
| registered_name = 'mock_controller' |
| self.assertTrue(registered_name in c_manager._controller_objects) |
| mock_ctrlrs = c_manager._controller_objects[registered_name] |
| self.assertEqual(mock_ctrlrs[0].magic, 'magic1') |
| self.assertEqual(mock_ctrlrs[1].magic, 'magic2') |
| self.assertTrue(c_manager._controller_modules[registered_name]) |
| expected_msg = 'Controller module .* has already been registered.' |
| with self.assertRaisesRegex(signals.ControllerError, expected_msg): |
| c_manager.register_controller(mock_controller) |
| |
| def test_register_controller_return_value(self): |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| magic_devices = c_manager.register_controller(mock_controller) |
| self.assertEqual(magic_devices[0].magic, 'magic1') |
| self.assertEqual(magic_devices[1].magic, 'magic2') |
| |
| def test_register_controller_change_return_value(self): |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| magic_devices = c_manager.register_controller(mock_controller) |
| magic1 = magic_devices.pop(0) |
| self.assertIs(magic1, c_manager._controller_objects['mock_controller'][0]) |
| self.assertEqual(len(c_manager._controller_objects['mock_controller']), 2) |
| |
| def test_register_controller_less_than_min_number(self): |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| expected_msg = 'Expected to get at least 3 controller objects, got 2.' |
| with self.assertRaisesRegex(signals.ControllerError, expected_msg): |
| c_manager.register_controller(mock_controller, min_number=3) |
| |
| @mock.patch('yaml.dump', side_effect=TypeError('ha')) |
| def test_get_controller_info_record_not_serializable(self, _): |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| c_manager.register_controller(mock_controller) |
| record = c_manager.get_controller_info_records()[0] |
| actual_controller_info = record.controller_info |
| self.assertEqual(actual_controller_info, |
| "[{'MyMagic': 'magic1'}, {'MyMagic': 'magic2'}]") |
| |
| def test_controller_record_exists_without_get_info(self): |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| get_info = getattr(mock_controller, 'get_info') |
| delattr(mock_controller, 'get_info') |
| try: |
| c_manager.register_controller(mock_controller) |
| record = c_manager.get_controller_info_records()[0] |
| self.assertIsNone(record.controller_info) |
| self.assertEqual(record.test_class, 'SomeClass') |
| self.assertEqual(record.controller_name, 'MagicDevice') |
| finally: |
| setattr(mock_controller, 'get_info', get_info) |
| |
| @mock.patch('tests.lib.mock_controller.get_info') |
| def test_get_controller_info_records_empty(self, mock_get_info_func): |
| mock_get_info_func.return_value = None |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| c_manager.register_controller(mock_controller) |
| record = c_manager.get_controller_info_records()[0] |
| self.assertIsNone(record.controller_info) |
| self.assertEqual(record.test_class, 'SomeClass') |
| self.assertEqual(record.controller_name, 'MagicDevice') |
| |
| @mock.patch('mobly.expects._ExpectErrorRecorder.add_error') |
| @mock.patch('tests.lib.mock_controller.get_info') |
| def test_get_controller_info_records_error(self, mock_get_info_func, |
| mock_add_error): |
| mock_get_info_func.side_effect = Exception('Record info failed.') |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| c_manager.register_controller(mock_controller) |
| self.assertFalse(c_manager.get_controller_info_records()) |
| mock_add_error.assert_called_once() |
| error_record = mock_add_error.call_args[0][0] |
| self.assertIn('Record info failed.', error_record.stacktrace) |
| |
| def test_get_controller_info_records(self): |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| c_manager.register_controller(mock_controller) |
| record = c_manager.get_controller_info_records()[0] |
| record_dict = record.to_dict() |
| record_dict.pop('Timestamp') |
| self.assertEqual( |
| record_dict, { |
| 'Controller Info': [{ |
| 'MyMagic': 'magic1' |
| }, { |
| 'MyMagic': 'magic2' |
| }], |
| 'Controller Name': 'MagicDevice', |
| 'Test Class': 'SomeClass' |
| }) |
| |
| def test_get_controller_info_without_registration(self): |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| self.assertFalse(c_manager.get_controller_info_records()) |
| |
| @mock.patch('tests.lib.mock_controller.destroy') |
| def test_unregister_controller(self, mock_destroy_func): |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| objects = c_manager.register_controller(mock_controller) |
| c_manager.unregister_controllers() |
| mock_destroy_func.assert_called_once_with(objects) |
| self.assertFalse(c_manager._controller_objects) |
| self.assertFalse(c_manager._controller_modules) |
| |
| @mock.patch('mobly.expects._ExpectErrorRecorder.add_error') |
| @mock.patch('tests.lib.mock_controller.destroy') |
| def test_unregister_controller_error(self, mock_destroy_func, mock_add_error): |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| c_manager.register_controller(mock_controller) |
| mock_destroy_func.side_effect = Exception('Failed in destroy.') |
| c_manager.unregister_controllers() |
| mock_add_error.assert_called_once() |
| error_record = mock_add_error.call_args[0][0] |
| self.assertIn('Failed in destroy.', error_record.stacktrace) |
| self.assertFalse(c_manager._controller_objects) |
| self.assertFalse(c_manager._controller_modules) |
| |
| @mock.patch('tests.lib.mock_controller.destroy') |
| def test_unregister_controller_without_registration(self, mock_destroy_func): |
| mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME |
| controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']} |
| c_manager = controller_manager.ControllerManager('SomeClass', |
| controller_configs) |
| c_manager.unregister_controllers() |
| mock_destroy_func.assert_not_called() |
| self.assertFalse(c_manager._controller_objects) |
| self.assertFalse(c_manager._controller_modules) |
| |
| |
| if __name__ == "__main__": |
| unittest.main() |