# Copyright 2014 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 oslo_serialization import jsonutils

from nova.api.openstack import api_version_request as api_version
from nova import test
from nova.tests.unit.api.openstack.compute import microversions
from nova.tests.unit.api.openstack import fakes


class LegacyMicroversionsTest(test.NoDBTestCase):

    header_name = 'X-OpenStack-Nova-API-Version'

    def setUp(self):
        super(LegacyMicroversionsTest, self).setUp()
        self.app = fakes.wsgi_app_v21(custom_routes=microversions.ROUTES)

    def _test_microversions(self, app, req, ret_code, ret_header=None):
        req.environ['CONTENT_TYPE'] = "application/json"

        res = req.get_response(app)
        self.assertEqual(ret_code, res.status_int)
        if ret_header:
            if 'nova' not in self.header_name.lower():
                ret_header = 'compute %s' % ret_header
            self.assertEqual(ret_header,
                             res.headers[self.header_name])
        return res

    def _make_header(self, req_header):
        if 'nova' in self.header_name.lower():
            headers = {self.header_name: req_header}
        else:
            headers = {self.header_name: 'compute %s' % req_header}
        return headers

    def test_microversions_no_header(self):
        req = fakes.HTTPRequest.blank(
                '/v2/%s/microversions' % fakes.FAKE_PROJECT_ID,
                method='GET')
        res = req.get_response(self.app)
        self.assertEqual(200, res.status_int)
        resp_json = jsonutils.loads(res.body)
        self.assertEqual('val', resp_json['param'])

    def test_microversions_return_header(self):
        req = fakes.HTTPRequest.blank(
                '/v2/%s/microversions' % fakes.FAKE_PROJECT_ID)
        res = req.get_response(self.app)
        self.assertEqual(200, res.status_int)
        resp_json = jsonutils.loads(res.body)
        self.assertEqual('val', resp_json['param'])
        if 'nova' in self.header_name.lower():
            self.assertEqual("2.1", res.headers[self.header_name])
        else:
            self.assertEqual("compute 2.1", res.headers[self.header_name])
        self.assertIn(self.header_name, res.headers.getall('Vary'))

    @mock.patch("nova.api.openstack.api_version_request.max_api_version")
    def test_microversions_return_header_non_default(self,
                                                     mock_maxver):
        mock_maxver.return_value = api_version.APIVersionRequest("2.3")

        req = fakes.HTTPRequest.blank(
                '/v2/%s/microversions' % fakes.FAKE_PROJECT_ID)
        req.headers = self._make_header('2.3')
        res = req.get_response(self.app)
        self.assertEqual(200, res.status_int)
        resp_json = jsonutils.loads(res.body)
        self.assertEqual('val2', resp_json['param'])
        if 'nova' in self.header_name.lower():
            self.assertEqual("2.3", res.headers[self.header_name])
        else:
            self.assertEqual("compute 2.3", res.headers[self.header_name])
        self.assertIn(self.header_name, res.headers.getall('Vary'))

    @mock.patch("nova.api.openstack.api_version_request.max_api_version")
    def test_microversions_return_header_fault(self, mock_maxver):
        mock_maxver.return_value = api_version.APIVersionRequest("3.0")

        req = fakes.HTTPRequest.blank(
                '/v2/%s/microversions' % fakes.FAKE_PROJECT_ID)
        req.headers = self._make_header('3.0')
        res = req.get_response(self.app)
        self.assertEqual(400, res.status_int)