blob: 9d300377419c4c7e0bfb935be2680d4aaef4153a [file] [log] [blame]
Jay Pipes051075a2012-04-28 17:39:37 -04001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack, LLC
4# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
Attila Fazekasf86fa312013-07-30 19:56:39 +020018import atexit
Ian Wienand98c35f32013-07-23 20:34:23 +100019import os
Jay Pipes051075a2012-04-28 17:39:37 -040020import time
21
Matthew Treinish78561ad2013-07-26 11:41:56 -040022import fixtures
Chris Yeoh55530bb2013-02-08 16:04:27 +103023import nose.plugins.attrib
Attila Fazekasdc216422013-01-29 15:12:14 +010024import testresources
ivan-zhu1feeb382013-01-24 10:14:39 +080025import testtools
Jay Pipes051075a2012-04-28 17:39:37 -040026
Matthew Treinish3e046852013-07-23 16:00:24 -040027from tempest import clients
Attila Fazekasdc216422013-01-29 15:12:14 +010028from tempest import config
Matthew Treinishf4a9b0f2013-07-26 16:58:26 -040029from tempest.openstack.common import log as logging
Jay Pipes051075a2012-04-28 17:39:37 -040030
31LOG = logging.getLogger(__name__)
32
Samuel Merritt0d499bc2013-06-19 12:08:23 -070033# All the successful HTTP status codes from RFC 2616
34HTTP_SUCCESS = (200, 201, 202, 203, 204, 205, 206)
35
Jay Pipes051075a2012-04-28 17:39:37 -040036
Chris Yeoh55530bb2013-02-08 16:04:27 +103037def attr(*args, **kwargs):
38 """A decorator which applies the nose and testtools attr decorator
39
40 This decorator applies the nose attr decorator as well as the
41 the testtools.testcase.attr if it is in the list of attributes
Attila Fazekasb2902af2013-02-16 16:22:44 +010042 to testtools we want to apply.
43 """
Chris Yeoh55530bb2013-02-08 16:04:27 +103044
45 def decorator(f):
Giulio Fidente4946a052013-05-14 12:23:51 +020046 if 'type' in kwargs and isinstance(kwargs['type'], str):
47 f = testtools.testcase.attr(kwargs['type'])(f)
Chris Yeohcf3fb7c2013-05-19 15:59:00 +093048 if kwargs['type'] == 'smoke':
49 f = testtools.testcase.attr('gate')(f)
Giulio Fidente4946a052013-05-14 12:23:51 +020050 elif 'type' in kwargs and isinstance(kwargs['type'], list):
51 for attr in kwargs['type']:
52 f = testtools.testcase.attr(attr)(f)
Chris Yeohcf3fb7c2013-05-19 15:59:00 +093053 if attr == 'smoke':
54 f = testtools.testcase.attr('gate')(f)
Giulio Fidente4946a052013-05-14 12:23:51 +020055 return nose.plugins.attrib.attr(*args, **kwargs)(f)
Chris Yeoh55530bb2013-02-08 16:04:27 +103056
57 return decorator
58
59
Marc Koderer32221b8e2013-08-23 13:57:50 +020060def stresstest(*args, **kwargs):
61 """Add stress test decorator
62
63 For all functions with this decorator a attr stress will be
64 set automatically.
65
66 @param class_setup_per: allowed values are application, process, action
67 ``application``: once in the stress job lifetime
68 ``process``: once in the worker process lifetime
69 ``action``: on each action
Marc Kodererb0604412013-09-02 09:43:40 +020070 @param allow_inheritance: allows inheritance of this attribute
Marc Koderer32221b8e2013-08-23 13:57:50 +020071 """
72 def decorator(f):
73 if 'class_setup_per' in kwargs:
74 setattr(f, "st_class_setup_per", kwargs['class_setup_per'])
75 else:
76 setattr(f, "st_class_setup_per", 'process')
Marc Kodererb0604412013-09-02 09:43:40 +020077 if 'allow_inheritance' in kwargs:
78 setattr(f, "st_allow_inheritance", kwargs['allow_inheritance'])
79 else:
80 setattr(f, "st_allow_inheritance", False)
Marc Koderer32221b8e2013-08-23 13:57:50 +020081 attr(type='stress')(f)
82 return f
83 return decorator
84
85
Ian Wienand98c35f32013-07-23 20:34:23 +100086# there is a mis-match between nose and testtools for older pythons.
87# testtools will set skipException to be either
88# unittest.case.SkipTest, unittest2.case.SkipTest or an internal skip
89# exception, depending on what it can find. Python <2.7 doesn't have
90# unittest.case.SkipTest; so if unittest2 is not installed it falls
91# back to the internal class.
92#
93# The current nose skip plugin will decide to raise either
94# unittest.case.SkipTest or its own internal exception; it does not
95# look for unittest2 or the internal unittest exception. Thus we must
96# monkey-patch testtools.TestCase.skipException to be the exception
97# the nose skip plugin expects.
98#
99# However, with the switch to testr nose may not be available, so we
100# require you to opt-in to this fix with an environment variable.
101#
102# This is temporary until upstream nose starts looking for unittest2
103# as testtools does; we can then remove this and ensure unittest2 is
104# available for older pythons; then nose and testtools will agree
105# unittest2.case.SkipTest is the one-true skip test exception.
106#
107# https://review.openstack.org/#/c/33056
108# https://github.com/nose-devs/nose/pull/699
109if 'TEMPEST_PY26_NOSE_COMPAT' in os.environ:
110 try:
111 import unittest.case.SkipTest
112 # convince pep8 we're using the import...
113 if unittest.case.SkipTest:
114 pass
115 raise RuntimeError("You have unittest.case.SkipTest; "
116 "no need to override")
117 except ImportError:
118 LOG.info("Overriding skipException to nose SkipTest")
119 testtools.TestCase.skipException = nose.plugins.skip.SkipTest
120
Attila Fazekasf86fa312013-07-30 19:56:39 +0200121at_exit_set = set()
122
123
124def validate_tearDownClass():
125 if at_exit_set:
Alex Gaynor94560d42013-08-23 05:41:23 -0700126 raise RuntimeError("tearDownClass does not calls the super's "
Attila Fazekasf86fa312013-07-30 19:56:39 +0200127 "tearDownClass in these classes: "
128 + str(at_exit_set))
129
130atexit.register(validate_tearDownClass)
131
Ian Wienand98c35f32013-07-23 20:34:23 +1000132
Attila Fazekasdc216422013-01-29 15:12:14 +0100133class BaseTestCase(testtools.TestCase,
134 testtools.testcase.WithAttributes,
135 testresources.ResourcedTestCase):
Attila Fazekasc43fec82013-04-09 23:17:52 +0200136
137 config = config.TempestConfig()
Attila Fazekasdc216422013-01-29 15:12:14 +0100138
Attila Fazekasf86fa312013-07-30 19:56:39 +0200139 setUpClassCalled = False
140
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200141 @classmethod
142 def setUpClass(cls):
143 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
144 super(BaseTestCase, cls).setUpClass()
Attila Fazekasf86fa312013-07-30 19:56:39 +0200145 cls.setUpClassCalled = True
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200146
Attila Fazekasf86fa312013-07-30 19:56:39 +0200147 @classmethod
148 def tearDownClass(cls):
149 at_exit_set.remove(cls)
150 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
151 super(BaseTestCase, cls).tearDownClass()
152
153 def setUp(self):
154 super(BaseTestCase, self).setUp()
155 if not self.setUpClassCalled:
156 raise RuntimeError("setUpClass does not calls the super's"
157 "setUpClass in the "
158 + self.__class__.__name__)
159 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400160 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
161 try:
162 test_timeout = int(test_timeout)
163 except ValueError:
164 test_timeout = 0
165 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200166 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400167
168 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
169 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200170 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
171 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400172 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
173 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200174 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
175 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200176 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
177 os.environ.get('OS_LOG_CAPTURE') != '0'):
178 log_format = '%(asctime)-15s %(message)s'
179 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
180 format=log_format))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400181
Matthew Treinish3e046852013-07-23 16:00:24 -0400182 @classmethod
183 def _get_identity_admin_client(cls):
184 """
185 Returns an instance of the Identity Admin API client
186 """
187 os = clients.AdminManager(interface=cls._interface)
188 admin_client = os.identity_client
189 return admin_client
190
191 @classmethod
192 def _get_client_args(cls):
193
194 return (
195 cls.config,
196 cls.config.identity.admin_username,
197 cls.config.identity.admin_password,
198 cls.config.identity.uri
199 )
200
Attila Fazekasdc216422013-01-29 15:12:14 +0100201
Sean Dague35a7caf2013-05-10 10:38:22 -0400202def call_until_true(func, duration, sleep_for):
203 """
204 Call the given function until it returns True (and return True) or
205 until the specified duration (in seconds) elapses (and return
206 False).
207
208 :param func: A zero argument callable that returns True on success.
209 :param duration: The number of seconds for which to attempt a
210 successful call of the function.
211 :param sleep_for: The number of seconds to sleep after an unsuccessful
212 invocation of the function.
213 """
214 now = time.time()
215 timeout = now + duration
216 while now < timeout:
217 if func():
218 return True
219 LOG.debug("Sleeping for %d seconds", sleep_for)
220 time.sleep(sleep_for)
221 now = time.time()
222 return False