Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / packages / Python / lldbsuite / test / decorators.py
blobb8fea1e02e864debd598af12cc4e5e688d21f0fb
1 # System modules
2 from distutils.version import LooseVersion
3 from functools import wraps
4 import ctypes
5 import locale
6 import os
7 import platform
8 import re
9 import sys
10 import tempfile
11 import subprocess
13 # Third-party modules
14 import unittest2
16 # LLDB modules
17 import lldb
18 from . import configuration
19 from . import test_categories
20 from . import lldbtest_config
21 from lldbsuite.support import funcutils
22 from lldbsuite.test import lldbplatform
23 from lldbsuite.test import lldbplatformutil
26 class DecorateMode:
27 Skip, Xfail = range(2)
30 # You can use no_match to reverse the test of the conditional that is used to match keyword
31 # arguments in the skip / xfail decorators. If oslist=["windows", "linux"] skips windows
32 # and linux, oslist=no_match(["windows", "linux"]) skips *unless* windows
33 # or linux.
34 class no_match:
35 def __init__(self, item):
36 self.item = item
39 def _check_expected_version(comparison, expected, actual):
40 def fn_leq(x, y):
41 return x <= y
43 def fn_less(x, y):
44 return x < y
46 def fn_geq(x, y):
47 return x >= y
49 def fn_greater(x, y):
50 return x > y
52 def fn_eq(x, y):
53 return x == y
55 def fn_neq(x, y):
56 return x != y
58 op_lookup = {
59 "==": fn_eq,
60 "=": fn_eq,
61 "!=": fn_neq,
62 "<>": fn_neq,
63 ">": fn_greater,
64 "<": fn_less,
65 ">=": fn_geq,
66 "<=": fn_leq,
68 expected_str = ".".join([str(x) for x in expected])
69 actual_str = ".".join([str(x) for x in actual])
71 return op_lookup[comparison](LooseVersion(actual_str), LooseVersion(expected_str))
74 def _match_decorator_property(expected, actual):
75 if expected is None:
76 return True
78 if actual is None:
79 return False
81 if isinstance(expected, no_match):
82 return not _match_decorator_property(expected.item, actual)
84 # Python 3.6 doesn't declare a `re.Pattern` type, get the dynamic type.
85 pattern_type = type(re.compile(""))
86 if isinstance(expected, (pattern_type, str)):
87 return re.search(expected, actual) is not None
89 if hasattr(expected, "__iter__"):
90 return any(
91 [x is not None and _match_decorator_property(x, actual) for x in expected]
94 return expected == actual
97 def _compiler_supports(
98 compiler, flag, source="int main() {}", output_file=tempfile.NamedTemporaryFile()
100 """Test whether the compiler supports the given flag."""
101 if platform.system() == "Darwin":
102 compiler = "xcrun " + compiler
103 try:
104 cmd = "echo '%s' | %s %s -x c -o %s -" % (
105 source,
106 compiler,
107 flag,
108 output_file.name,
110 subprocess.check_call(cmd, shell=True)
111 except subprocess.CalledProcessError:
112 return False
113 return True
116 def expectedFailure(func):
117 return unittest2.expectedFailure(func)
120 def expectedFailureIfFn(expected_fn, bugnumber=None):
121 def expectedFailure_impl(func):
122 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
123 raise Exception("Decorator can only be used to decorate a test method")
125 @wraps(func)
126 def wrapper(*args, **kwargs):
127 xfail_reason = expected_fn(*args, **kwargs)
128 if xfail_reason is not None:
129 xfail_func = unittest2.expectedFailure(func)
130 xfail_func(*args, **kwargs)
131 else:
132 func(*args, **kwargs)
134 return wrapper
136 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)
137 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called
138 # the first way, the first argument will be the actual function because decorators are
139 # weird like that. So this is basically a check that says "which syntax was the original
140 # function decorated with?"
141 if callable(bugnumber):
142 return expectedFailure_impl(bugnumber)
143 else:
144 return expectedFailure_impl
147 def skipTestIfFn(expected_fn, bugnumber=None):
148 def skipTestIfFn_impl(func):
149 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
150 reason = expected_fn()
151 # The return value is the reason (or None if we don't skip), so
152 # reason is used for both args.
153 return unittest2.skipIf(condition=reason, reason=reason)(func)
155 @wraps(func)
156 def wrapper(*args, **kwargs):
157 self = args[0]
158 if funcutils.requires_self(expected_fn):
159 reason = expected_fn(self)
160 else:
161 reason = expected_fn()
163 if reason is not None:
164 self.skipTest(reason)
165 else:
166 return func(*args, **kwargs)
168 return wrapper
170 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)
171 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called
172 # the first way, the first argument will be the actual function because decorators are
173 # weird like that. So this is basically a check that says "how was the
174 # decorator used"
175 if callable(bugnumber):
176 return skipTestIfFn_impl(bugnumber)
177 else:
178 return skipTestIfFn_impl
181 def _decorateTest(
182 mode,
183 bugnumber=None,
184 oslist=None,
185 hostoslist=None,
186 compiler=None,
187 compiler_version=None,
188 archs=None,
189 triple=None,
190 debug_info=None,
191 swig_version=None,
192 py_version=None,
193 macos_version=None,
194 remote=None,
195 dwarf_version=None,
196 setting=None,
198 def fn(self):
199 skip_for_os = _match_decorator_property(
200 lldbplatform.translate(oslist), self.getPlatform()
202 skip_for_hostos = _match_decorator_property(
203 lldbplatform.translate(hostoslist), lldbplatformutil.getHostPlatform()
205 skip_for_compiler = _match_decorator_property(
206 compiler, self.getCompiler()
207 ) and self.expectedCompilerVersion(compiler_version)
208 skip_for_arch = _match_decorator_property(archs, self.getArchitecture())
209 skip_for_debug_info = _match_decorator_property(debug_info, self.getDebugInfo())
210 skip_for_triple = _match_decorator_property(
211 triple, lldb.selected_platform.GetTriple()
213 skip_for_remote = _match_decorator_property(
214 remote, lldb.remote_platform is not None
217 skip_for_swig_version = (
218 (swig_version is None)
219 or (not hasattr(lldb, "swig_version"))
220 or (
221 _check_expected_version(
222 swig_version[0], swig_version[1], lldb.swig_version
226 skip_for_py_version = (py_version is None) or _check_expected_version(
227 py_version[0], py_version[1], sys.version_info
229 skip_for_macos_version = (macos_version is None) or (
230 (platform.mac_ver()[0] != "")
231 and (
232 _check_expected_version(
233 macos_version[0], macos_version[1], platform.mac_ver()[0]
237 skip_for_dwarf_version = (dwarf_version is None) or (
238 _check_expected_version(
239 dwarf_version[0], dwarf_version[1], self.getDwarfVersion()
242 skip_for_setting = (setting is None) or (setting in configuration.settings)
244 # For the test to be skipped, all specified (e.g. not None) parameters must be True.
245 # An unspecified parameter means "any", so those are marked skip by default. And we skip
246 # the final test if all conditions are True.
247 conditions = [
248 (oslist, skip_for_os, "target o/s"),
249 (hostoslist, skip_for_hostos, "host o/s"),
250 (compiler, skip_for_compiler, "compiler or version"),
251 (archs, skip_for_arch, "architecture"),
252 (debug_info, skip_for_debug_info, "debug info format"),
253 (triple, skip_for_triple, "target triple"),
254 (swig_version, skip_for_swig_version, "swig version"),
255 (py_version, skip_for_py_version, "python version"),
256 (macos_version, skip_for_macos_version, "macOS version"),
257 (remote, skip_for_remote, "platform locality (remote/local)"),
258 (dwarf_version, skip_for_dwarf_version, "dwarf version"),
259 (setting, skip_for_setting, "setting"),
261 reasons = []
262 final_skip_result = True
263 for this_condition in conditions:
264 final_skip_result = final_skip_result and this_condition[1]
265 if this_condition[0] is not None and this_condition[1]:
266 reasons.append(this_condition[2])
267 reason_str = None
268 if final_skip_result:
269 mode_str = {DecorateMode.Skip: "skipping", DecorateMode.Xfail: "xfailing"}[
270 mode
272 if len(reasons) > 0:
273 reason_str = ",".join(reasons)
274 reason_str = "{} due to the following parameter(s): {}".format(
275 mode_str, reason_str
277 else:
278 reason_str = "{} unconditionally".format(mode_str)
279 if bugnumber is not None and not callable(bugnumber):
280 reason_str = reason_str + " [" + str(bugnumber) + "]"
281 return reason_str
283 if mode == DecorateMode.Skip:
284 return skipTestIfFn(fn, bugnumber)
285 elif mode == DecorateMode.Xfail:
286 return expectedFailureIfFn(fn, bugnumber)
287 else:
288 return None
291 # provide a function to xfail on defined oslist, compiler version, and archs
292 # if none is specified for any argument, that argument won't be checked and thus means for all
293 # for example,
294 # @expectedFailureAll, xfail for all platform/compiler/arch,
295 # @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture
296 # @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386
299 def expectedFailureAll(
300 bugnumber=None,
301 oslist=None,
302 hostoslist=None,
303 compiler=None,
304 compiler_version=None,
305 archs=None,
306 triple=None,
307 debug_info=None,
308 swig_version=None,
309 py_version=None,
310 macos_version=None,
311 remote=None,
312 dwarf_version=None,
313 setting=None,
315 return _decorateTest(
316 DecorateMode.Xfail,
317 bugnumber=bugnumber,
318 oslist=oslist,
319 hostoslist=hostoslist,
320 compiler=compiler,
321 compiler_version=compiler_version,
322 archs=archs,
323 triple=triple,
324 debug_info=debug_info,
325 swig_version=swig_version,
326 py_version=py_version,
327 macos_version=macos_version,
328 remote=remote,
329 dwarf_version=dwarf_version,
330 setting=setting,
334 # provide a function to skip on defined oslist, compiler version, and archs
335 # if none is specified for any argument, that argument won't be checked and thus means for all
336 # for example,
337 # @skipIf, skip for all platform/compiler/arch,
338 # @skipIf(compiler='gcc'), skip for gcc on all platform/architecture
339 # @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386
340 def skipIf(
341 bugnumber=None,
342 oslist=None,
343 hostoslist=None,
344 compiler=None,
345 compiler_version=None,
346 archs=None,
347 triple=None,
348 debug_info=None,
349 swig_version=None,
350 py_version=None,
351 macos_version=None,
352 remote=None,
353 dwarf_version=None,
354 setting=None,
356 return _decorateTest(
357 DecorateMode.Skip,
358 bugnumber=bugnumber,
359 oslist=oslist,
360 hostoslist=hostoslist,
361 compiler=compiler,
362 compiler_version=compiler_version,
363 archs=archs,
364 triple=triple,
365 debug_info=debug_info,
366 swig_version=swig_version,
367 py_version=py_version,
368 macos_version=macos_version,
369 remote=remote,
370 dwarf_version=dwarf_version,
371 setting=setting,
375 def _skip_for_android(reason, api_levels, archs):
376 def impl(obj):
377 result = lldbplatformutil.match_android_device(
378 obj.getArchitecture(), valid_archs=archs, valid_api_levels=api_levels
380 return reason if result else None
382 return impl
385 def add_test_categories(cat):
386 """Add test categories to a TestCase method"""
387 cat = test_categories.validate(cat, True)
389 def impl(func):
390 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
391 raise Exception(
392 "@add_test_categories can only be used to decorate a test method"
394 try:
395 if hasattr(func, "categories"):
396 cat.extend(func.categories)
397 setattr(func, "categories", cat)
398 except AttributeError:
399 raise Exception("Cannot assign categories to inline tests.")
401 return func
403 return impl
406 def benchmarks_test(func):
407 """Decorate the item as a benchmarks test."""
409 def should_skip_benchmarks_test():
410 return "benchmarks test"
412 # Mark this function as such to separate them from the regular tests.
413 result = skipTestIfFn(should_skip_benchmarks_test)(func)
414 result.__benchmarks_test__ = True
415 return result
418 def no_debug_info_test(func):
419 """Decorate the item as a test what don't use any debug info. If this annotation is specified
420 then the test runner won't generate a separate test for each debug info format."""
421 if isinstance(func, type) and issubclass(func, unittest2.TestCase):
422 raise Exception(
423 "@no_debug_info_test can only be used to decorate a test method"
426 @wraps(func)
427 def wrapper(self, *args, **kwargs):
428 return func(self, *args, **kwargs)
430 # Mark this function as such to separate them from the regular tests.
431 wrapper.__no_debug_info_test__ = True
432 return wrapper
435 def apple_simulator_test(platform):
437 Decorate the test as a test requiring a simulator for a specific platform.
439 Consider that a simulator is available if you have the corresponding SDK installed.
440 The SDK identifiers for simulators are iphonesimulator, appletvsimulator, watchsimulator
443 def should_skip_simulator_test():
444 if lldbplatformutil.getHostPlatform() not in ["darwin", "macosx"]:
445 return "simulator tests are run only on darwin hosts."
446 try:
447 DEVNULL = open(os.devnull, "w")
448 output = subprocess.check_output(
449 ["xcodebuild", "-showsdks"], stderr=DEVNULL
450 ).decode("utf-8")
451 if re.search("%ssimulator" % platform, output):
452 return None
453 else:
454 return "%s simulator is not supported on this system." % platform
455 except subprocess.CalledProcessError:
456 return "Simulators are unsupported on this system (xcodebuild failed)"
458 return skipTestIfFn(should_skip_simulator_test)
461 def debugserver_test(func):
462 """Decorate the item as a debugserver test."""
463 return add_test_categories(["debugserver"])(func)
466 def llgs_test(func):
467 """Decorate the item as a lldb-server test."""
468 return add_test_categories(["llgs"])(func)
471 def expectedFailureOS(
472 oslist, bugnumber=None, compilers=None, debug_info=None, archs=None
474 return expectedFailureAll(
475 oslist=oslist,
476 bugnumber=bugnumber,
477 compiler=compilers,
478 archs=archs,
479 debug_info=debug_info,
483 def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None, archs=None):
484 # For legacy reasons, we support both "darwin" and "macosx" as OS X
485 # triples.
486 return expectedFailureOS(
487 lldbplatform.darwin_all,
488 bugnumber,
489 compilers,
490 debug_info=debug_info,
491 archs=archs,
495 def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None):
496 """Mark a test as xfail for Android.
498 Arguments:
499 bugnumber - The LLVM pr associated with the problem.
500 api_levels - A sequence of numbers specifying the Android API levels
501 for which a test is expected to fail. None means all API level.
502 arch - A sequence of architecture names specifying the architectures
503 for which a test is expected to fail. None means all architectures.
505 return expectedFailureIfFn(
506 _skip_for_android("xfailing on android", api_levels, archs), bugnumber
510 def expectedFailureNetBSD(bugnumber=None):
511 return expectedFailureOS(["netbsd"], bugnumber)
514 def expectedFailureWindows(bugnumber=None):
515 return expectedFailureOS(["windows"], bugnumber)
518 # TODO: This decorator does not do anything. Remove it.
519 def expectedFlakey(expected_fn, bugnumber=None):
520 def expectedFailure_impl(func):
521 @wraps(func)
522 def wrapper(*args, **kwargs):
523 func(*args, **kwargs)
525 return wrapper
527 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)
528 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called
529 # the first way, the first argument will be the actual function because decorators are
530 # weird like that. So this is basically a check that says "which syntax was the original
531 # function decorated with?"
532 if callable(bugnumber):
533 return expectedFailure_impl(bugnumber)
534 else:
535 return expectedFailure_impl
538 def expectedFlakeyOS(oslist, bugnumber=None, compilers=None):
539 def fn(self):
540 return self.getPlatform() in oslist and self.expectedCompiler(compilers)
542 return expectedFlakey(fn, bugnumber)
545 def expectedFlakeyDarwin(bugnumber=None, compilers=None):
546 # For legacy reasons, we support both "darwin" and "macosx" as OS X
547 # triples.
548 return expectedFlakeyOS(lldbplatformutil.getDarwinOSTriples(), bugnumber, compilers)
551 def expectedFlakeyFreeBSD(bugnumber=None, compilers=None):
552 return expectedFlakeyOS(["freebsd"], bugnumber, compilers)
555 def expectedFlakeyLinux(bugnumber=None, compilers=None):
556 return expectedFlakeyOS(["linux"], bugnumber, compilers)
559 def expectedFlakeyNetBSD(bugnumber=None, compilers=None):
560 return expectedFlakeyOS(["netbsd"], bugnumber, compilers)
563 def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None):
564 return expectedFlakey(
565 _skip_for_android("flakey on android", api_levels, archs), bugnumber
569 def skipIfOutOfTreeDebugserver(func):
570 """Decorate the item to skip tests if using an out-of-tree debugserver."""
572 def is_out_of_tree_debugserver():
573 return (
574 "out-of-tree debugserver"
575 if lldbtest_config.out_of_tree_debugserver
576 else None
579 return skipTestIfFn(is_out_of_tree_debugserver)(func)
582 def skipIfRemote(func):
583 """Decorate the item to skip tests if testing remotely."""
584 return unittest2.skipIf(lldb.remote_platform, "skip on remote platform")(func)
587 def skipIfNoSBHeaders(func):
588 """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers."""
590 def are_sb_headers_missing():
591 if lldb.remote_platform:
592 return "skip because SBHeaders tests make no sense remotely"
594 if (
595 lldbplatformutil.getHostPlatform() == "darwin"
596 and configuration.lldb_framework_path
598 header = os.path.join(
599 configuration.lldb_framework_path,
600 "Versions",
601 "Current",
602 "Headers",
603 "LLDB.h",
605 if os.path.exists(header):
606 return None
608 header = os.path.join(
609 os.environ["LLDB_SRC"], "include", "lldb", "API", "LLDB.h"
611 if not os.path.exists(header):
612 return "skip because LLDB.h header not found"
613 return None
615 return skipTestIfFn(are_sb_headers_missing)(func)
618 def skipIfRosetta(bugnumber):
619 """Skip a test when running the testsuite on macOS under the Rosetta translation layer."""
621 def is_running_rosetta(self):
622 if lldbplatformutil.getPlatform() in ["darwin", "macosx"]:
623 if (platform.uname()[5] == "arm") and (self.getArchitecture() == "x86_64"):
624 return "skipped under Rosetta"
625 return None
627 return skipTestIfFn(is_running_rosetta)
630 def skipIfiOSSimulator(func):
631 """Decorate the item to skip tests that should be skipped on the iOS Simulator."""
633 def is_ios_simulator():
634 return (
635 "skip on the iOS Simulator"
636 if configuration.lldb_platform_name == "ios-simulator"
637 else None
640 return skipTestIfFn(is_ios_simulator)(func)
643 def skipIfiOS(func):
644 return skipIfPlatform(lldbplatform.translate(lldbplatform.ios))(func)
647 def skipIftvOS(func):
648 return skipIfPlatform(lldbplatform.translate(lldbplatform.tvos))(func)
651 def skipIfwatchOS(func):
652 return skipIfPlatform(lldbplatform.translate(lldbplatform.watchos))(func)
655 def skipIfbridgeOS(func):
656 return skipIfPlatform(lldbplatform.translate(lldbplatform.bridgeos))(func)
659 def skipIfDarwinEmbedded(func):
660 """Decorate the item to skip tests that should be skipped on Darwin armv7/arm64 targets."""
661 return skipIfPlatform(lldbplatform.translate(lldbplatform.darwin_embedded))(func)
664 def skipIfDarwinSimulator(func):
665 """Decorate the item to skip tests that should be skipped on Darwin simulator targets."""
666 return skipIfPlatform(lldbplatform.translate(lldbplatform.darwin_simulator))(func)
669 def skipIfFreeBSD(func):
670 """Decorate the item to skip tests that should be skipped on FreeBSD."""
671 return skipIfPlatform(["freebsd"])(func)
674 def skipIfNetBSD(func):
675 """Decorate the item to skip tests that should be skipped on NetBSD."""
676 return skipIfPlatform(["netbsd"])(func)
679 def skipIfDarwin(func):
680 """Decorate the item to skip tests that should be skipped on Darwin."""
681 return skipIfPlatform(lldbplatform.translate(lldbplatform.darwin_all))(func)
684 def skipIfLinux(func):
685 """Decorate the item to skip tests that should be skipped on Linux."""
686 return skipIfPlatform(["linux"])(func)
689 def skipIfWindows(func):
690 """Decorate the item to skip tests that should be skipped on Windows."""
691 return skipIfPlatform(["windows"])(func)
694 def skipIfWindowsAndNonEnglish(func):
695 """Decorate the item to skip tests that should be skipped on non-English locales on Windows."""
697 def is_Windows_NonEnglish(self):
698 if sys.platform != "win32":
699 return None
700 kernel = ctypes.windll.kernel32
701 if locale.windows_locale[kernel.GetUserDefaultUILanguage()] == "en_US":
702 return None
703 return "skipping non-English Windows locale"
705 return skipTestIfFn(is_Windows_NonEnglish)(func)
708 def skipUnlessWindows(func):
709 """Decorate the item to skip tests that should be skipped on any non-Windows platform."""
710 return skipUnlessPlatform(["windows"])(func)
713 def skipUnlessDarwin(func):
714 """Decorate the item to skip tests that should be skipped on any non Darwin platform."""
715 return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func)
718 def skipUnlessTargetAndroid(func):
719 return unittest2.skipUnless(
720 lldbplatformutil.target_is_android(), "requires target to be Android"
721 )(func)
724 def skipIfHostIncompatibleWithRemote(func):
725 """Decorate the item to skip tests if binaries built on this host are incompatible."""
727 def is_host_incompatible_with_remote(self):
728 host_arch = self.getLldbArchitecture()
729 host_platform = lldbplatformutil.getHostPlatform()
730 target_arch = self.getArchitecture()
731 target_platform = "darwin" if self.platformIsDarwin() else self.getPlatform()
732 if (
733 not (target_arch == "x86_64" and host_arch == "i386")
734 and host_arch != target_arch
736 return (
737 "skipping because target %s is not compatible with host architecture %s"
738 % (target_arch, host_arch)
740 if target_platform != host_platform:
741 return "skipping because target is %s but host is %s" % (
742 target_platform,
743 host_platform,
745 if lldbplatformutil.match_android_device(target_arch):
746 return "skipping because target is android"
747 return None
749 return skipTestIfFn(is_host_incompatible_with_remote)(func)
752 def skipIfPlatform(oslist):
753 """Decorate the item to skip tests if running on one of the listed platforms."""
754 # This decorator cannot be ported to `skipIf` yet because it is used on entire
755 # classes, which `skipIf` explicitly forbids.
756 return unittest2.skipIf(
757 lldbplatformutil.getPlatform() in oslist, "skip on %s" % (", ".join(oslist))
761 def skipUnlessPlatform(oslist):
762 """Decorate the item to skip tests unless running on one of the listed platforms."""
763 # This decorator cannot be ported to `skipIf` yet because it is used on entire
764 # classes, which `skipIf` explicitly forbids.
765 return unittest2.skipUnless(
766 lldbplatformutil.getPlatform() in oslist,
767 "requires one of %s" % (", ".join(oslist)),
771 def skipUnlessArch(arch):
772 """Decorate the item to skip tests unless running on the specified architecture."""
774 def arch_doesnt_match(self):
775 target_arch = self.getArchitecture()
776 if arch != target_arch:
777 return "Test only runs on " + arch + ", but target arch is " + target_arch
778 return None
780 return skipTestIfFn(arch_doesnt_match)
783 def skipIfTargetAndroid(bugnumber=None, api_levels=None, archs=None):
784 """Decorator to skip tests when the target is Android.
786 Arguments:
787 api_levels - The API levels for which the test should be skipped. If
788 it is None, then the test will be skipped for all API levels.
789 arch - A sequence of architecture names specifying the architectures
790 for which a test is skipped. None means all architectures.
792 return skipTestIfFn(
793 _skip_for_android("skipping for android", api_levels, archs), bugnumber
797 def skipUnlessAppleSilicon(func):
798 """Decorate the item to skip tests unless running on Apple Silicon."""
800 def not_apple_silicon(test):
801 if platform.system() != "Darwin" or test.getArchitecture() not in [
802 "arm64",
803 "arm64e",
805 return "Test only runs on Apple Silicon"
806 return None
808 return skipTestIfFn(not_apple_silicon)(func)
811 def skipUnlessSupportedTypeAttribute(attr):
812 """Decorate the item to skip test unless Clang supports type __attribute__(attr)."""
814 def compiler_doesnt_support_struct_attribute(self):
815 compiler_path = self.getCompiler()
816 f = tempfile.NamedTemporaryFile()
817 cmd = [self.getCompiler(), "-x", "c++", "-c", "-o", f.name, "-"]
818 p = subprocess.Popen(
819 cmd,
820 stdin=subprocess.PIPE,
821 stdout=subprocess.PIPE,
822 stderr=subprocess.PIPE,
823 universal_newlines=True,
825 stdout, stderr = p.communicate("struct __attribute__((%s)) Test {};" % attr)
826 if attr in stderr:
827 return "Compiler does not support attribute %s" % (attr)
828 return None
830 return skipTestIfFn(compiler_doesnt_support_struct_attribute)
833 def skipUnlessHasCallSiteInfo(func):
834 """Decorate the function to skip testing unless call site info from clang is available."""
836 def is_compiler_clang_with_call_site_info(self):
837 compiler_path = self.getCompiler()
838 compiler = os.path.basename(compiler_path)
839 if not compiler.startswith("clang"):
840 return "Test requires clang as compiler"
842 f = tempfile.NamedTemporaryFile()
843 cmd = (
844 "echo 'int main() {}' | "
845 "%s -g -glldb -O1 -S -emit-llvm -x c -o %s -" % (compiler_path, f.name)
847 if os.popen(cmd).close() is not None:
848 return "Compiler can't compile with call site info enabled"
850 with open(f.name, "r") as ir_output_file:
851 buf = ir_output_file.read()
853 if "DIFlagAllCallsDescribed" not in buf:
854 return "Compiler did not introduce DIFlagAllCallsDescribed IR flag"
856 return None
858 return skipTestIfFn(is_compiler_clang_with_call_site_info)(func)
861 def skipUnlessThreadSanitizer(func):
862 """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""
864 def is_compiler_clang_with_thread_sanitizer(self):
865 if is_running_under_asan():
866 return "Thread sanitizer tests are disabled when runing under ASAN"
868 compiler_path = self.getCompiler()
869 compiler = os.path.basename(compiler_path)
870 if not compiler.startswith("clang"):
871 return "Test requires clang as compiler"
872 if lldbplatformutil.getPlatform() == "windows":
873 return "TSAN tests not compatible with 'windows'"
874 # rdar://28659145 - TSAN tests don't look like they're supported on i386
875 if self.getArchitecture() == "i386" and platform.system() == "Darwin":
876 return "TSAN tests not compatible with i386 targets"
877 if not _compiler_supports(compiler_path, "-fsanitize=thread"):
878 return "Compiler cannot compile with -fsanitize=thread"
879 return None
881 return skipTestIfFn(is_compiler_clang_with_thread_sanitizer)(func)
884 def skipUnlessUndefinedBehaviorSanitizer(func):
885 """Decorate the item to skip test unless -fsanitize=undefined is supported."""
887 def is_compiler_clang_with_ubsan(self):
888 if is_running_under_asan():
889 return (
890 "Undefined behavior sanitizer tests are disabled when runing under ASAN"
893 # We need to write out the object into a named temp file for inspection.
894 outputf = tempfile.NamedTemporaryFile()
896 # Try to compile with ubsan turned on.
897 if not _compiler_supports(
898 self.getCompiler(),
899 "-fsanitize=undefined",
900 "int main() { int x = 0; return x / x; }",
901 outputf,
903 return "Compiler cannot compile with -fsanitize=undefined"
905 # Check that we actually see ubsan instrumentation in the binary.
906 cmd = "nm %s" % outputf.name
907 with os.popen(cmd) as nm_output:
908 if "___ubsan_handle_divrem_overflow" not in nm_output.read():
909 return "Division by zero instrumentation is missing"
911 # Find the ubsan dylib.
912 # FIXME: This check should go away once compiler-rt gains support for __ubsan_on_report.
913 cmd = "%s -fsanitize=undefined -x c - -o - -### 2>&1" % self.getCompiler()
914 with os.popen(cmd) as cc_output:
915 driver_jobs = cc_output.read()
916 m = re.search(r'"([^"]+libclang_rt.ubsan_osx_dynamic.dylib)"', driver_jobs)
917 if not m:
918 return "Could not find the ubsan dylib used by the driver"
919 ubsan_dylib = m.group(1)
921 # Check that the ubsan dylib has special monitor hooks.
922 cmd = "nm -gU %s" % ubsan_dylib
923 with os.popen(cmd) as nm_output:
924 syms = nm_output.read()
925 if "___ubsan_on_report" not in syms:
926 return "Missing ___ubsan_on_report"
927 if "___ubsan_get_current_report_data" not in syms:
928 return "Missing ___ubsan_get_current_report_data"
930 # OK, this dylib + compiler works for us.
931 return None
933 return skipTestIfFn(is_compiler_clang_with_ubsan)(func)
936 def is_running_under_asan():
937 if "ASAN_OPTIONS" in os.environ:
938 return "ASAN unsupported"
939 return None
942 def skipUnlessAddressSanitizer(func):
943 """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""
945 def is_compiler_with_address_sanitizer(self):
946 # Also don't run tests that use address sanitizer inside an
947 # address-sanitized LLDB. The tests don't support that
948 # configuration.
949 if is_running_under_asan():
950 return "Address sanitizer tests are disabled when runing under ASAN"
952 if lldbplatformutil.getPlatform() == "windows":
953 return "ASAN tests not compatible with 'windows'"
954 if not _compiler_supports(self.getCompiler(), "-fsanitize=address"):
955 return "Compiler cannot compile with -fsanitize=address"
956 return None
958 return skipTestIfFn(is_compiler_with_address_sanitizer)(func)
961 def skipIfAsan(func):
962 """Skip this test if the environment is set up to run LLDB *itself* under ASAN."""
963 return skipTestIfFn(is_running_under_asan)(func)
966 def skipUnlessAArch64MTELinuxCompiler(func):
967 """Decorate the item to skip test unless MTE is supported by the test compiler."""
969 def is_toolchain_with_mte(self):
970 compiler_path = self.getCompiler()
971 compiler = os.path.basename(compiler_path)
972 f = tempfile.NamedTemporaryFile()
973 if lldbplatformutil.getPlatform() == "windows":
974 return "MTE tests are not compatible with 'windows'"
976 cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name)
977 if os.popen(cmd).close() is not None:
978 # Cannot compile at all, don't skip the test
979 # so that we report the broken compiler normally.
980 return None
982 # We need the Linux headers and ACLE MTE intrinsics
983 test_src = """
984 #include <asm/hwcap.h>
985 #include <arm_acle.h>
986 #ifndef HWCAP2_MTE
987 #error
988 #endif
989 int main() {
990 void* ptr = __arm_mte_create_random_tag((void*)(0), 0);
991 }"""
992 cmd = "echo '%s' | %s -march=armv8.5-a+memtag -x c -o %s -" % (
993 test_src,
994 compiler_path,
995 f.name,
997 if os.popen(cmd).close() is not None:
998 return "Toolchain does not support MTE"
999 return None
1001 return skipTestIfFn(is_toolchain_with_mte)(func)
1004 def _get_bool_config(key, fail_value=True):
1006 Returns the current LLDB's build config value.
1007 :param key The key to lookup in LLDB's build configuration.
1008 :param fail_value The error value to return when the key can't be found.
1009 Defaults to true so that if an unknown key is lookup up we rather
1010 enable more tests (that then fail) than silently skipping them.
1012 config = lldb.SBDebugger.GetBuildConfiguration()
1013 value_node = config.GetValueForKey(key)
1014 return value_node.GetValueForKey("value").GetBooleanValue(fail_value)
1017 def _get_bool_config_skip_if_decorator(key):
1018 have = _get_bool_config(key)
1019 return unittest2.skipIf(not have, "requires " + key)
1022 def skipIfCursesSupportMissing(func):
1023 return _get_bool_config_skip_if_decorator("curses")(func)
1026 def skipIfXmlSupportMissing(func):
1027 return _get_bool_config_skip_if_decorator("xml")(func)
1030 def skipIfEditlineSupportMissing(func):
1031 return _get_bool_config_skip_if_decorator("editline")(func)
1034 def skipIfEditlineWideCharSupportMissing(func):
1035 return _get_bool_config_skip_if_decorator("editline_wchar")(func)
1038 def skipIfFBSDVMCoreSupportMissing(func):
1039 return _get_bool_config_skip_if_decorator("fbsdvmcore")(func)
1042 def skipIfLLVMTargetMissing(target):
1043 config = lldb.SBDebugger.GetBuildConfiguration()
1044 targets = config.GetValueForKey("targets").GetValueForKey("value")
1045 found = False
1046 for i in range(targets.GetSize()):
1047 if targets.GetItemAtIndex(i).GetStringValue(99) == target:
1048 found = True
1049 break
1051 return unittest2.skipIf(not found, "requires " + target)
1054 # Call sysctl on darwin to see if a specified hardware feature is available on this machine.
1055 def skipUnlessFeature(feature):
1056 def is_feature_enabled(self):
1057 if platform.system() == "Darwin":
1058 try:
1059 DEVNULL = open(os.devnull, "w")
1060 output = subprocess.check_output(
1061 ["/usr/sbin/sysctl", feature], stderr=DEVNULL
1062 ).decode("utf-8")
1063 # If 'feature: 1' was output, then this feature is available and
1064 # the test should not be skipped.
1065 if re.match("%s: 1\s*" % feature, output):
1066 return None
1067 else:
1068 return "%s is not supported on this system." % feature
1069 except subprocess.CalledProcessError:
1070 return "%s is not supported on this system." % feature
1072 return skipTestIfFn(is_feature_enabled)