# Copyright 2014 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
#    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 copy

from tempest.lib import auth
from tempest.lib import exceptions
from tempest.lib.services.identity.v2 import token_client as v2_client
from tempest.lib.services.identity.v3 import token_client as v3_client
from tempest.tests import base
from tempest.tests.lib import fake_identity


class CredentialsTests(base.TestCase):
    attributes = {}
    credentials_class = auth.Credentials

    def _get_credentials(self, attributes=None):
        if attributes is None:
            attributes = self.attributes
        return self.credentials_class(**attributes)

    def _check(self, credentials, credentials_class, filled):
        # Check the right version of credentials has been returned
        self.assertIsInstance(credentials, credentials_class)
        # Check the id attributes are filled in
        # NOTE(andreaf) project_* attributes are accepted as input but
        # never set on the credentials object
        attributes = [x for x in credentials.ATTRIBUTES if (
            '_id' in x and x != 'domain_id' and x != 'project_id')]
        for attr in attributes:
            if filled:
                self.assertIsNotNone(getattr(credentials, attr))
            else:
                self.assertIsNone(getattr(credentials, attr))

    def test_create(self):
        creds = self._get_credentials()
        self.assertEqual(self.attributes, creds._initial)

    def test_create_invalid_attr(self):
        self.assertRaises(exceptions.InvalidCredentials,
                          self._get_credentials,
                          attributes=dict(invalid='fake'))

    def test_is_valid(self):
        creds = self._get_credentials()
        self.assertRaises(NotImplementedError, creds.is_valid)


class KeystoneV2CredentialsTests(CredentialsTests):
    attributes = {
        'username': 'fake_username',
        'password': 'fake_password',
        'tenant_name': 'fake_tenant_name'
    }

    identity_response = fake_identity._fake_v2_response
    credentials_class = auth.KeystoneV2Credentials
    tokenclient_class = v2_client.TokenClient
    identity_version = 'v2'

    def setUp(self):
        super(KeystoneV2CredentialsTests, self).setUp()
        self.patchobject(self.tokenclient_class, 'raw_request',
                         self.identity_response)

    def _verify_credentials(self, credentials_class, creds_dict, filled=True):
        creds = auth.get_credentials(fake_identity.FAKE_AUTH_URL,
                                     fill_in=filled,
                                     identity_version=self.identity_version,
                                     **creds_dict)
        self._check(creds, credentials_class, filled)

    def test_get_credentials(self):
        self._verify_credentials(credentials_class=self.credentials_class,
                                 creds_dict=self.attributes)

    def test_get_credentials_not_filled(self):
        self._verify_credentials(credentials_class=self.credentials_class,
                                 creds_dict=self.attributes,
                                 filled=False)

    def test_is_valid(self):
        creds = self._get_credentials()
        self.assertTrue(creds.is_valid())

    def _test_is_not_valid(self, ignore_key):
        creds = self._get_credentials()
        for attr in self.attributes:
            if attr == ignore_key:
                continue
            temp_attr = getattr(creds, attr)
            delattr(creds, attr)
            self.assertFalse(creds.is_valid(),
                             "Credentials should be invalid without %s" % attr)
            setattr(creds, attr, temp_attr)

    def test_is_not_valid(self):
        # NOTE(mtreinish): A KeystoneV2 credential object is valid without
        # a tenant_name. So skip that check. See tempest.auth for the valid
        # credential requirements
        self._test_is_not_valid('tenant_name')

    def test_reset_all_attributes(self):
        creds = self._get_credentials()
        initial_creds = copy.deepcopy(creds)
        set_attr = creds.__dict__.keys()
        missing_attr = set(creds.ATTRIBUTES).difference(set_attr)
        # Set all unset attributes, then reset
        for attr in missing_attr:
            setattr(creds, attr, 'fake' + attr)
        creds.reset()
        # Check reset credentials are same as initial ones
        self.assertEqual(creds, initial_creds)

    def test_reset_single_attribute(self):
        creds = self._get_credentials()
        initial_creds = copy.deepcopy(creds)
        set_attr = creds.__dict__.keys()
        missing_attr = set(creds.ATTRIBUTES).difference(set_attr)
        # Set one unset attributes, then reset
        for attr in missing_attr:
            setattr(creds, attr, 'fake' + attr)
            creds.reset()
            # Check reset credentials are same as initial ones
            self.assertEqual(creds, initial_creds)


class KeystoneV3CredentialsTests(KeystoneV2CredentialsTests):
    attributes = {
        'username': 'fake_username',
        'password': 'fake_password',
        'project_name': 'fake_project_name',
        'user_domain_name': 'fake_domain_name'
    }

    credentials_class = auth.KeystoneV3Credentials
    identity_response = fake_identity._fake_v3_response
    tokenclient_class = v3_client.V3TokenClient
    identity_version = 'v3'

    def test_is_not_valid(self):
        # NOTE(mtreinish) For a Keystone V3 credential object a project name
        # is not required to be valid, so we skip that check. See tempest.auth
        # for the valid credential requirements
        self._test_is_not_valid('project_name')

    def test_synced_attributes(self):
        attributes = self.attributes
        # Create V3 credentials with tenant instead of project, and user_domain
        for attr in ['project_id', 'user_domain_id']:
            attributes[attr] = 'fake_' + attr
        creds = self._get_credentials(attributes)
        self.assertEqual(creds.project_name, creds.tenant_name)
        self.assertEqual(creds.project_id, creds.tenant_id)
        self.assertEqual(creds.user_domain_name, creds.project_domain_name)
        self.assertEqual(creds.user_domain_id, creds.project_domain_id)
        # Replace user_domain with project_domain
        del attributes['user_domain_name']
        del attributes['user_domain_id']
        del attributes['project_name']
        del attributes['project_id']
        for attr in ['project_domain_name', 'project_domain_id',
                     'tenant_name', 'tenant_id']:
            attributes[attr] = 'fake_' + attr
        self.assertEqual(creds.tenant_name, creds.project_name)
        self.assertEqual(creds.tenant_id, creds.project_id)
        self.assertEqual(creds.project_domain_name, creds.user_domain_name)
        self.assertEqual(creds.project_domain_id, creds.user_domain_id)
