# Copyright 2016 IBM Corp.
#
#    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 mock

from tempest import clients
from tempest.common import credentials_factory as credentials
from tempest.common import fixed_network
from tempest import config
from tempest import test
from tempest.tests import base
from tempest.tests import fake_config


class TestBaseTestCase(base.TestCase):
    def setUp(self):
        super(TestBaseTestCase, self).setUp()
        self.useFixture(fake_config.ConfigFixture())
        self.fixed_network_name = 'fixed-net'
        config.CONF.compute.fixed_network_name = self.fixed_network_name
        config.CONF.service_available.neutron = True

    @mock.patch.object(test.BaseTestCase, 'get_client_manager')
    @mock.patch.object(test.BaseTestCase, '_get_credentials_provider')
    @mock.patch.object(fixed_network, 'get_tenant_network')
    def test_get_tenant_network(self, mock_gtn, mock_gprov, mock_gcm):
        net_client = mock.Mock()
        mock_prov = mock.Mock()
        mock_gcm.return_value.compute_networks_client = net_client
        mock_gprov.return_value = mock_prov

        test.BaseTestCase.get_tenant_network()

        mock_gcm.assert_called_once_with(credential_type='primary')
        mock_gprov.assert_called_once_with()
        mock_gtn.assert_called_once_with(mock_prov, net_client,
                                         self.fixed_network_name)

    @mock.patch.object(test.BaseTestCase, 'get_client_manager')
    @mock.patch.object(test.BaseTestCase, '_get_credentials_provider')
    @mock.patch.object(fixed_network, 'get_tenant_network')
    @mock.patch.object(test.BaseTestCase, 'get_identity_version')
    @mock.patch.object(credentials, 'is_admin_available')
    @mock.patch.object(clients, 'Manager')
    def test_get_tenant_network_with_nova_net(self, mock_man, mock_iaa,
                                              mock_giv, mock_gtn, mock_gcp,
                                              mock_gcm):
        config.CONF.service_available.neutron = False
        mock_prov = mock.Mock()
        mock_admin_man = mock.Mock()
        mock_iaa.return_value = True
        mock_gcp.return_value = mock_prov
        mock_man.return_value = mock_admin_man

        test.BaseTestCase.get_tenant_network()

        mock_man.assert_called_once_with(
            mock_prov.get_admin_creds.return_value)
        mock_iaa.assert_called_once_with(
            identity_version=mock_giv.return_value)
        mock_gcp.assert_called_once_with()
        mock_gtn.assert_called_once_with(
            mock_prov, mock_admin_man.compute_networks_client,
            self.fixed_network_name)

    @mock.patch.object(test.BaseTestCase, 'get_client_manager')
    @mock.patch.object(test.BaseTestCase, '_get_credentials_provider')
    @mock.patch.object(fixed_network, 'get_tenant_network')
    def test_get_tenant_network_with_alt_creds(self, mock_gtn, mock_gprov,
                                               mock_gcm):
        net_client = mock.Mock()
        mock_prov = mock.Mock()
        mock_gcm.return_value.compute_networks_client = net_client
        mock_gprov.return_value = mock_prov

        test.BaseTestCase.get_tenant_network(credentials_type='alt')

        mock_gcm.assert_called_once_with(credential_type='alt')
        mock_gprov.assert_called_once_with()
        mock_gtn.assert_called_once_with(mock_prov, net_client,
                                         self.fixed_network_name)

    @mock.patch.object(test.BaseTestCase, 'get_client_manager')
    @mock.patch.object(test.BaseTestCase, '_get_credentials_provider')
    @mock.patch.object(fixed_network, 'get_tenant_network')
    def test_get_tenant_network_with_role_creds(self, mock_gtn, mock_gprov,
                                                mock_gcm):
        net_client = mock.Mock()
        mock_prov = mock.Mock()
        mock_gcm.return_value.compute_networks_client = net_client
        mock_gprov.return_value = mock_prov
        creds = ['foo_type', 'role1']

        test.BaseTestCase.get_tenant_network(credentials_type=creds)

        mock_gcm.assert_called_once_with(roles=['role1'])
        mock_gprov.assert_called_once_with()
        mock_gtn.assert_called_once_with(mock_prov, net_client,
                                         self.fixed_network_name)
