1from __future__ import absolute_import
2from __future__ import print_function
3
4# System modules
5from distutils.version import LooseVersion, StrictVersion
6from functools import wraps
7import os
8import platform
9import re
10import sys
11import tempfile
12
13# Third-party modules
14import six
15import unittest2
16
17# LLDB modules
18import use_lldb_suite
19
20import lldb
21from . import configuration
22from . import test_categories
23from lldbsuite.test_event.event_builder import EventBuilder
24from lldbsuite.support import funcutils
25from lldbsuite.test import lldbplatform
26from lldbsuite.test import lldbplatformutil
27
28
29class 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.
37class no_match:
38
39    def __init__(self, item):
40        self.item = item
41
42
43def _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
74def _match_decorator_property(expected, actual):
75    if actual is None or expected is None:
76        return True
77
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
87
88
89def 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")
94
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
121
122
123def 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")
128
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()
136
137            if reason is not None:
138                self.skipTest(reason)
139            else:
140                func(*args, **kwargs)
141        return wrapper
142
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
152
153
154def _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):
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.debug_info)
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)
178
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            _check_expected_version(
193                macos_version[0],
194                macos_version[1],
195                platform.mac_ver()[0]))
196
197        # For the test to be skipped, all specified (e.g. not None) parameters must be True.
198        # An unspecified parameter means "any", so those are marked skip by default.  And we skip
199        # the final test if all conditions are True.
200        conditions = [(oslist, skip_for_os, "target o/s"),
201                      (hostoslist, skip_for_hostos, "host o/s"),
202                      (compiler, skip_for_compiler, "compiler or version"),
203                      (archs, skip_for_arch, "architecture"),
204                      (debug_info, skip_for_debug_info, "debug info format"),
205                      (triple, skip_for_triple, "target triple"),
206                      (swig_version, skip_for_swig_version, "swig version"),
207                      (py_version, skip_for_py_version, "python version"),
208                      (macos_version, skip_for_macos_version, "macOS version"),
209                      (remote, skip_for_remote, "platform locality (remote/local)")]
210        reasons = []
211        final_skip_result = True
212        for this_condition in conditions:
213            final_skip_result = final_skip_result and this_condition[1]
214            if this_condition[0] is not None and this_condition[1]:
215                reasons.append(this_condition[2])
216        reason_str = None
217        if final_skip_result:
218            mode_str = {
219                DecorateMode.Skip: "skipping",
220                DecorateMode.Xfail: "xfailing"}[mode]
221            if len(reasons) > 0:
222                reason_str = ",".join(reasons)
223                reason_str = "{} due to the following parameter(s): {}".format(
224                    mode_str, reason_str)
225            else:
226                reason_str = "{} unconditionally"
227            if bugnumber is not None and not six.callable(bugnumber):
228                reason_str = reason_str + " [" + str(bugnumber) + "]"
229        return reason_str
230
231    if mode == DecorateMode.Skip:
232        return skipTestIfFn(fn, bugnumber)
233    elif mode == DecorateMode.Xfail:
234        return expectedFailure(fn, bugnumber)
235    else:
236        return None
237
238# provide a function to xfail on defined oslist, compiler version, and archs
239# if none is specified for any argument, that argument won't be checked and thus means for all
240# for example,
241# @expectedFailureAll, xfail for all platform/compiler/arch,
242# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture
243# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386
244
245
246def expectedFailureAll(bugnumber=None,
247                       oslist=None, hostoslist=None,
248                       compiler=None, compiler_version=None,
249                       archs=None, triple=None,
250                       debug_info=None,
251                       swig_version=None, py_version=None,
252                       macos_version=None,
253                       remote=None):
254    return _decorateTest(DecorateMode.Xfail,
255                         bugnumber=bugnumber,
256                         oslist=oslist, hostoslist=hostoslist,
257                         compiler=compiler, compiler_version=compiler_version,
258                         archs=archs, triple=triple,
259                         debug_info=debug_info,
260                         swig_version=swig_version, py_version=py_version,
261                         macos_version=None,
262                         remote=remote)
263
264
265# provide a function to skip on defined oslist, compiler version, and archs
266# if none is specified for any argument, that argument won't be checked and thus means for all
267# for example,
268# @skipIf, skip for all platform/compiler/arch,
269# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture
270# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386
271def skipIf(bugnumber=None,
272           oslist=None, hostoslist=None,
273           compiler=None, compiler_version=None,
274           archs=None, triple=None,
275           debug_info=None,
276           swig_version=None, py_version=None,
277           macos_version=None,
278           remote=None):
279    return _decorateTest(DecorateMode.Skip,
280                         bugnumber=bugnumber,
281                         oslist=oslist, hostoslist=hostoslist,
282                         compiler=compiler, compiler_version=compiler_version,
283                         archs=archs, triple=triple,
284                         debug_info=debug_info,
285                         swig_version=swig_version, py_version=py_version,
286                         macos_version=macos_version,
287                         remote=remote)
288
289
290def _skip_for_android(reason, api_levels, archs):
291    def impl(obj):
292        result = lldbplatformutil.match_android_device(
293            obj.getArchitecture(), valid_archs=archs, valid_api_levels=api_levels)
294        return reason if result else None
295    return impl
296
297
298def add_test_categories(cat):
299    """Add test categories to a TestCase method"""
300    cat = test_categories.validate(cat, True)
301
302    def impl(func):
303        if isinstance(func, type) and issubclass(func, unittest2.TestCase):
304            raise Exception(
305                "@add_test_categories can only be used to decorate a test method")
306        if hasattr(func, "categories"):
307            cat.extend(func.categories)
308        func.categories = cat
309        return func
310
311    return impl
312
313
314def benchmarks_test(func):
315    """Decorate the item as a benchmarks test."""
316    def should_skip_benchmarks_test():
317        return "benchmarks test"
318
319    # Mark this function as such to separate them from the regular tests.
320    result = skipTestIfFn(should_skip_benchmarks_test)(func)
321    result.__benchmarks_test__ = True
322    return result
323
324
325def no_debug_info_test(func):
326    """Decorate the item as a test what don't use any debug info. If this annotation is specified
327       then the test runner won't generate a separate test for each debug info format. """
328    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
329        raise Exception(
330            "@no_debug_info_test can only be used to decorate a test method")
331
332    @wraps(func)
333    def wrapper(self, *args, **kwargs):
334        return func(self, *args, **kwargs)
335
336    # Mark this function as such to separate them from the regular tests.
337    wrapper.__no_debug_info_test__ = True
338    return wrapper
339
340
341def debugserver_test(func):
342    """Decorate the item as a debugserver test."""
343    def should_skip_debugserver_test():
344        return "debugserver tests" if configuration.dont_do_debugserver_test else None
345    return skipTestIfFn(should_skip_debugserver_test)(func)
346
347
348def llgs_test(func):
349    """Decorate the item as a lldb-server test."""
350    def should_skip_llgs_tests():
351        return "llgs tests" if configuration.dont_do_llgs_test else None
352    return skipTestIfFn(should_skip_llgs_tests)(func)
353
354
355def not_remote_testsuite_ready(func):
356    """Decorate the item as a test which is not ready yet for remote testsuite."""
357    def is_remote():
358        return "Not ready for remote testsuite" if lldb.remote_platform else None
359    return skipTestIfFn(is_remote)(func)
360
361
362def expectedFailureOS(
363        oslist,
364        bugnumber=None,
365        compilers=None,
366        debug_info=None,
367        archs=None):
368    return expectedFailureAll(
369        oslist=oslist,
370        bugnumber=bugnumber,
371        compiler=compilers,
372        archs=archs,
373        debug_info=debug_info)
374
375
376def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None):
377    # For legacy reasons, we support both "darwin" and "macosx" as OS X
378    # triples.
379    return expectedFailureOS(
380        lldbplatform.darwin_all,
381        bugnumber,
382        compilers,
383        debug_info=debug_info)
384
385
386def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None):
387    """ Mark a test as xfail for Android.
388
389    Arguments:
390        bugnumber - The LLVM pr associated with the problem.
391        api_levels - A sequence of numbers specifying the Android API levels
392            for which a test is expected to fail. None means all API level.
393        arch - A sequence of architecture names specifying the architectures
394            for which a test is expected to fail. None means all architectures.
395    """
396    return expectedFailure(
397        _skip_for_android(
398            "xfailing on android",
399            api_levels,
400            archs),
401        bugnumber)
402
403# Flakey tests get two chances to run. If they fail the first time round, the result formatter
404# makes sure it is run one more time.
405
406
407def expectedFlakey(expected_fn, bugnumber=None):
408    def expectedFailure_impl(func):
409        @wraps(func)
410        def wrapper(*args, **kwargs):
411            self = args[0]
412            if expected_fn(self):
413                # Send event marking test as explicitly eligible for rerunning.
414                if configuration.results_formatter_object is not None:
415                    # Mark this test as rerunnable.
416                    configuration.results_formatter_object.handle_event(
417                        EventBuilder.event_for_mark_test_rerun_eligible(self))
418            func(*args, **kwargs)
419        return wrapper
420    # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)
421    # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])).  When called
422    # the first way, the first argument will be the actual function because decorators are
423    # weird like that.  So this is basically a check that says "which syntax was the original
424    # function decorated with?"
425    if six.callable(bugnumber):
426        return expectedFailure_impl(bugnumber)
427    else:
428        return expectedFailure_impl
429
430
431def expectedFlakeyDwarf(bugnumber=None):
432    def fn(self):
433        return self.debug_info == "dwarf"
434    return expectedFlakey(fn, bugnumber)
435
436
437def expectedFlakeyDsym(bugnumber=None):
438    def fn(self):
439        return self.debug_info == "dwarf"
440    return expectedFlakey(fn, bugnumber)
441
442
443def expectedFlakeyOS(oslist, bugnumber=None, compilers=None):
444    def fn(self):
445        return (self.getPlatform() in oslist and
446                self.expectedCompiler(compilers))
447    return expectedFlakey(fn, bugnumber)
448
449
450def expectedFlakeyDarwin(bugnumber=None, compilers=None):
451    # For legacy reasons, we support both "darwin" and "macosx" as OS X
452    # triples.
453    return expectedFlakeyOS(
454        lldbplatformutil.getDarwinOSTriples(),
455        bugnumber,
456        compilers)
457
458
459def expectedFlakeyFreeBSD(bugnumber=None, compilers=None):
460    return expectedFlakeyOS(['freebsd'], bugnumber, compilers)
461
462
463def expectedFlakeyLinux(bugnumber=None, compilers=None):
464    return expectedFlakeyOS(['linux'], bugnumber, compilers)
465
466
467def expectedFlakeyNetBSD(bugnumber=None, compilers=None):
468    return expectedFlakeyOS(['netbsd'], bugnumber, compilers)
469
470
471def expectedFlakeyCompiler(compiler, compiler_version=None, bugnumber=None):
472    if compiler_version is None:
473        compiler_version = ['=', None]
474
475    def fn(self):
476        return compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version)
477    return expectedFlakey(fn, bugnumber)
478
479# @expectedFlakeyClang('bugnumber', ['<=', '3.4'])
480
481
482def expectedFlakeyClang(bugnumber=None, compiler_version=None):
483    return expectedFlakeyCompiler('clang', compiler_version, bugnumber)
484
485# @expectedFlakeyGcc('bugnumber', ['<=', '3.4'])
486
487
488def expectedFlakeyGcc(bugnumber=None, compiler_version=None):
489    return expectedFlakeyCompiler('gcc', compiler_version, bugnumber)
490
491
492def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None):
493    return expectedFlakey(
494        _skip_for_android(
495            "flakey on android",
496            api_levels,
497            archs),
498        bugnumber)
499
500
501def skipIfRemote(func):
502    """Decorate the item to skip tests if testing remotely."""
503    def is_remote():
504        return "skip on remote platform" if lldb.remote_platform else None
505    return skipTestIfFn(is_remote)(func)
506
507
508def skipIfRemoteDueToDeadlock(func):
509    """Decorate the item to skip tests if testing remotely due to the test deadlocking."""
510    def is_remote():
511        return "skip on remote platform (deadlocks)" if lldb.remote_platform else None
512    return skipTestIfFn(is_remote)(func)
513
514
515def skipIfNoSBHeaders(func):
516    """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers."""
517    def are_sb_headers_missing():
518        if lldbplatformutil.getHostPlatform() == 'darwin':
519            header = os.path.join(
520                os.environ["LLDB_LIB_DIR"],
521                'LLDB.framework',
522                'Versions',
523                'Current',
524                'Headers',
525                'LLDB.h')
526            if os.path.exists(header):
527                return None
528
529        header = os.path.join(
530            os.environ["LLDB_SRC"],
531            "include",
532            "lldb",
533            "API",
534            "LLDB.h")
535        if not os.path.exists(header):
536            return "skip because LLDB.h header not found"
537        return None
538
539    return skipTestIfFn(are_sb_headers_missing)(func)
540
541
542def skipIfiOSSimulator(func):
543    """Decorate the item to skip tests that should be skipped on the iOS Simulator."""
544    def is_ios_simulator():
545        return "skip on the iOS Simulator" if configuration.lldb_platform_name == 'ios-simulator' else None
546    return skipTestIfFn(is_ios_simulator)(func)
547
548
549def skipIfFreeBSD(func):
550    """Decorate the item to skip tests that should be skipped on FreeBSD."""
551    return skipIfPlatform(["freebsd"])(func)
552
553
554def skipIfNetBSD(func):
555    """Decorate the item to skip tests that should be skipped on NetBSD."""
556    return skipIfPlatform(["netbsd"])(func)
557
558
559def skipIfDarwin(func):
560    """Decorate the item to skip tests that should be skipped on Darwin."""
561    return skipIfPlatform(
562        lldbplatform.translate(
563            lldbplatform.darwin_all))(func)
564
565
566def skipIfLinux(func):
567    """Decorate the item to skip tests that should be skipped on Linux."""
568    return skipIfPlatform(["linux"])(func)
569
570
571def skipIfWindows(func):
572    """Decorate the item to skip tests that should be skipped on Windows."""
573    return skipIfPlatform(["windows"])(func)
574
575
576def skipUnlessWindows(func):
577    """Decorate the item to skip tests that should be skipped on any non-Windows platform."""
578    return skipUnlessPlatform(["windows"])(func)
579
580
581def skipUnlessDarwin(func):
582    """Decorate the item to skip tests that should be skipped on any non Darwin platform."""
583    return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func)
584
585
586def skipUnlessGoInstalled(func):
587    """Decorate the item to skip tests when no Go compiler is available."""
588
589    def is_go_missing(self):
590        compiler = self.getGoCompilerVersion()
591        if not compiler:
592            return "skipping because go compiler not found"
593        match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler)
594        if not match_version:
595            # Couldn't determine version.
596            return "skipping because go version could not be parsed out of {}".format(
597                compiler)
598        else:
599            min_strict_version = StrictVersion("1.4.0")
600            compiler_strict_version = StrictVersion(match_version.group(1))
601            if compiler_strict_version < min_strict_version:
602                return "skipping because available version ({}) does not meet minimum required version ({})".format(
603                    compiler_strict_version, min_strict_version)
604        return None
605    return skipTestIfFn(is_go_missing)(func)
606
607
608def skipIfHostIncompatibleWithRemote(func):
609    """Decorate the item to skip tests if binaries built on this host are incompatible."""
610
611    def is_host_incompatible_with_remote(self):
612        host_arch = self.getLldbArchitecture()
613        host_platform = lldbplatformutil.getHostPlatform()
614        target_arch = self.getArchitecture()
615        target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform()
616        if not (target_arch == 'x86_64' and host_arch ==
617                'i386') and host_arch != target_arch:
618            return "skipping because target %s is not compatible with host architecture %s" % (
619                target_arch, host_arch)
620        if target_platform != host_platform:
621            return "skipping because target is %s but host is %s" % (
622                target_platform, host_platform)
623        if lldbplatformutil.match_android_device(target_arch):
624            return "skipping because target is android"
625        return None
626    return skipTestIfFn(is_host_incompatible_with_remote)(func)
627
628
629def skipIfPlatform(oslist):
630    """Decorate the item to skip tests if running on one of the listed platforms."""
631    # This decorator cannot be ported to `skipIf` yet because it is used on entire
632    # classes, which `skipIf` explicitly forbids.
633    return unittest2.skipIf(lldbplatformutil.getPlatform() in oslist,
634                            "skip on %s" % (", ".join(oslist)))
635
636
637def skipUnlessPlatform(oslist):
638    """Decorate the item to skip tests unless running on one of the listed platforms."""
639    # This decorator cannot be ported to `skipIf` yet because it is used on entire
640    # classes, which `skipIf` explicitly forbids.
641    return unittest2.skipUnless(lldbplatformutil.getPlatform() in oslist,
642                                "requires one of %s" % (", ".join(oslist)))
643
644
645def skipIfTargetAndroid(api_levels=None, archs=None):
646    """Decorator to skip tests when the target is Android.
647
648    Arguments:
649        api_levels - The API levels for which the test should be skipped. If
650            it is None, then the test will be skipped for all API levels.
651        arch - A sequence of architecture names specifying the architectures
652            for which a test is skipped. None means all architectures.
653    """
654    return skipTestIfFn(
655        _skip_for_android(
656            "skipping for android",
657            api_levels,
658            archs))
659
660
661def skipUnlessThreadSanitizer(func):
662    """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""
663
664    def is_compiler_clang_with_thread_sanitizer(self):
665        compiler_path = self.getCompiler()
666        compiler = os.path.basename(compiler_path)
667        if not compiler.startswith("clang"):
668            return "Test requires clang as compiler"
669        if lldbplatformutil.getPlatform() == 'windows':
670            return "TSAN tests not compatible with 'windows'"
671        # rdar://28659145 - TSAN tests don't look like they're supported on i386
672        if self.getArchitecture() == 'i386' and platform.system() == 'Darwin':
673            return "TSAN tests not compatible with i386 targets"
674        f = tempfile.NamedTemporaryFile()
675        cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name)
676        if os.popen(cmd).close() is not None:
677            return None  # The compiler cannot compile at all, let's *not* skip the test
678        cmd = "echo 'int main() {}' | %s -fsanitize=thread -x c -o %s -" % (compiler_path, f.name)
679        if os.popen(cmd).close() is not None:
680            return "Compiler cannot compile with -fsanitize=thread"
681        return None
682    return skipTestIfFn(is_compiler_clang_with_thread_sanitizer)(func)
683
684def skipUnlessAddressSanitizer(func):
685    """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""
686
687    def is_compiler_with_address_sanitizer(self):
688        compiler_path = self.getCompiler()
689        compiler = os.path.basename(compiler_path)
690        f = tempfile.NamedTemporaryFile()
691        if lldbplatformutil.getPlatform() == 'windows':
692            return "ASAN tests not compatible with 'windows'"
693        cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name)
694        if os.popen(cmd).close() is not None:
695            return None  # The compiler cannot compile at all, let's *not* skip the test
696        cmd = "echo 'int main() {}' | %s -fsanitize=address -x c -o %s -" % (compiler_path, f.name)
697        if os.popen(cmd).close() is not None:
698            return "Compiler cannot compile with -fsanitize=address"
699        return None
700    return skipTestIfFn(is_compiler_with_address_sanitizer)(func)
701