Ken'ichi Ohmichi | 4d237e7 | 2015-11-05 06:32:33 +0000 | [diff] [blame] | 1 | # Copyright 2015 NEC Corporation. All rights reserved. |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 4 | # not use this file except in compliance with the License. You may obtain |
| 5 | # a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 12 | # License for the specific language governing permissions and limitations |
| 13 | # under the License. |
| 14 | |
chenke | 4beff29 | 2019-04-11 14:02:57 +0800 | [diff] [blame] | 15 | import six |
Ken'ichi Ohmichi | 4d237e7 | 2015-11-05 06:32:33 +0000 | [diff] [blame] | 16 | import testtools |
| 17 | |
Ghanshyam | 1f47cf9 | 2016-02-25 04:57:18 +0900 | [diff] [blame] | 18 | from tempest.lib.common import api_version_request |
| 19 | from tempest.lib import exceptions |
Ken'ichi Ohmichi | 4d237e7 | 2015-11-05 06:32:33 +0000 | [diff] [blame] | 20 | |
| 21 | |
Ghanshyam | 05049dd | 2016-02-12 17:44:48 +0900 | [diff] [blame] | 22 | LATEST_MICROVERSION = 'latest' |
| 23 | |
| 24 | |
Ken'ichi Ohmichi | 4d237e7 | 2015-11-05 06:32:33 +0000 | [diff] [blame] | 25 | class BaseMicroversionTest(object): |
| 26 | """Mixin class for API microversion test class.""" |
| 27 | |
| 28 | # NOTE: Basically, each microversion is small API change and we |
| 29 | # can use the same tests for most microversions in most cases. |
| 30 | # So it is nice to define the test class as possible to run |
| 31 | # for all microversions. We need to define microversion range |
| 32 | # (min_microversion, max_microversion) on each test class if necessary. |
| 33 | min_microversion = None |
Ghanshyam | 05049dd | 2016-02-12 17:44:48 +0900 | [diff] [blame] | 34 | max_microversion = LATEST_MICROVERSION |
Ken'ichi Ohmichi | 4d237e7 | 2015-11-05 06:32:33 +0000 | [diff] [blame] | 35 | |
| 36 | |
| 37 | def check_skip_with_microversion(test_min_version, test_max_version, |
| 38 | cfg_min_version, cfg_max_version): |
Ghanshyam | 1f47cf9 | 2016-02-25 04:57:18 +0900 | [diff] [blame] | 39 | """Checks API microversions range and returns whether test needs to be skip |
| 40 | |
| 41 | Compare the test and configured microversion range and returns |
| 42 | whether test microversion range is out of configured one. |
| 43 | This method can be used to skip the test based on configured and test |
| 44 | microversion range. |
| 45 | |
| 46 | :param test_min_version: Test Minimum Microversion |
| 47 | :param test_max_version: Test Maximum Microversion |
| 48 | :param cfg_min_version: Configured Minimum Microversion |
| 49 | :param cfg_max_version: Configured Maximum Microversion |
| 50 | :returns: boolean |
| 51 | """ |
| 52 | |
Ken'ichi Ohmichi | 4d237e7 | 2015-11-05 06:32:33 +0000 | [diff] [blame] | 53 | min_version = api_version_request.APIVersionRequest(test_min_version) |
| 54 | max_version = api_version_request.APIVersionRequest(test_max_version) |
| 55 | config_min_version = api_version_request.APIVersionRequest(cfg_min_version) |
| 56 | config_max_version = api_version_request.APIVersionRequest(cfg_max_version) |
| 57 | if ((min_version > max_version) or |
afazekas | 40fcb9b | 2019-03-08 11:25:11 +0100 | [diff] [blame] | 58 | (config_min_version > config_max_version)): |
Ghanshyam | d2e7a0a | 2016-02-02 10:53:33 +0900 | [diff] [blame] | 59 | msg = ("Test Class versions [%s - %s]. " |
| 60 | "Configuration versions [%s - %s]." |
Ken'ichi Ohmichi | 4d237e7 | 2015-11-05 06:32:33 +0000 | [diff] [blame] | 61 | % (min_version.get_string(), |
| 62 | max_version.get_string(), |
| 63 | config_min_version.get_string(), |
| 64 | config_max_version.get_string())) |
Ghanshyam | d2e7a0a | 2016-02-02 10:53:33 +0900 | [diff] [blame] | 65 | raise exceptions.InvalidAPIVersionRange(msg) |
Ken'ichi Ohmichi | 4d237e7 | 2015-11-05 06:32:33 +0000 | [diff] [blame] | 66 | |
| 67 | # NOTE: Select tests which are in range of configuration like |
| 68 | # config min config max |
| 69 | # ----------------+--------------------------+---------------- |
| 70 | # ...don't-select| |
| 71 | # ...select... ...select... ...select... |
| 72 | # |don't-select... |
| 73 | # ......................select............................ |
| 74 | if (max_version < config_min_version or |
| 75 | config_max_version < min_version): |
| 76 | msg = ("The microversion range[%s - %s] of this test is out of the " |
april | 4567efe | 2015-12-30 22:32:45 +0800 | [diff] [blame] | 77 | "configuration range[%s - %s]." |
Ken'ichi Ohmichi | 4d237e7 | 2015-11-05 06:32:33 +0000 | [diff] [blame] | 78 | % (min_version.get_string(), |
| 79 | max_version.get_string(), |
| 80 | config_min_version.get_string(), |
| 81 | config_max_version.get_string())) |
| 82 | raise testtools.TestCase.skipException(msg) |
ghanshyam | 4e2be34 | 2015-11-27 18:07:46 +0900 | [diff] [blame] | 83 | |
| 84 | |
| 85 | def select_request_microversion(test_min_version, cfg_min_version): |
ghanshyam | c3b0b8b | 2016-03-16 11:58:34 +0900 | [diff] [blame] | 86 | """Select microversion from test and configuration min version. |
Ghanshyam | 1f47cf9 | 2016-02-25 04:57:18 +0900 | [diff] [blame] | 87 | |
| 88 | Compare requested microversion and return the maximum |
| 89 | microversion out of those. |
| 90 | |
| 91 | :param test_min_version: Test Minimum Microversion |
| 92 | :param cfg_min_version: Configured Minimum Microversion |
| 93 | :returns: Selected microversion string |
| 94 | """ |
| 95 | |
ghanshyam | 4e2be34 | 2015-11-27 18:07:46 +0900 | [diff] [blame] | 96 | test_version = api_version_request.APIVersionRequest(test_min_version) |
| 97 | cfg_version = api_version_request.APIVersionRequest(cfg_min_version) |
| 98 | max_version = cfg_version if cfg_version >= test_version else test_version |
| 99 | return max_version.get_string() |
Ghanshyam | bbdb33b | 2016-01-08 11:51:07 +0900 | [diff] [blame] | 100 | |
| 101 | |
| 102 | def assert_version_header_matches_request(api_microversion_header_name, |
| 103 | api_microversion, |
| 104 | response_header): |
ghanshyam | c3b0b8b | 2016-03-16 11:58:34 +0900 | [diff] [blame] | 105 | """Checks API microversion in response header |
Ghanshyam | bbdb33b | 2016-01-08 11:51:07 +0900 | [diff] [blame] | 106 | |
| 107 | Verify whether microversion is present in response header |
| 108 | and with specified 'api_microversion' value. |
| 109 | |
Ghanshyam | 1f47cf9 | 2016-02-25 04:57:18 +0900 | [diff] [blame] | 110 | :param api_microversion_header_name: Microversion header name |
Ghanshyam | bbdb33b | 2016-01-08 11:51:07 +0900 | [diff] [blame] | 111 | Example- "X-OpenStack-Nova-API-Version" |
chenke | 4beff29 | 2019-04-11 14:02:57 +0800 | [diff] [blame] | 112 | :param api_microversion: Microversion number like "2.10", type str. |
Ghanshyam | 1f47cf9 | 2016-02-25 04:57:18 +0900 | [diff] [blame] | 113 | :param response_header: Response header where microversion is |
Ghanshyam | bbdb33b | 2016-01-08 11:51:07 +0900 | [diff] [blame] | 114 | expected to be present. |
| 115 | """ |
chenke | 4beff29 | 2019-04-11 14:02:57 +0800 | [diff] [blame] | 116 | if not isinstance(api_microversion, six.string_types): |
| 117 | raise TypeError('api_microversion must be a string') |
Ghanshyam | bbdb33b | 2016-01-08 11:51:07 +0900 | [diff] [blame] | 118 | api_microversion_header_name = api_microversion_header_name.lower() |
| 119 | if (api_microversion_header_name not in response_header or |
| 120 | api_microversion != response_header[api_microversion_header_name]): |
| 121 | msg = ("Microversion header '%s' with value '%s' does not match in " |
| 122 | "response - %s. " % (api_microversion_header_name, |
| 123 | api_microversion, |
| 124 | response_header)) |
| 125 | raise exceptions.InvalidHTTPResponseHeader(msg) |
Felipe Monteiro | 9ff5c28 | 2017-06-21 21:05:07 +0100 | [diff] [blame] | 126 | |
| 127 | |
| 128 | def compare_version_header_to_response(api_microversion_header_name, |
| 129 | api_microversion, |
| 130 | response_header, |
| 131 | operation='eq'): |
| 132 | """Compares API microversion in response header to ``api_microversion``. |
| 133 | |
| 134 | Compare the ``api_microversion`` value in response header if microversion |
| 135 | header is present in response, otherwise return false. |
| 136 | |
| 137 | To make this function work for APIs which do not return microversion |
| 138 | header in response (example compute v2.0), this function does *not* raise |
| 139 | InvalidHTTPResponseHeader. |
| 140 | |
| 141 | :param api_microversion_header_name: Microversion header name. Example: |
| 142 | 'Openstack-Api-Version'. |
| 143 | :param api_microversion: Microversion number. Example: |
| 144 | |
| 145 | * '2.10' for the old-style header name, 'X-OpenStack-Nova-API-Version' |
| 146 | * 'Compute 2.10' for the new-style header name, 'Openstack-Api-Version' |
| 147 | |
| 148 | :param response_header: Response header where microversion is |
| 149 | expected to be present. |
| 150 | :param operation: The boolean operation to use to compare the |
| 151 | ``api_microversion`` to the microversion in ``response_header``. |
| 152 | Can be 'lt', 'eq', 'gt', 'le', 'ne', 'ge'. Default is 'eq'. The |
| 153 | operation type should be based on the order of the arguments: |
| 154 | ``api_microversion`` <operation> ``response_header`` microversion. |
| 155 | :returns: True if the comparison is logically true, else False if the |
| 156 | comparison is logically false or if ``api_microversion_header_name`` is |
| 157 | missing in the ``response_header``. |
| 158 | :raises InvalidParam: If the operation is not lt, eq, gt, le, ne or ge. |
| 159 | """ |
| 160 | api_microversion_header_name = api_microversion_header_name.lower() |
| 161 | if api_microversion_header_name not in response_header: |
| 162 | return False |
| 163 | |
| 164 | op = getattr(api_version_request.APIVersionRequest, |
| 165 | '__%s__' % operation, None) |
| 166 | |
| 167 | if op is None: |
| 168 | msg = ("Operation %s is invalid. Valid options include: lt, eq, gt, " |
| 169 | "le, ne, ge." % operation) |
Felipe Monteiro | 9ff5c28 | 2017-06-21 21:05:07 +0100 | [diff] [blame] | 170 | raise exceptions.InvalidParam(invalid_param=msg) |
| 171 | |
| 172 | # Remove "volume" from "volume <microversion>", for example, so that the |
| 173 | # microversion can be converted to `APIVersionRequest`. |
| 174 | api_version = api_microversion.split(' ')[-1] |
| 175 | resp_version = response_header[api_microversion_header_name].split(' ')[-1] |
| 176 | if not op( |
| 177 | api_version_request.APIVersionRequest(api_version), |
| 178 | api_version_request.APIVersionRequest(resp_version)): |
| 179 | return False |
| 180 | |
| 181 | return True |