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