blob: 0cd0b08989a504e80f0c82f7c571fefd7f3f75b8 [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
Ian Wienand98c35f32013-07-23 20:34:23 +100018import os
Jay Pipes051075a2012-04-28 17:39:37 -040019import time
20
Matthew Treinish78561ad2013-07-26 11:41:56 -040021import fixtures
Chris Yeoh55530bb2013-02-08 16:04:27 +103022import nose.plugins.attrib
Attila Fazekasdc216422013-01-29 15:12:14 +010023import testresources
ivan-zhu1feeb382013-01-24 10:14:39 +080024import testtools
Jay Pipes051075a2012-04-28 17:39:37 -040025
Matthew Treinish3e046852013-07-23 16:00:24 -040026from tempest import clients
Attila Fazekasdc216422013-01-29 15:12:14 +010027from tempest import config
Matthew Treinishf4a9b0f2013-07-26 16:58:26 -040028from tempest.openstack.common import log as logging
Jay Pipes051075a2012-04-28 17:39:37 -040029
30LOG = logging.getLogger(__name__)
31
Samuel Merritt0d499bc2013-06-19 12:08:23 -070032# All the successful HTTP status codes from RFC 2616
33HTTP_SUCCESS = (200, 201, 202, 203, 204, 205, 206)
34
Jay Pipes051075a2012-04-28 17:39:37 -040035
Chris Yeoh55530bb2013-02-08 16:04:27 +103036def attr(*args, **kwargs):
37 """A decorator which applies the nose and testtools attr decorator
38
39 This decorator applies the nose attr decorator as well as the
40 the testtools.testcase.attr if it is in the list of attributes
Attila Fazekasb2902af2013-02-16 16:22:44 +010041 to testtools we want to apply.
42 """
Chris Yeoh55530bb2013-02-08 16:04:27 +103043
44 def decorator(f):
Giulio Fidente4946a052013-05-14 12:23:51 +020045 if 'type' in kwargs and isinstance(kwargs['type'], str):
46 f = testtools.testcase.attr(kwargs['type'])(f)
Chris Yeohcf3fb7c2013-05-19 15:59:00 +093047 if kwargs['type'] == 'smoke':
48 f = testtools.testcase.attr('gate')(f)
Giulio Fidente4946a052013-05-14 12:23:51 +020049 elif 'type' in kwargs and isinstance(kwargs['type'], list):
50 for attr in kwargs['type']:
51 f = testtools.testcase.attr(attr)(f)
Chris Yeohcf3fb7c2013-05-19 15:59:00 +093052 if attr == 'smoke':
53 f = testtools.testcase.attr('gate')(f)
Giulio Fidente4946a052013-05-14 12:23:51 +020054 return nose.plugins.attrib.attr(*args, **kwargs)(f)
Chris Yeoh55530bb2013-02-08 16:04:27 +103055
56 return decorator
57
58
Ian Wienand98c35f32013-07-23 20:34:23 +100059# there is a mis-match between nose and testtools for older pythons.
60# testtools will set skipException to be either
61# unittest.case.SkipTest, unittest2.case.SkipTest or an internal skip
62# exception, depending on what it can find. Python <2.7 doesn't have
63# unittest.case.SkipTest; so if unittest2 is not installed it falls
64# back to the internal class.
65#
66# The current nose skip plugin will decide to raise either
67# unittest.case.SkipTest or its own internal exception; it does not
68# look for unittest2 or the internal unittest exception. Thus we must
69# monkey-patch testtools.TestCase.skipException to be the exception
70# the nose skip plugin expects.
71#
72# However, with the switch to testr nose may not be available, so we
73# require you to opt-in to this fix with an environment variable.
74#
75# This is temporary until upstream nose starts looking for unittest2
76# as testtools does; we can then remove this and ensure unittest2 is
77# available for older pythons; then nose and testtools will agree
78# unittest2.case.SkipTest is the one-true skip test exception.
79#
80# https://review.openstack.org/#/c/33056
81# https://github.com/nose-devs/nose/pull/699
82if 'TEMPEST_PY26_NOSE_COMPAT' in os.environ:
83 try:
84 import unittest.case.SkipTest
85 # convince pep8 we're using the import...
86 if unittest.case.SkipTest:
87 pass
88 raise RuntimeError("You have unittest.case.SkipTest; "
89 "no need to override")
90 except ImportError:
91 LOG.info("Overriding skipException to nose SkipTest")
92 testtools.TestCase.skipException = nose.plugins.skip.SkipTest
93
94
Attila Fazekasdc216422013-01-29 15:12:14 +010095class BaseTestCase(testtools.TestCase,
96 testtools.testcase.WithAttributes,
97 testresources.ResourcedTestCase):
Attila Fazekasc43fec82013-04-09 23:17:52 +020098
99 config = config.TempestConfig()
Attila Fazekasdc216422013-01-29 15:12:14 +0100100
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200101 @classmethod
102 def setUpClass(cls):
103 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
104 super(BaseTestCase, cls).setUpClass()
105
Matthew Treinish78561ad2013-07-26 11:41:56 -0400106 def setUp(cls):
107 super(BaseTestCase, cls).setUp()
108 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
109 try:
110 test_timeout = int(test_timeout)
111 except ValueError:
112 test_timeout = 0
113 if test_timeout > 0:
114 cls.useFixture(fixtures.Timeout(test_timeout, gentle=True))
115
116 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
117 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
118 stdout = cls.useFixture(fixtures.StringStream('stdout')).stream
119 cls.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
120 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
121 os.environ.get('OS_STDERR_CAPTURE') == '1'):
122 stderr = cls.useFixture(fixtures.StringStream('stderr')).stream
123 cls.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
124
Matthew Treinish3e046852013-07-23 16:00:24 -0400125 @classmethod
126 def _get_identity_admin_client(cls):
127 """
128 Returns an instance of the Identity Admin API client
129 """
130 os = clients.AdminManager(interface=cls._interface)
131 admin_client = os.identity_client
132 return admin_client
133
134 @classmethod
135 def _get_client_args(cls):
136
137 return (
138 cls.config,
139 cls.config.identity.admin_username,
140 cls.config.identity.admin_password,
141 cls.config.identity.uri
142 )
143
Attila Fazekasdc216422013-01-29 15:12:14 +0100144
Sean Dague35a7caf2013-05-10 10:38:22 -0400145def call_until_true(func, duration, sleep_for):
146 """
147 Call the given function until it returns True (and return True) or
148 until the specified duration (in seconds) elapses (and return
149 False).
150
151 :param func: A zero argument callable that returns True on success.
152 :param duration: The number of seconds for which to attempt a
153 successful call of the function.
154 :param sleep_for: The number of seconds to sleep after an unsuccessful
155 invocation of the function.
156 """
157 now = time.time()
158 timeout = now + duration
159 while now < timeout:
160 if func():
161 return True
162 LOG.debug("Sleeping for %d seconds", sleep_for)
163 time.sleep(sleep_for)
164 now = time.time()
165 return False