blob: e99dd24e6c041e29d29bb4c8df940b9ff1ab3149 [file] [log] [blame]
Matthew Treinish9e26ca82016-02-23 11:43:20 -05001# Copyright 2015 Hewlett-Packard Development Company, L.P.
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
15import functools
16import uuid
17
Jordan Pittierc5665a62017-04-12 16:42:53 +020018from oslo_log import log as logging
Matthew Treinish9e26ca82016-02-23 11:43:20 -050019import six
20import testtools
21
Jordan Pittierc5665a62017-04-12 16:42:53 +020022LOG = logging.getLogger(__name__)
23
Matthew Treinish9e26ca82016-02-23 11:43:20 -050024
25def skip_because(*args, **kwargs):
26 """A decorator useful to skip tests hitting known bugs
27
28 @param bug: bug number causing the test to skip
29 @param condition: optional condition to be True for the skip to have place
30 """
31 def decorator(f):
32 @functools.wraps(f)
lkuchlana2addfe2017-11-13 12:06:34 +020033 def wrapper(*func_args, **func_kwargs):
Matthew Treinish9e26ca82016-02-23 11:43:20 -050034 skip = False
35 if "condition" in kwargs:
36 if kwargs["condition"] is True:
37 skip = True
38 else:
39 skip = True
40 if "bug" in kwargs and skip is True:
41 if not kwargs['bug'].isdigit():
42 raise ValueError('bug must be a valid bug number')
43 msg = "Skipped until Bug: %s is resolved." % kwargs["bug"]
44 raise testtools.TestCase.skipException(msg)
lkuchlana2addfe2017-11-13 12:06:34 +020045 return f(*func_args, **func_kwargs)
Matthew Treinish9e26ca82016-02-23 11:43:20 -050046 return wrapper
47 return decorator
48
49
Jordan Pittierc5665a62017-04-12 16:42:53 +020050def related_bug(bug, status_code=None):
51 """A decorator useful to know solutions from launchpad bug reports
52
53 @param bug: The launchpad bug number causing the test
54 @param status_code: The status code related to the bug report
55 """
56 def decorator(f):
57 @functools.wraps(f)
lkuchlanf5c19052017-11-23 09:26:55 +020058 def wrapper(*func_args, **func_kwargs):
Jordan Pittierc5665a62017-04-12 16:42:53 +020059 try:
lkuchlanf5c19052017-11-23 09:26:55 +020060 return f(*func_args, **func_kwargs)
Jordan Pittierc5665a62017-04-12 16:42:53 +020061 except Exception as exc:
62 exc_status_code = getattr(exc, 'status_code', None)
63 if status_code is None or status_code == exc_status_code:
64 LOG.error('Hints: This test was made for the bug %s. '
65 'The failure could be related to '
66 'https://launchpad.net/bugs/%s', bug, bug)
67 raise exc
68 return wrapper
69 return decorator
70
71
Matthew Treinish9e26ca82016-02-23 11:43:20 -050072def idempotent_id(id):
73 """Stub for metadata decorator"""
74 if not isinstance(id, six.string_types):
75 raise TypeError('Test idempotent_id must be string not %s'
76 '' % type(id).__name__)
77 uuid.UUID(id)
78
79 def decorator(f):
80 f = testtools.testcase.attr('id-%s' % id)(f)
81 if f.__doc__:
82 f.__doc__ = 'Test idempotent id: %s\n%s' % (id, f.__doc__)
83 else:
84 f.__doc__ = 'Test idempotent id: %s' % id
85 return f
86 return decorator
87
88
Jordan Pittier3b46d272017-04-12 16:17:28 +020089def attr(**kwargs):
90 """A decorator which applies the testtools attr decorator
91
92 This decorator applies the testtools.testcase.attr if it is in the list of
93 attributes to testtools we want to apply.
94 """
95
96 def decorator(f):
97 if 'type' in kwargs and isinstance(kwargs['type'], str):
98 f = testtools.testcase.attr(kwargs['type'])(f)
99 elif 'type' in kwargs and isinstance(kwargs['type'], list):
100 for attr in kwargs['type']:
101 f = testtools.testcase.attr(attr)(f)
102 return f
103
104 return decorator