xref: /llvm-project/lldb/test/API/functionalities/tsan/multiple/TestTsanMultiple.py (revision 9c2468821ec51defd09c246fea4a47886fff8c01)
1"""
2Test ThreadSanitizer when multiple different issues are found.
3"""
4
5import lldb
6from lldbsuite.test.lldbtest import *
7from lldbsuite.test.decorators import *
8import lldbsuite.test.lldbutil as lldbutil
9import json
10
11
12class TsanMultipleTestCase(TestBase):
13    @expectedFailureAll(
14        oslist=["linux"],
15        bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)",
16    )
17    @expectedFailureNetBSD
18    @skipIfFreeBSD  # llvm.org/pr21136 runtimes not yet available by default
19    @skipIfRemote
20    @skipUnlessThreadSanitizer
21    @add_test_categories(["objc"])
22    def test(self):
23        self.build()
24        self.tsan_tests()
25
26    def tsan_tests(self):
27        exe = self.getBuildArtifact("a.out")
28        self.expect("file " + exe, patterns=["Current executable set to .*a.out"])
29
30        self.runCmd("env TSAN_OPTIONS=abort_on_error=0")
31
32        self.runCmd("run")
33
34        stop_reason = (
35            self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason()
36        )
37        if stop_reason == lldb.eStopReasonExec:
38            # On OS X 10.10 and older, we need to re-exec to enable
39            # interceptors.
40            self.runCmd("continue")
41
42        report_count = 0
43        while (
44            self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason()
45            == lldb.eStopReasonInstrumentation
46        ):
47            report_count += 1
48
49            stop_description = (
50                self.dbg.GetSelectedTarget()
51                .process.GetSelectedThread()
52                .GetStopDescription(100)
53            )
54
55            self.assertTrue(
56                (stop_description == "Data race detected")
57                or (stop_description == "Use of deallocated memory detected")
58                or (stop_description == "Thread leak detected")
59                or (
60                    stop_description
61                    == "Use of an uninitialized or destroyed mutex detected"
62                )
63                or (
64                    stop_description
65                    == "Unlock of an unlocked mutex (or by a wrong thread) detected"
66                )
67            )
68
69            self.expect(
70                "thread info -s",
71                "The extended stop info should contain the TSan provided fields",
72                substrs=["instrumentation_class", "description", "mops"],
73            )
74
75            output_lines = self.res.GetOutput().split("\n")
76            json_line = "\n".join(output_lines[2:])
77            data = json.loads(json_line)
78            self.assertEqual(data["instrumentation_class"], "ThreadSanitizer")
79
80            backtraces = (
81                self.dbg.GetSelectedTarget()
82                .process.GetSelectedThread()
83                .GetStopReasonExtendedBacktraces(
84                    lldb.eInstrumentationRuntimeTypeThreadSanitizer
85                )
86            )
87            self.assertGreaterEqual(backtraces.GetSize(), 1)
88
89            self.runCmd("continue")
90
91        self.assertEqual(
92            self.dbg.GetSelectedTarget().process.GetState(),
93            lldb.eStateExited,
94            PROCESS_EXITED,
95        )
96