Merge "Add the base microversions test part"
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index a5c0600..5bc0769 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -18,6 +18,7 @@
from oslo_log import log as logging
from tempest_lib import exceptions as lib_exc
+from tempest.common import api_version_utils
from tempest.common import compute
from tempest.common.utils import data_utils
from tempest.common import waiters
@@ -29,7 +30,8 @@
LOG = logging.getLogger(__name__)
-class BaseV2ComputeTest(tempest.test.BaseTestCase):
+class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
+ tempest.test.BaseTestCase):
"""Base test case class for all Compute API tests."""
force_tenant_isolation = False
@@ -43,6 +45,12 @@
super(BaseV2ComputeTest, cls).skip_checks()
if not CONF.service_available.nova:
raise cls.skipException("Nova is not available")
+ cfg_min_version = CONF.compute_feature_enabled.min_microversion
+ cfg_max_version = CONF.compute_feature_enabled.max_microversion
+ api_version_utils.check_skip_with_microversion(cls.min_microversion,
+ cls.max_microversion,
+ cfg_min_version,
+ cfg_max_version)
@classmethod
def setup_credentials(cls):
diff --git a/tempest/common/api_version_request.py b/tempest/common/api_version_request.py
new file mode 100644
index 0000000..72a11ea
--- /dev/null
+++ b/tempest/common/api_version_request.py
@@ -0,0 +1,152 @@
+# 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 re
+
+from tempest import exceptions
+
+
+# Define the minimum and maximum version of the API across all of the
+# REST API. The format of the version is:
+# X.Y where:
+#
+# - X will only be changed if a significant backwards incompatible API
+# change is made which affects the API as whole. That is, something
+# that is only very very rarely incremented.
+#
+# - Y when you make any change to the API. Note that this includes
+# semantic changes which may not affect the input or output formats or
+# even originate in the API code layer. We are not distinguishing
+# between backwards compatible and backwards incompatible changes in
+# the versioning system. It must be made clear in the documentation as
+# to what is a backwards compatible change and what is a backwards
+# incompatible one.
+
+class APIVersionRequest(object):
+ """This class represents an API Version Request.
+
+ This class provides convenience methods for manipulation
+ and comparison of version numbers that we need to do to
+ implement microversions.
+ """
+
+ # NOTE: This 'latest' version is a magic number, we assume any
+ # projects(Nova, etc.) never achieve this number.
+ latest_ver_major = 99999
+ latest_ver_minor = 99999
+
+ def __init__(self, version_string=None):
+ """Create an API version request object.
+
+ :param version_string: String representation of APIVersionRequest.
+ Correct format is 'X.Y', where 'X' and 'Y' are int values.
+ None value should be used to create Null APIVersionRequest,
+ which is equal to 0.0
+ """
+ self.ver_major = 0
+ self.ver_minor = 0
+
+ if version_string is not None:
+ match = re.match(r"^([1-9]\d*)\.([1-9]\d*|0)$",
+ version_string)
+ if match:
+ self.ver_major = int(match.group(1))
+ self.ver_minor = int(match.group(2))
+ elif version_string == 'latest':
+ self.ver_major = self.latest_ver_major
+ self.ver_minor = self.latest_ver_minor
+ else:
+ raise exceptions.InvalidAPIVersionString(
+ version=version_string)
+
+ def __str__(self):
+ """Debug/Logging representation of object."""
+ return ("API Version Request: %s" % self.get_string())
+
+ def is_null(self):
+ return self.ver_major == 0 and self.ver_minor == 0
+
+ def _format_type_error(self, other):
+ return TypeError("'%(other)s' should be an instance of '%(cls)s'" %
+ {"other": other, "cls": self.__class__})
+
+ def __lt__(self, other):
+ if not isinstance(other, APIVersionRequest):
+ raise self._format_type_error(other)
+
+ return ((self.ver_major, self.ver_minor) <
+ (other.ver_major, other.ver_minor))
+
+ def __eq__(self, other):
+ if not isinstance(other, APIVersionRequest):
+ raise self._format_type_error(other)
+
+ return ((self.ver_major, self.ver_minor) ==
+ (other.ver_major, other.ver_minor))
+
+ def __gt__(self, other):
+ if not isinstance(other, APIVersionRequest):
+ raise self._format_type_error(other)
+
+ return ((self.ver_major, self.ver_minor) >
+ (other.ver_major, other.ver_minor))
+
+ def __le__(self, other):
+ return self < other or self == other
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __ge__(self, other):
+ return self > other or self == other
+
+ def matches(self, min_version, max_version):
+ """Matches the version object.
+
+ Returns whether the version object represents a version
+ greater than or equal to the minimum version and less than
+ or equal to the maximum version.
+
+ @param min_version: Minimum acceptable version.
+ @param max_version: Maximum acceptable version.
+ @returns: boolean
+
+ If min_version is null then there is no minimum limit.
+ If max_version is null then there is no maximum limit.
+ If self is null then raise ValueError
+ """
+
+ if self.is_null():
+ raise ValueError
+ if max_version.is_null() and min_version.is_null():
+ return True
+ elif max_version.is_null():
+ return min_version <= self
+ elif min_version.is_null():
+ return self <= max_version
+ else:
+ return min_version <= self <= max_version
+
+ def get_string(self):
+ """Version string representation.
+
+ Converts object to string representation which if used to create
+ an APIVersionRequest object results in the same version request.
+ """
+ if self.is_null():
+ return None
+ if (self.ver_major == self.latest_ver_major and
+ self.ver_minor == self.latest_ver_minor):
+ return 'latest'
+ return "%s.%s" % (self.ver_major, self.ver_minor)
diff --git a/tempest/common/api_version_utils.py b/tempest/common/api_version_utils.py
new file mode 100644
index 0000000..c499f23
--- /dev/null
+++ b/tempest/common/api_version_utils.py
@@ -0,0 +1,64 @@
+# Copyright 2015 NEC Corporation. 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 testtools
+
+from tempest.common import api_version_request
+from tempest import exceptions
+
+
+class BaseMicroversionTest(object):
+ """Mixin class for API microversion test class."""
+
+ # NOTE: Basically, each microversion is small API change and we
+ # can use the same tests for most microversions in most cases.
+ # So it is nice to define the test class as possible to run
+ # for all microversions. We need to define microversion range
+ # (min_microversion, max_microversion) on each test class if necessary.
+ min_microversion = None
+ max_microversion = 'latest'
+
+
+def check_skip_with_microversion(test_min_version, test_max_version,
+ cfg_min_version, cfg_max_version):
+ min_version = api_version_request.APIVersionRequest(test_min_version)
+ max_version = api_version_request.APIVersionRequest(test_max_version)
+ config_min_version = api_version_request.APIVersionRequest(cfg_min_version)
+ config_max_version = api_version_request.APIVersionRequest(cfg_max_version)
+ if ((min_version > max_version) or
+ (config_min_version > config_max_version)):
+ msg = ("Min version is greater than Max version. Test Class versions "
+ "[%s - %s]. configration versions [%s - %s]."
+ % (min_version.get_string(),
+ max_version.get_string(),
+ config_min_version.get_string(),
+ config_max_version.get_string()))
+ raise exceptions.InvalidConfiguration(msg)
+
+ # NOTE: Select tests which are in range of configuration like
+ # config min config max
+ # ----------------+--------------------------+----------------
+ # ...don't-select|
+ # ...select... ...select... ...select...
+ # |don't-select...
+ # ......................select............................
+ if (max_version < config_min_version or
+ config_max_version < min_version):
+ msg = ("The microversion range[%s - %s] of this test is out of the "
+ "configration range[%s - %s]."
+ % (min_version.get_string(),
+ max_version.get_string(),
+ config_min_version.get_string(),
+ config_max_version.get_string()))
+ raise testtools.TestCase.skipException(msg)
diff --git a/tempest/config.py b/tempest/config.py
index 8c3656f..26dda2d 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -341,6 +341,22 @@
title="Enabled Compute Service Features")
ComputeFeaturesGroup = [
+ cfg.StrOpt('min_microversion',
+ default=None,
+ help="Lower version of the test target microversion range. "
+ "The format is 'X.Y', where 'X' and 'Y' are int values. "
+ "Tempest selects tests based on the range between "
+ "min_microversion and max_microversion. "
+ "If both values are None, Tempest avoids tests which "
+ "require a microversion."),
+ cfg.StrOpt('max_microversion',
+ default=None,
+ help="Upper version of the test target microversion range. "
+ "The format is 'X.Y', where 'X' and 'Y' are int values. "
+ "Tempest selects tests based on the range between "
+ "min_microversion and max_microversion. "
+ "If both values are None, Tempest avoids tests which "
+ "require a microversion."),
cfg.BoolOpt('disk_config',
default=True,
help="If false, skip disk config tests"),
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 031df7f..8537898 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -176,6 +176,11 @@
message = "Invalid structure of table with details"
+class InvalidAPIVersionString(TempestException):
+ msg_fmt = ("API Version String %(version)s is of invalid format. Must "
+ "be of format MajorNum.MinorNum.")
+
+
class CommandFailed(Exception):
def __init__(self, returncode, cmd, output, stderr):
super(CommandFailed, self).__init__()
diff --git a/tempest/tests/common/test_api_version_request.py b/tempest/tests/common/test_api_version_request.py
new file mode 100644
index 0000000..38fbfc1
--- /dev/null
+++ b/tempest/tests/common/test_api_version_request.py
@@ -0,0 +1,146 @@
+# 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.
+
+from tempest.common import api_version_request
+from tempest import exceptions
+from tempest.tests import base
+
+
+class APIVersionRequestTests(base.TestCase):
+ def test_valid_version_strings(self):
+ def _test_string(version, exp_major, exp_minor):
+ v = api_version_request.APIVersionRequest(version)
+ self.assertEqual(v.ver_major, exp_major)
+ self.assertEqual(v.ver_minor, exp_minor)
+
+ _test_string("1.1", 1, 1)
+ _test_string("2.10", 2, 10)
+ _test_string("5.234", 5, 234)
+ _test_string("12.5", 12, 5)
+ _test_string("2.0", 2, 0)
+ _test_string("2.200", 2, 200)
+
+ def test_null_version(self):
+ v = api_version_request.APIVersionRequest()
+ self.assertTrue(v.is_null())
+
+ def test_invalid_version_strings(self):
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "2")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "200")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "2.1.4")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "200.23.66.3")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "5 .3")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "5. 3")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "5.03")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "02.1")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "2.001")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, " 2.1")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "2.1 ")
+
+ def test_version_comparisons(self):
+ vers2_0 = api_version_request.APIVersionRequest("2.0")
+ vers2_5 = api_version_request.APIVersionRequest("2.5")
+ vers5_23 = api_version_request.APIVersionRequest("5.23")
+ v_null = api_version_request.APIVersionRequest()
+ v_latest = api_version_request.APIVersionRequest('latest')
+
+ self.assertTrue(v_null < vers2_5)
+ self.assertTrue(vers2_0 < vers2_5)
+ self.assertTrue(vers2_0 <= vers2_5)
+ self.assertTrue(vers2_0 <= vers2_0)
+ self.assertTrue(vers2_5 > v_null)
+ self.assertTrue(vers5_23 > vers2_5)
+ self.assertTrue(vers2_0 >= vers2_0)
+ self.assertTrue(vers5_23 >= vers2_5)
+ self.assertTrue(vers2_0 != vers2_5)
+ self.assertTrue(vers2_0 == vers2_0)
+ self.assertTrue(vers2_0 != v_null)
+ self.assertTrue(v_null == v_null)
+ self.assertTrue(vers2_0 <= v_latest)
+ self.assertTrue(vers2_0 != v_latest)
+ self.assertTrue(v_latest == v_latest)
+ self.assertRaises(TypeError, vers2_0.__lt__, "2.1")
+
+ def test_version_matches(self):
+ vers2_0 = api_version_request.APIVersionRequest("2.0")
+ vers2_5 = api_version_request.APIVersionRequest("2.5")
+ vers2_45 = api_version_request.APIVersionRequest("2.45")
+ vers3_3 = api_version_request.APIVersionRequest("3.3")
+ vers3_23 = api_version_request.APIVersionRequest("3.23")
+ vers4_0 = api_version_request.APIVersionRequest("4.0")
+ v_null = api_version_request.APIVersionRequest()
+ v_latest = api_version_request.APIVersionRequest('latest')
+
+ def _check_version_matches(version, version1, version2, check=True):
+ if check:
+ msg = "Version %s does not matches with [%s - %s] range"
+ self.assertTrue(version.matches(version1, version2),
+ msg % (version.get_string(),
+ version1.get_string(),
+ version2.get_string()))
+ else:
+ msg = "Version %s matches with [%s - %s] range"
+ self.assertFalse(version.matches(version1, version2),
+ msg % (version.get_string(),
+ version1.get_string(),
+ version2.get_string()))
+
+ _check_version_matches(vers2_5, vers2_0, vers2_45)
+ _check_version_matches(vers2_5, vers2_0, v_null)
+ _check_version_matches(vers2_0, vers2_0, vers2_5)
+ _check_version_matches(vers3_3, vers2_5, vers3_3)
+ _check_version_matches(vers3_3, v_null, vers3_3)
+ _check_version_matches(vers3_3, v_null, vers4_0)
+ _check_version_matches(vers2_0, vers2_5, vers2_45, False)
+ _check_version_matches(vers3_23, vers2_5, vers3_3, False)
+ _check_version_matches(vers2_5, vers2_45, vers2_0, False)
+ _check_version_matches(vers2_5, vers2_0, v_latest)
+ _check_version_matches(v_latest, v_latest, v_latest)
+ _check_version_matches(vers2_5, v_latest, v_latest, False)
+ _check_version_matches(v_latest, vers2_0, vers4_0, False)
+
+ self.assertRaises(ValueError, v_null.matches, vers2_0, vers2_45)
+
+ def test_get_string(self):
+ vers_string = ["3.23", "latest"]
+ for ver in vers_string:
+ ver_obj = api_version_request.APIVersionRequest(ver)
+ self.assertEqual(ver, ver_obj.get_string())
+
+ self.assertIsNotNone(
+ api_version_request.APIVersionRequest().get_string)
diff --git a/tempest/tests/common/test_api_version_utils.py b/tempest/tests/common/test_api_version_utils.py
new file mode 100644
index 0000000..33024b6
--- /dev/null
+++ b/tempest/tests/common/test_api_version_utils.py
@@ -0,0 +1,194 @@
+# Copyright 2015 NEC Corporation. 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.
+
+from oslo_config import cfg
+import testtools
+
+from tempest.api.compute import base as compute_base
+from tempest.common import api_version_utils
+from tempest import config
+from tempest import exceptions
+from tempest.tests import base
+from tempest.tests import fake_config
+
+
+class VersionTestNoneTolatest(compute_base.BaseV2ComputeTest):
+ min_microversion = None
+ max_microversion = 'latest'
+
+
+class VersionTestNoneTo2_2(compute_base.BaseV2ComputeTest):
+ min_microversion = None
+ max_microversion = '2.2'
+
+
+class VersionTest2_3ToLatest(compute_base.BaseV2ComputeTest):
+ min_microversion = '2.3'
+ max_microversion = 'latest'
+
+
+class VersionTest2_5To2_10(compute_base.BaseV2ComputeTest):
+ min_microversion = '2.5'
+ max_microversion = '2.10'
+
+
+class VersionTest2_10To2_10(compute_base.BaseV2ComputeTest):
+ min_microversion = '2.10'
+ max_microversion = '2.10'
+
+
+class InvalidVersionTest(compute_base.BaseV2ComputeTest):
+ min_microversion = '2.11'
+ max_microversion = '2.1'
+
+
+class TestMicroversionsTestsClass(base.TestCase):
+
+ def setUp(self):
+ super(TestMicroversionsTestsClass, self).setUp()
+ self.useFixture(fake_config.ConfigFixture())
+ self.stubs.Set(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
+
+ def _test_version(self, cfg_min, cfg_max,
+ expected_pass_tests,
+ expected_skip_tests):
+ cfg.CONF.set_default('min_microversion',
+ cfg_min, group='compute-feature-enabled')
+ cfg.CONF.set_default('max_microversion',
+ cfg_max, group='compute-feature-enabled')
+ try:
+ for test_class in expected_pass_tests:
+ test_class.skip_checks()
+ for test_class in expected_skip_tests:
+ self.assertRaises(testtools.TestCase.skipException,
+ test_class.skip_checks)
+ except testtools.TestCase.skipException as e:
+ raise testtools.TestCase.failureException(e.message)
+
+ def test_config_version_none_none(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2]
+ expected_skip_tests = [VersionTest2_3ToLatest, VersionTest2_5To2_10,
+ VersionTest2_10To2_10]
+ self._test_version(None, None,
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_none_23(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+ VersionTest2_3ToLatest]
+ expected_skip_tests = [VersionTest2_5To2_10, VersionTest2_10To2_10]
+ self._test_version(None, '2.3',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_22_latest(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+ VersionTest2_3ToLatest, VersionTest2_5To2_10,
+ VersionTest2_10To2_10]
+ expected_skip_tests = []
+ self._test_version('2.2', 'latest',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_22_23(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+ VersionTest2_3ToLatest]
+ expected_skip_tests = [VersionTest2_5To2_10, VersionTest2_10To2_10]
+ self._test_version('2.2', '2.3',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_210_210(self):
+ expected_pass_tests = [VersionTestNoneTolatest,
+ VersionTest2_3ToLatest,
+ VersionTest2_5To2_10,
+ VersionTest2_10To2_10]
+ expected_skip_tests = [VersionTestNoneTo2_2]
+ self._test_version('2.10', '2.10',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_none_latest(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+ VersionTest2_3ToLatest, VersionTest2_5To2_10,
+ VersionTest2_10To2_10]
+ expected_skip_tests = []
+ self._test_version(None, 'latest',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_latest_latest(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTest2_3ToLatest]
+ expected_skip_tests = [VersionTestNoneTo2_2, VersionTest2_5To2_10,
+ VersionTest2_10To2_10]
+ self._test_version('latest', 'latest',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_invalid_version(self):
+ cfg.CONF.set_default('min_microversion',
+ '2.5', group='compute-feature-enabled')
+ cfg.CONF.set_default('max_microversion',
+ '2.1', group='compute-feature-enabled')
+ self.assertRaises(exceptions.InvalidConfiguration,
+ VersionTestNoneTolatest.skip_checks)
+
+ def test_config_version_invalid_test_version(self):
+ cfg.CONF.set_default('min_microversion',
+ None, group='compute-feature-enabled')
+ cfg.CONF.set_default('max_microversion',
+ '2.13', group='compute-feature-enabled')
+ self.assertRaises(exceptions.InvalidConfiguration,
+ InvalidVersionTest.skip_checks)
+
+
+class TestVersionSkipLogic(base.TestCase):
+
+ def _test_version(self, test_min_version, test_max_version,
+ cfg_min_version, cfg_max_version, expected_skip=False):
+ try:
+ api_version_utils.check_skip_with_microversion(test_min_version,
+ test_max_version,
+ cfg_min_version,
+ cfg_max_version)
+ except testtools.TestCase.skipException as e:
+ if not expected_skip:
+ raise testtools.TestCase.failureException(e.message)
+
+ def test_version_min_in_range(self):
+ self._test_version('2.2', '2.10', '2.1', '2.7')
+
+ def test_version_max_in_range(self):
+ self._test_version('2.1', '2.3', '2.2', '2.7')
+
+ def test_version_cfg_in_range(self):
+ self._test_version('2.2', '2.9', '2.3', '2.7')
+
+ def test_version_equal(self):
+ self._test_version('2.2', '2.2', '2.2', '2.2')
+
+ def test_version_below_cfg_min(self):
+ self._test_version('2.2', '2.4', '2.5', '2.7', expected_skip=True)
+
+ def test_version_above_cfg_max(self):
+ self._test_version('2.8', '2.9', '2.3', '2.7', expected_skip=True)
+
+ def test_version_min_greater_than_max(self):
+ self.assertRaises(exceptions.InvalidConfiguration,
+ self._test_version, '2.8', '2.7', '2.3', '2.7')
+
+ def test_cfg_version_min_greater_than_max(self):
+ self.assertRaises(exceptions.InvalidConfiguration,
+ self._test_version, '2.2', '2.7', '2.9', '2.7')