# Copyright 2021 Google LLC
#
# 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 gdm_manager."""
import unittest
from unittest import mock

import gazoo_device
from gazoo_device import errors as gdm_errors

from local_agent import errors as agent_errors
from local_agent.translation_layer import gdm_manager


####################### Fake data for unit test #############################
_FAKE_DEVICE_TYPE = 'fake-device-type'
_FAKE_DEVICE_ID = 'fake-device-id'
_FAKE_DEVICE_ID2 = 'fake-device-id2'
_FAKE_DETECTION_RESULT = {
    'efr32-3453': {
        'persistent': {'device_type': 'efr32', 'serial_number': '000440173453'},
        },
    'nrf52840-1234': {
        'persistent': {'device_type': 'nrf52849', 'serial_number': '1234'},
        },
}
_FAKE_DEVICE_CAPABILITIES = ['flash_build', 'switchboard']
_FAKE_ERROR_MSG = 'error'
##############################################################################


class GdmManagerTest(unittest.TestCase):
    """Unit tests for gdm_manager module."""

    def setUp(self):
        super().setUp()
        self.mgr = gdm_manager.GdmManager(mock.Mock())

    @mock.patch.object(gazoo_device.Manager, 'get_supported_device_capabilities')
    @mock.patch.object(gazoo_device.Manager, 'is_device_connected')
    @mock.patch.object(gazoo_device.Manager, 'get_devices')
    @mock.patch.object(gazoo_device.Manager, 'detect')
    def test_01_detect_devices(
        self,
        mock_detect,
        mock_get_devices,
        mock_is_connect,
        mock_get_capabilities):
        """Verifies detect_devices on success."""
        mock_get_devices.return_value = _FAKE_DETECTION_RESULT
        mock_is_connect.side_effect = [True, False]
        mock_get_capabilities.return_value = _FAKE_DEVICE_CAPABILITIES
        device_statuses = self.mgr.detect_devices()
        expected_statuses = [
            {
                'deviceId': 'efr32-3453',
                'serialNumber': '000440173453',
                'deviceType': 'efr32',
                'capabilities': ['flash_build', 'switchboard'],
            },
        ]
        self.assertEqual(expected_statuses, device_statuses)
        mock_detect.assert_called_once_with(
            force_overwrite=True, log_directory='/tmp')
        self.assertEqual(2, mock_is_connect.call_count)
        self.assertEqual(1, mock_get_capabilities.call_count)

    @mock.patch.object(gazoo_device.Manager, 'create_device')
    def test_02_create_devices_on_success(self, mock_create):
        """Verifies create_devices on success."""
        identifiers = [_FAKE_DEVICE_ID, _FAKE_DEVICE_ID2]
        self.mgr.create_devices(identifiers)
        mock_create.assert_called_with(
            identifier=_FAKE_DEVICE_ID2, log_directory=None)
        self.assertEqual(2, mock_create.call_count)

    @mock.patch.object(gazoo_device.Manager, 'is_device_connected')
    def test_03_check_device_connected_on_success(
        self, mock_is_device_connected):
        """Verifies check_device_connected succeeds when device connected."""
        mock_is_device_connected.return_value = True
        self.mgr.check_device_connected(_FAKE_DEVICE_ID)
        self.assertEqual(1, mock_is_device_connected.call_count)

    @mock.patch.object(gazoo_device.Manager, 'is_device_connected')
    def test_03_check_device_connected_raises_when_disconnected(
        self, mock_is_device_connected):
        """Verifies check_device_connected raises when device disconnected."""
        mock_is_device_connected.return_value = False
        with self.assertRaises(agent_errors.DeviceNotConnectedError):
            self.mgr.check_device_connected(_FAKE_DEVICE_ID)
        self.assertEqual(1, mock_is_device_connected.call_count)

    @mock.patch.object(gazoo_device.Manager, 'is_device_connected')
    def test_03_check_device_connected_raises_unexpected_error(
        self, mock_is_device_connected):
        """
        Verifies check_device_connected raises when device operation has error.
        """
        mock_is_device_connected.side_effect = (
            gdm_errors.DeviceError(_FAKE_ERROR_MSG))
        with self.assertRaisesRegex(gdm_errors.DeviceError, _FAKE_ERROR_MSG):
            self.mgr.check_device_connected(_FAKE_DEVICE_ID)
        self.assertEqual(1, mock_is_device_connected.call_count)

    @mock.patch.object(gazoo_device.Manager, 'get_open_device')
    @mock.patch.object(gazoo_device.Manager, 'get_open_device_names')
    def test_04_get_device_instance_on_success(
        self, mock_get_open_device_names, mock_get_open_device):
        """Verifies get_device_instance on success."""
        mock_get_open_device_names.return_value = [_FAKE_DEVICE_ID]
        self.mgr.get_device_instance(_FAKE_DEVICE_ID)
        self.assertEqual(1, mock_get_open_device_names.call_count)
        mock_get_open_device.assert_called_once_with(_FAKE_DEVICE_ID)

    @mock.patch.object(gazoo_device.Manager, 'get_open_device_names')
    def test_04_get_device_instance_failure_because_device_not_open(
        self, mock_get_open_device_names):
        """Verifies get_device_instance on failure."""
        mock_get_open_device_names.return_value = []
        error_msg = f'{_FAKE_DEVICE_ID} is not open'
        with self.assertRaisesRegex(agent_errors.DeviceNotOpenError, error_msg):
            self.mgr.get_device_instance(_FAKE_DEVICE_ID)

    @mock.patch.object(gazoo_device.Manager, 'get_open_device')
    @mock.patch.object(gazoo_device.Manager, 'get_open_device_names')
    def test_05_get_device_type_on_success(
        self, mock_get_names, mock_get_device):
        """Verifies _get_device_type on success."""
        mock_get_names.return_value = {_FAKE_DEVICE_ID,}
        mock_get_device.return_value.device_type = _FAKE_DEVICE_TYPE
        dut_type = self.mgr.get_device_type(_FAKE_DEVICE_ID)
        self.assertEqual(_FAKE_DEVICE_TYPE, dut_type)
        self.assertEqual(1, mock_get_names.call_count)
        self.assertEqual(1, mock_get_device.call_count)

    @mock.patch.object(gazoo_device.Manager, 'get_open_device_names')
    def test_05_get_device_type_on_failure_not_open(self, mock_get_names):
        """Verifies _get_device_type on failure not open."""
        mock_get_names.return_value = []
        error_msg = f'{_FAKE_DEVICE_ID} is not open'
        with self.assertRaisesRegex(agent_errors.DeviceNotOpenError, error_msg):
            self.mgr.get_device_type(_FAKE_DEVICE_ID)

    @mock.patch.object(gazoo_device.Manager, 'close_open_devices')
    def test_06_close_open_devices_on_success(self, mock_close_open_devices):
        """Verifies close_open_devices on success."""
        self.mgr.close_open_devices()
        self.assertEqual(1, mock_close_open_devices.call_count)
