blob: 2a9f3a92a02228a861b25851ba8b38518edcef81 [file] [log] [blame]
Jordan Pittier9e227c52016-02-09 14:35:18 +01001# Copyright 2016 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15import inspect
16import re
Jordan Pittier35a63752016-08-30 13:09:12 +020017import time
Jordan Pittier9e227c52016-02-09 14:35:18 +010018
19from oslo_log import log as logging
20
21from tempest.lib import exceptions
22
23LOG = logging.getLogger(__name__)
24
25
26def find_test_caller():
27 """Find the caller class and test name.
28
29 Because we know that the interesting things that call us are
30 test_* methods, and various kinds of setUp / tearDown, we
31 can look through the call stack to find appropriate methods,
32 and the class we were in when those were called.
33 """
34 caller_name = None
35 names = []
36 frame = inspect.currentframe()
37 is_cleanup = False
38 # Start climbing the ladder until we hit a good method
39 while True:
40 try:
41 frame = frame.f_back
42 name = frame.f_code.co_name
43 names.append(name)
44 if re.search("^(test_|setUp|tearDown)", name):
45 cname = ""
46 if 'self' in frame.f_locals:
47 cname = frame.f_locals['self'].__class__.__name__
48 if 'cls' in frame.f_locals:
49 cname = frame.f_locals['cls'].__name__
50 caller_name = cname + ":" + name
51 break
52 elif re.search("^_run_cleanup", name):
53 is_cleanup = True
54 elif name == 'main':
55 caller_name = 'main'
56 break
57 else:
58 cname = ""
59 if 'self' in frame.f_locals:
60 cname = frame.f_locals['self'].__class__.__name__
61 if 'cls' in frame.f_locals:
62 cname = frame.f_locals['cls'].__name__
63
64 # the fact that we are running cleanups is indicated pretty
65 # deep in the stack, so if we see that we want to just
66 # start looking for a real class name, and declare victory
67 # once we do.
68 if is_cleanup and cname:
69 if not re.search("^RunTest", cname):
70 caller_name = cname + ":_run_cleanups"
71 break
72 except Exception:
73 break
74 # prevents frame leaks
75 del frame
76 if caller_name is None:
Jordan Pittier525ec712016-12-07 17:51:26 +010077 LOG.debug("Sane call name not found in %s", names)
Jordan Pittier9e227c52016-02-09 14:35:18 +010078 return caller_name
79
80
81def call_and_ignore_notfound_exc(func, *args, **kwargs):
82 """Call the given function and pass if a `NotFound` exception is raised."""
83 try:
84 return func(*args, **kwargs)
85 except exceptions.NotFound:
86 pass
Jordan Pittier35a63752016-08-30 13:09:12 +020087
88
zhuflcf52e342017-11-13 10:05:13 +080089def call_until_true(func, duration, sleep_for, *args, **kwargs):
Jordan Pittier35a63752016-08-30 13:09:12 +020090 """Call the given function until it returns True (and return True)
91
92 or until the specified duration (in seconds) elapses (and return False).
93
zhuflcf52e342017-11-13 10:05:13 +080094 :param func: A callable that returns True on success.
Jordan Pittier35a63752016-08-30 13:09:12 +020095 :param duration: The number of seconds for which to attempt a
96 successful call of the function.
97 :param sleep_for: The number of seconds to sleep after an unsuccessful
98 invocation of the function.
zhuflcf52e342017-11-13 10:05:13 +080099 :param args: args that are passed to func.
100 :param kwargs: kwargs that are passed to func.
Jordan Pittier35a63752016-08-30 13:09:12 +0200101 """
102 now = time.time()
zhuflcf52e342017-11-13 10:05:13 +0800103 begin_time = now
Jordan Pittier35a63752016-08-30 13:09:12 +0200104 timeout = now + duration
zhufleffafa32018-01-19 13:37:05 +0800105 func_name = getattr(func, '__name__', getattr(func.__class__, '__name__'))
Jordan Pittier35a63752016-08-30 13:09:12 +0200106 while now < timeout:
zhuflcf52e342017-11-13 10:05:13 +0800107 if func(*args, **kwargs):
108 LOG.debug("Call %s returns true in %f seconds",
zhufleffafa32018-01-19 13:37:05 +0800109 func_name, time.time() - begin_time)
Jordan Pittier35a63752016-08-30 13:09:12 +0200110 return True
111 time.sleep(sleep_for)
112 now = time.time()
zhufleffafa32018-01-19 13:37:05 +0800113 LOG.debug("Call %s returns false in %f seconds", func_name, duration)
Jordan Pittier35a63752016-08-30 13:09:12 +0200114 return False