[PowerPC] Collect some CallLowering arguments into a struct. [NFC]
[llvm-project.git] / lldb / packages / Python / lldbsuite / test / decorators.py
blobec17cb7c25697b44104798570fa2e2ef51c0cf65
1 from __future__ import absolute_import
3 # System modules
4 from distutils.version import LooseVersion
5 from functools import wraps
6 import os
7 import platform
8 import re
9 import sys
10 import tempfile
11 import subprocess
13 # Third-party modules
14 import six
15 import unittest2
17 # LLDB modules
18 import lldb
19 from . import configuration
20 from . import test_categories
21 from . import lldbtest_config
22 from lldbsuite.test_event.event_builder import EventBuilder
23 from lldbsuite.support import funcutils
24 from lldbsuite.test import lldbplatform
25 from lldbsuite.test import lldbplatformutil
28 class DecorateMode:
29 Skip, Xfail = range(2)
32 # You can use no_match to reverse the test of the conditional that is used to match keyword
33 # arguments in the skip / xfail decorators. If oslist=["windows", "linux"] skips windows
34 # and linux, oslist=no_match(["windows", "linux"]) skips *unless* windows
35 # or linux.
36 class no_match:
38 def __init__(self, item):
39 self.item = item
42 def _check_expected_version(comparison, expected, actual):
43 def fn_leq(x, y): return x <= y
45 def fn_less(x, y): return x < y
47 def fn_geq(x, y): return x >= y
49 def fn_greater(x, y): return x > y
51 def fn_eq(x, y): return x == y
53 def fn_neq(x, y): return x != y
55 op_lookup = {
56 "==": fn_eq,
57 "=": fn_eq,
58 "!=": fn_neq,
59 "<>": fn_neq,
60 ">": fn_greater,
61 "<": fn_less,
62 ">=": fn_geq,
63 "<=": fn_leq
65 expected_str = '.'.join([str(x) for x in expected])
66 actual_str = '.'.join([str(x) for x in actual])
68 return op_lookup[comparison](
69 LooseVersion(actual_str),
70 LooseVersion(expected_str))
73 _re_pattern_type = type(re.compile(''))
74 def _match_decorator_property(expected, actual):
75 if actual is None or expected is None:
76 return True
78 if isinstance(expected, no_match):
79 return not _match_decorator_property(expected.item, actual)
80 elif isinstance(expected, (_re_pattern_type,) + six.string_types):
81 return re.search(expected, actual) is not None
82 elif hasattr(expected, "__iter__"):
83 return any([x is not None and _match_decorator_property(x, actual)
84 for x in expected])
85 else:
86 return expected == actual
89 def expectedFailure(expected_fn, bugnumber=None):
90 def expectedFailure_impl(func):
91 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
92 raise Exception(
93 "Decorator can only be used to decorate a test method")
95 @wraps(func)
96 def wrapper(*args, **kwargs):
97 self = args[0]
98 if funcutils.requires_self(expected_fn):
99 xfail_reason = expected_fn(self)
100 else:
101 xfail_reason = expected_fn()
102 if xfail_reason is not None:
103 if configuration.results_formatter_object is not None:
104 # Mark this test as expected to fail.
105 configuration.results_formatter_object.handle_event(
106 EventBuilder.event_for_mark_test_expected_failure(self))
107 xfail_func = unittest2.expectedFailure(func)
108 xfail_func(*args, **kwargs)
109 else:
110 func(*args, **kwargs)
111 return wrapper
112 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)
113 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called
114 # the first way, the first argument will be the actual function because decorators are
115 # weird like that. So this is basically a check that says "which syntax was the original
116 # function decorated with?"
117 if six.callable(bugnumber):
118 return expectedFailure_impl(bugnumber)
119 else:
120 return expectedFailure_impl
123 def skipTestIfFn(expected_fn, bugnumber=None):
124 def skipTestIfFn_impl(func):
125 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
126 raise Exception(
127 "@skipTestIfFn can only be used to decorate a test method")
129 @wraps(func)
130 def wrapper(*args, **kwargs):
131 self = args[0]
132 if funcutils.requires_self(expected_fn):
133 reason = expected_fn(self)
134 else:
135 reason = expected_fn()
137 if reason is not None:
138 self.skipTest(reason)
139 else:
140 func(*args, **kwargs)
141 return wrapper
143 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)
144 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called
145 # the first way, the first argument will be the actual function because decorators are
146 # weird like that. So this is basically a check that says "how was the
147 # decorator used"
148 if six.callable(bugnumber):
149 return skipTestIfFn_impl(bugnumber)
150 else:
151 return skipTestIfFn_impl
154 def _decorateTest(mode,
155 bugnumber=None, oslist=None, hostoslist=None,
156 compiler=None, compiler_version=None,
157 archs=None, triple=None,
158 debug_info=None,
159 swig_version=None, py_version=None,
160 macos_version=None,
161 remote=None, dwarf_version=None):
162 def fn(self):
163 skip_for_os = _match_decorator_property(
164 lldbplatform.translate(oslist), self.getPlatform())
165 skip_for_hostos = _match_decorator_property(
166 lldbplatform.translate(hostoslist),
167 lldbplatformutil.getHostPlatform())
168 skip_for_compiler = _match_decorator_property(
169 compiler, self.getCompiler()) and self.expectedCompilerVersion(compiler_version)
170 skip_for_arch = _match_decorator_property(
171 archs, self.getArchitecture())
172 skip_for_debug_info = _match_decorator_property(
173 debug_info, self.getDebugInfo())
174 skip_for_triple = _match_decorator_property(
175 triple, lldb.DBG.GetSelectedPlatform().GetTriple())
176 skip_for_remote = _match_decorator_property(
177 remote, lldb.remote_platform is not None)
179 skip_for_swig_version = (
180 swig_version is None) or (
181 not hasattr(
182 lldb,
183 'swig_version')) or (
184 _check_expected_version(
185 swig_version[0],
186 swig_version[1],
187 lldb.swig_version))
188 skip_for_py_version = (
189 py_version is None) or _check_expected_version(
190 py_version[0], py_version[1], sys.version_info)
191 skip_for_macos_version = (macos_version is None) or (
192 (platform.mac_ver()[0] != "") and (_check_expected_version(
193 macos_version[0],
194 macos_version[1],
195 platform.mac_ver()[0])))
196 skip_for_dwarf_version = (dwarf_version is None) or (
197 _check_expected_version(dwarf_version[0], dwarf_version[1],
198 self.getDwarfVersion()))
200 # For the test to be skipped, all specified (e.g. not None) parameters must be True.
201 # An unspecified parameter means "any", so those are marked skip by default. And we skip
202 # the final test if all conditions are True.
203 conditions = [(oslist, skip_for_os, "target o/s"),
204 (hostoslist, skip_for_hostos, "host o/s"),
205 (compiler, skip_for_compiler, "compiler or version"),
206 (archs, skip_for_arch, "architecture"),
207 (debug_info, skip_for_debug_info, "debug info format"),
208 (triple, skip_for_triple, "target triple"),
209 (swig_version, skip_for_swig_version, "swig version"),
210 (py_version, skip_for_py_version, "python version"),
211 (macos_version, skip_for_macos_version, "macOS version"),
212 (remote, skip_for_remote, "platform locality (remote/local)"),
213 (dwarf_version, skip_for_dwarf_version, "dwarf version")]
214 reasons = []
215 final_skip_result = True
216 for this_condition in conditions:
217 final_skip_result = final_skip_result and this_condition[1]
218 if this_condition[0] is not None and this_condition[1]:
219 reasons.append(this_condition[2])
220 reason_str = None
221 if final_skip_result:
222 mode_str = {
223 DecorateMode.Skip: "skipping",
224 DecorateMode.Xfail: "xfailing"}[mode]
225 if len(reasons) > 0:
226 reason_str = ",".join(reasons)
227 reason_str = "{} due to the following parameter(s): {}".format(
228 mode_str, reason_str)
229 else:
230 reason_str = "{} unconditionally"
231 if bugnumber is not None and not six.callable(bugnumber):
232 reason_str = reason_str + " [" + str(bugnumber) + "]"
233 return reason_str
235 if mode == DecorateMode.Skip:
236 return skipTestIfFn(fn, bugnumber)
237 elif mode == DecorateMode.Xfail:
238 return expectedFailure(fn, bugnumber)
239 else:
240 return None
242 # provide a function to xfail on defined oslist, compiler version, and archs
243 # if none is specified for any argument, that argument won't be checked and thus means for all
244 # for example,
245 # @expectedFailureAll, xfail for all platform/compiler/arch,
246 # @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture
247 # @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386
250 def expectedFailureAll(bugnumber=None,
251 oslist=None, hostoslist=None,
252 compiler=None, compiler_version=None,
253 archs=None, triple=None,
254 debug_info=None,
255 swig_version=None, py_version=None,
256 macos_version=None,
257 remote=None, dwarf_version=None):
258 return _decorateTest(DecorateMode.Xfail,
259 bugnumber=bugnumber,
260 oslist=oslist, hostoslist=hostoslist,
261 compiler=compiler, compiler_version=compiler_version,
262 archs=archs, triple=triple,
263 debug_info=debug_info,
264 swig_version=swig_version, py_version=py_version,
265 macos_version=None,
266 remote=remote,dwarf_version=dwarf_version)
269 # provide a function to skip on defined oslist, compiler version, and archs
270 # if none is specified for any argument, that argument won't be checked and thus means for all
271 # for example,
272 # @skipIf, skip for all platform/compiler/arch,
273 # @skipIf(compiler='gcc'), skip for gcc on all platform/architecture
274 # @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386
275 def skipIf(bugnumber=None,
276 oslist=None, hostoslist=None,
277 compiler=None, compiler_version=None,
278 archs=None, triple=None,
279 debug_info=None,
280 swig_version=None, py_version=None,
281 macos_version=None,
282 remote=None, dwarf_version=None):
283 return _decorateTest(DecorateMode.Skip,
284 bugnumber=bugnumber,
285 oslist=oslist, hostoslist=hostoslist,
286 compiler=compiler, compiler_version=compiler_version,
287 archs=archs, triple=triple,
288 debug_info=debug_info,
289 swig_version=swig_version, py_version=py_version,
290 macos_version=macos_version,
291 remote=remote, dwarf_version=dwarf_version)
294 def _skip_for_android(reason, api_levels, archs):
295 def impl(obj):
296 result = lldbplatformutil.match_android_device(
297 obj.getArchitecture(), valid_archs=archs, valid_api_levels=api_levels)
298 return reason if result else None
299 return impl
302 def add_test_categories(cat):
303 """Add test categories to a TestCase method"""
304 cat = test_categories.validate(cat, True)
306 def impl(func):
307 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
308 raise Exception(
309 "@add_test_categories can only be used to decorate a test method")
310 try:
311 if hasattr(func, "categories"):
312 cat.extend(func.categories)
313 setattr(func, "categories", cat)
314 except AttributeError:
315 raise Exception('Cannot assign categories to inline tests.')
317 return func
319 return impl
322 def benchmarks_test(func):
323 """Decorate the item as a benchmarks test."""
324 def should_skip_benchmarks_test():
325 return "benchmarks test"
327 # Mark this function as such to separate them from the regular tests.
328 result = skipTestIfFn(should_skip_benchmarks_test)(func)
329 result.__benchmarks_test__ = True
330 return result
333 def no_debug_info_test(func):
334 """Decorate the item as a test what don't use any debug info. If this annotation is specified
335 then the test runner won't generate a separate test for each debug info format. """
336 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
337 raise Exception(
338 "@no_debug_info_test can only be used to decorate a test method")
340 @wraps(func)
341 def wrapper(self, *args, **kwargs):
342 return func(self, *args, **kwargs)
344 # Mark this function as such to separate them from the regular tests.
345 wrapper.__no_debug_info_test__ = True
346 return wrapper
348 def apple_simulator_test(platform):
350 Decorate the test as a test requiring a simulator for a specific platform.
352 Consider that a simulator is available if you have the corresponding SDK installed.
353 The SDK identifiers for simulators are iphonesimulator, appletvsimulator, watchsimulator
355 def should_skip_simulator_test():
356 if lldbplatformutil.getHostPlatform() != 'darwin':
357 return "simulator tests are run only on darwin hosts"
358 try:
359 DEVNULL = open(os.devnull, 'w')
360 output = subprocess.check_output(["xcodebuild", "-showsdks"], stderr=DEVNULL).decode("utf-8")
361 if re.search('%ssimulator' % platform, output):
362 return None
363 else:
364 return "%s simulator is not supported on this system." % platform
365 except subprocess.CalledProcessError:
366 return "Simulators are unsupported on this system (xcodebuild failed)"
368 return skipTestIfFn(should_skip_simulator_test)
371 def debugserver_test(func):
372 """Decorate the item as a debugserver test."""
373 def should_skip_debugserver_test():
374 return "debugserver tests" if configuration.dont_do_debugserver_test else None
375 return skipTestIfFn(should_skip_debugserver_test)(func)
378 def llgs_test(func):
379 """Decorate the item as a lldb-server test."""
380 def should_skip_llgs_tests():
381 return "llgs tests" if configuration.dont_do_llgs_test else None
382 return skipTestIfFn(should_skip_llgs_tests)(func)
385 def not_remote_testsuite_ready(func):
386 """Decorate the item as a test which is not ready yet for remote testsuite."""
387 def is_remote():
388 return "Not ready for remote testsuite" if lldb.remote_platform else None
389 return skipTestIfFn(is_remote)(func)
392 def expectedFailureOS(
393 oslist,
394 bugnumber=None,
395 compilers=None,
396 debug_info=None,
397 archs=None):
398 return expectedFailureAll(
399 oslist=oslist,
400 bugnumber=bugnumber,
401 compiler=compilers,
402 archs=archs,
403 debug_info=debug_info)
406 def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None):
407 # For legacy reasons, we support both "darwin" and "macosx" as OS X
408 # triples.
409 return expectedFailureOS(
410 lldbplatform.darwin_all,
411 bugnumber,
412 compilers,
413 debug_info=debug_info)
416 def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None):
417 """ Mark a test as xfail for Android.
419 Arguments:
420 bugnumber - The LLVM pr associated with the problem.
421 api_levels - A sequence of numbers specifying the Android API levels
422 for which a test is expected to fail. None means all API level.
423 arch - A sequence of architecture names specifying the architectures
424 for which a test is expected to fail. None means all architectures.
426 return expectedFailure(
427 _skip_for_android(
428 "xfailing on android",
429 api_levels,
430 archs),
431 bugnumber)
434 def expectedFailureNetBSD(bugnumber=None):
435 return expectedFailureOS(
436 ['netbsd'],
437 bugnumber)
439 # Flakey tests get two chances to run. If they fail the first time round, the result formatter
440 # makes sure it is run one more time.
443 def expectedFlakey(expected_fn, bugnumber=None):
444 def expectedFailure_impl(func):
445 @wraps(func)
446 def wrapper(*args, **kwargs):
447 self = args[0]
448 if expected_fn(self):
449 # Send event marking test as explicitly eligible for rerunning.
450 if configuration.results_formatter_object is not None:
451 # Mark this test as rerunnable.
452 configuration.results_formatter_object.handle_event(
453 EventBuilder.event_for_mark_test_rerun_eligible(self))
454 func(*args, **kwargs)
455 return wrapper
456 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)
457 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called
458 # the first way, the first argument will be the actual function because decorators are
459 # weird like that. So this is basically a check that says "which syntax was the original
460 # function decorated with?"
461 if six.callable(bugnumber):
462 return expectedFailure_impl(bugnumber)
463 else:
464 return expectedFailure_impl
467 def expectedFlakeyOS(oslist, bugnumber=None, compilers=None):
468 def fn(self):
469 return (self.getPlatform() in oslist and
470 self.expectedCompiler(compilers))
471 return expectedFlakey(fn, bugnumber)
474 def expectedFlakeyDarwin(bugnumber=None, compilers=None):
475 # For legacy reasons, we support both "darwin" and "macosx" as OS X
476 # triples.
477 return expectedFlakeyOS(
478 lldbplatformutil.getDarwinOSTriples(),
479 bugnumber,
480 compilers)
483 def expectedFlakeyFreeBSD(bugnumber=None, compilers=None):
484 return expectedFlakeyOS(['freebsd'], bugnumber, compilers)
487 def expectedFlakeyLinux(bugnumber=None, compilers=None):
488 return expectedFlakeyOS(['linux'], bugnumber, compilers)
491 def expectedFlakeyNetBSD(bugnumber=None, compilers=None):
492 return expectedFlakeyOS(['netbsd'], bugnumber, compilers)
495 def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None):
496 return expectedFlakey(
497 _skip_for_android(
498 "flakey on android",
499 api_levels,
500 archs),
501 bugnumber)
503 def skipIfOutOfTreeDebugserver(func):
504 """Decorate the item to skip tests if using an out-of-tree debugserver."""
505 def is_out_of_tree_debugserver():
506 return "out-of-tree debugserver" if lldbtest_config.out_of_tree_debugserver else None
507 return skipTestIfFn(is_out_of_tree_debugserver)(func)
509 def skipIfRemote(func):
510 """Decorate the item to skip tests if testing remotely."""
511 def is_remote():
512 return "skip on remote platform" if lldb.remote_platform else None
513 return skipTestIfFn(is_remote)(func)
516 def skipIfNoSBHeaders(func):
517 """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers."""
518 def are_sb_headers_missing():
519 if lldb.remote_platform:
520 return "skip because SBHeaders tests make no sense remotely"
522 if lldbplatformutil.getHostPlatform() == 'darwin':
523 header = os.path.join(
524 os.environ["LLDB_LIB_DIR"],
525 'LLDB.framework',
526 'Versions',
527 'Current',
528 'Headers',
529 'LLDB.h')
530 if os.path.exists(header):
531 return None
533 header = os.path.join(
534 os.environ["LLDB_SRC"],
535 "include",
536 "lldb",
537 "API",
538 "LLDB.h")
539 if not os.path.exists(header):
540 return "skip because LLDB.h header not found"
541 return None
543 return skipTestIfFn(are_sb_headers_missing)(func)
546 def skipIfiOSSimulator(func):
547 """Decorate the item to skip tests that should be skipped on the iOS Simulator."""
548 def is_ios_simulator():
549 return "skip on the iOS Simulator" if configuration.lldb_platform_name == 'ios-simulator' else None
550 return skipTestIfFn(is_ios_simulator)(func)
552 def skipIfiOS(func):
553 return skipIfPlatform(["ios"])(func)
555 def skipIftvOS(func):
556 return skipIfPlatform(["tvos"])(func)
558 def skipIfwatchOS(func):
559 return skipIfPlatform(["watchos"])(func)
561 def skipIfbridgeOS(func):
562 return skipIfPlatform(["bridgeos"])(func)
564 def skipIfDarwinEmbedded(func):
565 """Decorate the item to skip tests that should be skipped on Darwin armv7/arm64 targets."""
566 return skipIfPlatform(
567 lldbplatform.translate(
568 lldbplatform.darwin_embedded))(func)
570 def skipIfFreeBSD(func):
571 """Decorate the item to skip tests that should be skipped on FreeBSD."""
572 return skipIfPlatform(["freebsd"])(func)
575 def skipIfNetBSD(func):
576 """Decorate the item to skip tests that should be skipped on NetBSD."""
577 return skipIfPlatform(["netbsd"])(func)
580 def skipIfDarwin(func):
581 """Decorate the item to skip tests that should be skipped on Darwin."""
582 return skipIfPlatform(
583 lldbplatform.translate(
584 lldbplatform.darwin_all))(func)
587 def skipIfLinux(func):
588 """Decorate the item to skip tests that should be skipped on Linux."""
589 return skipIfPlatform(["linux"])(func)
592 def skipIfWindows(func):
593 """Decorate the item to skip tests that should be skipped on Windows."""
594 return skipIfPlatform(["windows"])(func)
596 def skipUnlessWindows(func):
597 """Decorate the item to skip tests that should be skipped on any non-Windows platform."""
598 return skipUnlessPlatform(["windows"])(func)
601 def skipUnlessDarwin(func):
602 """Decorate the item to skip tests that should be skipped on any non Darwin platform."""
603 return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func)
605 def skipUnlessTargetAndroid(func):
606 return unittest2.skipUnless(lldbplatformutil.target_is_android(),
607 "requires target to be Android")(func)
610 def skipIfHostIncompatibleWithRemote(func):
611 """Decorate the item to skip tests if binaries built on this host are incompatible."""
613 def is_host_incompatible_with_remote(self):
614 host_arch = self.getLldbArchitecture()
615 host_platform = lldbplatformutil.getHostPlatform()
616 target_arch = self.getArchitecture()
617 target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform()
618 if not (target_arch == 'x86_64' and host_arch ==
619 'i386') and host_arch != target_arch:
620 return "skipping because target %s is not compatible with host architecture %s" % (
621 target_arch, host_arch)
622 if target_platform != host_platform:
623 return "skipping because target is %s but host is %s" % (
624 target_platform, host_platform)
625 if lldbplatformutil.match_android_device(target_arch):
626 return "skipping because target is android"
627 return None
628 return skipTestIfFn(is_host_incompatible_with_remote)(func)
631 def skipIfPlatform(oslist):
632 """Decorate the item to skip tests if running on one of the listed platforms."""
633 # This decorator cannot be ported to `skipIf` yet because it is used on entire
634 # classes, which `skipIf` explicitly forbids.
635 return unittest2.skipIf(lldbplatformutil.getPlatform() in oslist,
636 "skip on %s" % (", ".join(oslist)))
639 def skipUnlessPlatform(oslist):
640 """Decorate the item to skip tests unless running on one of the listed platforms."""
641 # This decorator cannot be ported to `skipIf` yet because it is used on entire
642 # classes, which `skipIf` explicitly forbids.
643 return unittest2.skipUnless(lldbplatformutil.getPlatform() in oslist,
644 "requires one of %s" % (", ".join(oslist)))
646 def skipUnlessArch(arch):
647 """Decorate the item to skip tests unless running on the specified architecture."""
649 def arch_doesnt_match(self):
650 target_arch = self.getArchitecture()
651 if arch != target_arch:
652 return "Test only runs on " + arch + ", but target arch is " + target_arch
653 return None
655 return skipTestIfFn(arch_doesnt_match)
657 def skipIfTargetAndroid(bugnumber=None, api_levels=None, archs=None):
658 """Decorator to skip tests when the target is Android.
660 Arguments:
661 api_levels - The API levels for which the test should be skipped. If
662 it is None, then the test will be skipped for all API levels.
663 arch - A sequence of architecture names specifying the architectures
664 for which a test is skipped. None means all architectures.
666 return skipTestIfFn(
667 _skip_for_android(
668 "skipping for android",
669 api_levels,
670 archs),
671 bugnumber)
673 def skipUnlessSupportedTypeAttribute(attr):
674 """Decorate the item to skip test unless Clang supports type __attribute__(attr)."""
675 def compiler_doesnt_support_struct_attribute(self):
676 compiler_path = self.getCompiler()
677 f = tempfile.NamedTemporaryFile()
678 cmd = [self.getCompiler(), "-x", "c++", "-c", "-o", f.name, "-"]
679 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
680 stdout, stderr = p.communicate('struct __attribute__((%s)) Test {};'%attr)
681 if attr in stderr:
682 return "Compiler does not support attribute %s"%(attr)
683 return None
684 return skipTestIfFn(compiler_doesnt_support_struct_attribute)
686 def skipUnlessHasCallSiteInfo(func):
687 """Decorate the function to skip testing unless call site info from clang is available."""
689 def is_compiler_clang_with_call_site_info(self):
690 compiler_path = self.getCompiler()
691 compiler = os.path.basename(compiler_path)
692 if not compiler.startswith("clang"):
693 return "Test requires clang as compiler"
695 f = tempfile.NamedTemporaryFile()
696 cmd = "echo 'int main() {}' | " \
697 "%s -g -glldb -O1 -Xclang -femit-debug-entry-values -S -emit-llvm -x c -o %s -" % (compiler_path, f.name)
698 if os.popen(cmd).close() is not None:
699 return "Compiler can't compile with call site info enabled"
701 with open(f.name, 'r') as ir_output_file:
702 buf = ir_output_file.read()
704 if 'DIFlagAllCallsDescribed' not in buf:
705 return "Compiler did not introduce DIFlagAllCallsDescribed IR flag"
707 return None
708 return skipTestIfFn(is_compiler_clang_with_call_site_info)(func)
710 def skipUnlessThreadSanitizer(func):
711 """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""
713 def is_compiler_clang_with_thread_sanitizer(self):
714 compiler_path = self.getCompiler()
715 compiler = os.path.basename(compiler_path)
716 if not compiler.startswith("clang"):
717 return "Test requires clang as compiler"
718 if lldbplatformutil.getPlatform() == 'windows':
719 return "TSAN tests not compatible with 'windows'"
720 # rdar://28659145 - TSAN tests don't look like they're supported on i386
721 if self.getArchitecture() == 'i386' and platform.system() == 'Darwin':
722 return "TSAN tests not compatible with i386 targets"
723 f = tempfile.NamedTemporaryFile()
724 cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name)
725 if os.popen(cmd).close() is not None:
726 return None # The compiler cannot compile at all, let's *not* skip the test
727 cmd = "echo 'int main() {}' | %s -fsanitize=thread -x c -o %s -" % (compiler_path, f.name)
728 if os.popen(cmd).close() is not None:
729 return "Compiler cannot compile with -fsanitize=thread"
730 return None
731 return skipTestIfFn(is_compiler_clang_with_thread_sanitizer)(func)
733 def skipUnlessUndefinedBehaviorSanitizer(func):
734 """Decorate the item to skip test unless -fsanitize=undefined is supported."""
736 def is_compiler_clang_with_ubsan(self):
737 # Write out a temp file which exhibits UB.
738 inputf = tempfile.NamedTemporaryFile(suffix='.c', mode='w')
739 inputf.write('int main() { int x = 0; return x / x; }\n')
740 inputf.flush()
742 # We need to write out the object into a named temp file for inspection.
743 outputf = tempfile.NamedTemporaryFile()
745 # Try to compile with ubsan turned on.
746 cmd = '%s -fsanitize=undefined %s -o %s' % (self.getCompiler(), inputf.name, outputf.name)
747 if os.popen(cmd).close() is not None:
748 return "Compiler cannot compile with -fsanitize=undefined"
750 # Check that we actually see ubsan instrumentation in the binary.
751 cmd = 'nm %s' % outputf.name
752 with os.popen(cmd) as nm_output:
753 if '___ubsan_handle_divrem_overflow' not in nm_output.read():
754 return "Division by zero instrumentation is missing"
756 # Find the ubsan dylib.
757 # FIXME: This check should go away once compiler-rt gains support for __ubsan_on_report.
758 cmd = '%s -fsanitize=undefined -x c - -o - -### 2>&1' % self.getCompiler()
759 with os.popen(cmd) as cc_output:
760 driver_jobs = cc_output.read()
761 m = re.search(r'"([^"]+libclang_rt.ubsan_osx_dynamic.dylib)"', driver_jobs)
762 if not m:
763 return "Could not find the ubsan dylib used by the driver"
764 ubsan_dylib = m.group(1)
766 # Check that the ubsan dylib has special monitor hooks.
767 cmd = 'nm -gU %s' % ubsan_dylib
768 with os.popen(cmd) as nm_output:
769 syms = nm_output.read()
770 if '___ubsan_on_report' not in syms:
771 return "Missing ___ubsan_on_report"
772 if '___ubsan_get_current_report_data' not in syms:
773 return "Missing ___ubsan_get_current_report_data"
775 # OK, this dylib + compiler works for us.
776 return None
778 return skipTestIfFn(is_compiler_clang_with_ubsan)(func)
780 def skipUnlessAddressSanitizer(func):
781 """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""
783 def is_compiler_with_address_sanitizer(self):
784 compiler_path = self.getCompiler()
785 compiler = os.path.basename(compiler_path)
786 f = tempfile.NamedTemporaryFile()
787 if lldbplatformutil.getPlatform() == 'windows':
788 return "ASAN tests not compatible with 'windows'"
789 cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name)
790 if os.popen(cmd).close() is not None:
791 return None # The compiler cannot compile at all, let's *not* skip the test
792 cmd = "echo 'int main() {}' | %s -fsanitize=address -x c -o %s -" % (compiler_path, f.name)
793 if os.popen(cmd).close() is not None:
794 return "Compiler cannot compile with -fsanitize=address"
795 return None
796 return skipTestIfFn(is_compiler_with_address_sanitizer)(func)
798 def _get_bool_config_skip_if_decorator(key):
799 config = lldb.SBDebugger.GetBuildConfiguration()
800 value_node = config.GetValueForKey(key)
801 fail_value = True # More likely to notice if something goes wrong
802 have = value_node.GetValueForKey("value").GetBooleanValue(fail_value)
803 return unittest2.skipIf(not have, "requires " + key)
805 def skipIfCursesSupportMissing(func):
806 return _get_bool_config_skip_if_decorator("curses")(func)
808 def skipIfXmlSupportMissing(func):
809 return _get_bool_config_skip_if_decorator("xml")(func)
811 def skipIfEditlineSupportMissing(func):
812 return _get_bool_config_skip_if_decorator("editline")(func)
814 def skipIfLLVMTargetMissing(target):
815 config = lldb.SBDebugger.GetBuildConfiguration()
816 targets = config.GetValueForKey("targets").GetValueForKey("value")
817 found = False
818 for i in range(targets.GetSize()):
819 if targets.GetItemAtIndex(i).GetStringValue(99) == target:
820 found = True
821 break
823 return unittest2.skipIf(not found, "requires " + target)
825 # Call sysctl on darwin to see if a specified hardware feature is available on this machine.
826 def skipUnlessFeature(feature):
827 def is_feature_enabled(self):
828 if platform.system() == 'Darwin':
829 try:
830 DEVNULL = open(os.devnull, 'w')
831 output = subprocess.check_output(["/usr/sbin/sysctl", feature], stderr=DEVNULL).decode("utf-8")
832 # If 'feature: 1' was output, then this feature is available and
833 # the test should not be skipped.
834 if re.match('%s: 1\s*' % feature, output):
835 return None
836 else:
837 return "%s is not supported on this system." % feature
838 except subprocess.CalledProcessError:
839 return "%s is not supported on this system." % feature
840 return skipTestIfFn(is_feature_enabled)
842 def skipIfAsan(func):
843 """Skip this test if the environment is set up to run LLDB itself under ASAN."""
844 def is_asan():
845 if ('ASAN_OPTIONS' in os.environ):
846 return "ASAN unsupported"
847 return None
848 return skipTestIfFn(is_asan)(func)