blob: d7008a7ab02e70d6ae9f4c91f7a63d8a5067291e [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
Jay Pipes051075a2012-04-28 17:39:37 -040018import time
19
Chris Yeoh55530bb2013-02-08 16:04:27 +103020import nose.plugins.attrib
Attila Fazekasdc216422013-01-29 15:12:14 +010021import testresources
ivan-zhu1feeb382013-01-24 10:14:39 +080022import testtools
Jay Pipes051075a2012-04-28 17:39:37 -040023
Mitsuhiko Yamazaki46818aa2013-04-18 17:49:17 +090024from tempest.common import log as logging
Attila Fazekasdc216422013-01-29 15:12:14 +010025from tempest import config
Jay Pipes051075a2012-04-28 17:39:37 -040026from tempest import manager
27
28LOG = logging.getLogger(__name__)
29
Samuel Merritt0d499bc2013-06-19 12:08:23 -070030# All the successful HTTP status codes from RFC 2616
31HTTP_SUCCESS = (200, 201, 202, 203, 204, 205, 206)
32
Jay Pipes051075a2012-04-28 17:39:37 -040033
Chris Yeoh55530bb2013-02-08 16:04:27 +103034def attr(*args, **kwargs):
35 """A decorator which applies the nose and testtools attr decorator
36
37 This decorator applies the nose attr decorator as well as the
38 the testtools.testcase.attr if it is in the list of attributes
Attila Fazekasb2902af2013-02-16 16:22:44 +010039 to testtools we want to apply.
40 """
Chris Yeoh55530bb2013-02-08 16:04:27 +103041
42 def decorator(f):
Giulio Fidente4946a052013-05-14 12:23:51 +020043 if 'type' in kwargs and isinstance(kwargs['type'], str):
44 f = testtools.testcase.attr(kwargs['type'])(f)
Chris Yeohcf3fb7c2013-05-19 15:59:00 +093045 if kwargs['type'] == 'smoke':
46 f = testtools.testcase.attr('gate')(f)
Giulio Fidente4946a052013-05-14 12:23:51 +020047 elif 'type' in kwargs and isinstance(kwargs['type'], list):
48 for attr in kwargs['type']:
49 f = testtools.testcase.attr(attr)(f)
Chris Yeohcf3fb7c2013-05-19 15:59:00 +093050 if attr == 'smoke':
51 f = testtools.testcase.attr('gate')(f)
Giulio Fidente4946a052013-05-14 12:23:51 +020052 return nose.plugins.attrib.attr(*args, **kwargs)(f)
Chris Yeoh55530bb2013-02-08 16:04:27 +103053
54 return decorator
55
56
Attila Fazekasdc216422013-01-29 15:12:14 +010057class BaseTestCase(testtools.TestCase,
58 testtools.testcase.WithAttributes,
59 testresources.ResourcedTestCase):
Attila Fazekasc43fec82013-04-09 23:17:52 +020060
61 config = config.TempestConfig()
Attila Fazekasdc216422013-01-29 15:12:14 +010062
Pavel Sedlák1053bd32013-04-16 16:47:40 +020063 @classmethod
64 def setUpClass(cls):
65 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
66 super(BaseTestCase, cls).setUpClass()
67
Attila Fazekasdc216422013-01-29 15:12:14 +010068
Sean Dague35a7caf2013-05-10 10:38:22 -040069def call_until_true(func, duration, sleep_for):
70 """
71 Call the given function until it returns True (and return True) or
72 until the specified duration (in seconds) elapses (and return
73 False).
74
75 :param func: A zero argument callable that returns True on success.
76 :param duration: The number of seconds for which to attempt a
77 successful call of the function.
78 :param sleep_for: The number of seconds to sleep after an unsuccessful
79 invocation of the function.
80 """
81 now = time.time()
82 timeout = now + duration
83 while now < timeout:
84 if func():
85 return True
86 LOG.debug("Sleeping for %d seconds", sleep_for)
87 time.sleep(sleep_for)
88 now = time.time()
89 return False
90
91
Attila Fazekasdc216422013-01-29 15:12:14 +010092class TestCase(BaseTestCase):
Pavel Sedláka2b757c2013-02-25 18:16:04 +010093 """Base test case class for all Tempest tests
Jay Pipes051075a2012-04-28 17:39:37 -040094
95 Contains basic setup and convenience methods
96 """
Pavel Sedláka2b757c2013-02-25 18:16:04 +010097
Jay Pipes051075a2012-04-28 17:39:37 -040098 manager_class = None
99
100 @classmethod
101 def setUpClass(cls):
102 cls.manager = cls.manager_class()
Maru Newbydec13ec2012-08-30 11:19:17 -0700103 for attr_name in cls.manager.client_attr_names:
104 # Ensure that pre-existing class attributes won't be
105 # accidentally overriden.
106 assert not hasattr(cls, attr_name)
107 client = getattr(cls.manager, attr_name)
108 setattr(cls, attr_name, client)
Jay Pipes051075a2012-04-28 17:39:37 -0400109 cls.resource_keys = {}
Attila Fazekasdc216422013-01-29 15:12:14 +0100110 cls.os_resources = []
Jay Pipes051075a2012-04-28 17:39:37 -0400111
112 def set_resource(self, key, thing):
113 LOG.debug("Adding %r to shared resources of %s" %
114 (thing, self.__class__.__name__))
115 self.resource_keys[key] = thing
Attila Fazekasdc216422013-01-29 15:12:14 +0100116 self.os_resources.append(thing)
Jay Pipes051075a2012-04-28 17:39:37 -0400117
118 def get_resource(self, key):
119 return self.resource_keys[key]
120
121 def remove_resource(self, key):
122 thing = self.resource_keys[key]
Attila Fazekasdc216422013-01-29 15:12:14 +0100123 self.os_resources.remove(thing)
Jay Pipes051075a2012-04-28 17:39:37 -0400124 del self.resource_keys[key]
125
Sean Dague35a7caf2013-05-10 10:38:22 -0400126 def status_timeout(self, things, thing_id, expected_status):
127 """
128 Given a thing and an expected status, do a loop, sleeping
129 for a configurable amount of time, checking for the
130 expected status to show. At any time, if the returned
131 status of the thing is ERROR, fail out.
132 """
133 def check_status():
134 # python-novaclient has resources available to its client
135 # that all implement a get() method taking an identifier
136 # for the singular resource to retrieve.
137 thing = things.get(thing_id)
138 new_status = thing.status
139 if new_status == 'ERROR':
Joe Gordonb5e10cd2013-07-10 15:51:12 +0000140 self.fail("%s failed to get to expected status. "
Pavel Sedlák51ed3562013-04-26 12:36:08 +0200141 "In ERROR state."
142 % thing)
Sean Dague35a7caf2013-05-10 10:38:22 -0400143 elif new_status == expected_status:
144 return True # All good.
145 LOG.debug("Waiting for %s to get to %s status. "
146 "Currently in %s status",
147 thing, expected_status, new_status)
148 conf = config.TempestConfig()
149 if not call_until_true(check_status,
150 conf.compute.build_timeout,
151 conf.compute.build_interval):
152 self.fail("Timed out waiting for thing %s to become %s"
Pavel Sedlák51ed3562013-04-26 12:36:08 +0200153 % (thing_id, expected_status))
Matthew Treinishfbf40fd2013-04-09 11:10:58 -0400154
155
Jay Pipes051075a2012-04-28 17:39:37 -0400156class ComputeFuzzClientTest(TestCase):
157
158 """
159 Base test case class for OpenStack Compute API (Nova)
160 that uses the Tempest REST fuzz client libs for calling the API.
161 """
162
163 manager_class = manager.ComputeFuzzClientManager