199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTests that TSan and LLDB have correct thread numbers.
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprechtimport lldb
699451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
799451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
899451b44SJordan Rupprechtimport lldbsuite.test.lldbutil as lldbutil
999451b44SJordan Rupprechtimport json
1099451b44SJordan Rupprecht
1199451b44SJordan Rupprecht
1299451b44SJordan Rupprechtclass TsanThreadNumbersTestCase(TestBase):
1399451b44SJordan Rupprecht
1499451b44SJordan Rupprecht    @expectedFailureAll(
1599451b44SJordan Rupprecht        oslist=["linux"],
1699451b44SJordan Rupprecht        bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)")
1799451b44SJordan Rupprecht    @expectedFailureNetBSD
1899451b44SJordan Rupprecht    @skipIfFreeBSD  # llvm.org/pr21136 runtimes not yet available by default
1999451b44SJordan Rupprecht    @skipIfRemote
2099451b44SJordan Rupprecht    @skipUnlessThreadSanitizer
2199451b44SJordan Rupprecht    def test(self):
2299451b44SJordan Rupprecht        self.build()
2399451b44SJordan Rupprecht        self.tsan_tests()
2499451b44SJordan Rupprecht
2599451b44SJordan Rupprecht    def tsan_tests(self):
2699451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
2799451b44SJordan Rupprecht        self.expect(
2899451b44SJordan Rupprecht            "file " + exe,
2999451b44SJordan Rupprecht            patterns=["Current executable set to .*a.out"])
3099451b44SJordan Rupprecht
3199451b44SJordan Rupprecht        self.runCmd("run")
3299451b44SJordan Rupprecht
3399451b44SJordan Rupprecht        stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason()
3499451b44SJordan Rupprecht        if stop_reason == lldb.eStopReasonExec:
3599451b44SJordan Rupprecht            # On OS X 10.10 and older, we need to re-exec to enable
3699451b44SJordan Rupprecht            # interceptors.
3799451b44SJordan Rupprecht            self.runCmd("continue")
3899451b44SJordan Rupprecht
3999451b44SJordan Rupprecht        # the stop reason of the thread should be breakpoint.
4099451b44SJordan Rupprecht        self.expect("thread list", "A data race should be detected",
4199451b44SJordan Rupprecht                    substrs=['stopped', 'stop reason = Data race detected'])
4299451b44SJordan Rupprecht
4399451b44SJordan Rupprecht        self.assertEqual(
4499451b44SJordan Rupprecht            self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(),
4599451b44SJordan Rupprecht            lldb.eStopReasonInstrumentation)
4699451b44SJordan Rupprecht
4799451b44SJordan Rupprecht        report_thread_id = self.dbg.GetSelectedTarget(
4899451b44SJordan Rupprecht        ).process.GetSelectedThread().GetIndexID()
4999451b44SJordan Rupprecht
5099451b44SJordan Rupprecht        self.expect(
5199451b44SJordan Rupprecht            "thread info -s",
5299451b44SJordan Rupprecht            "The extended stop info should contain the TSan provided fields",
5399451b44SJordan Rupprecht            substrs=[
5499451b44SJordan Rupprecht                "instrumentation_class",
5599451b44SJordan Rupprecht                "description",
5699451b44SJordan Rupprecht                "mops"])
5799451b44SJordan Rupprecht
5899451b44SJordan Rupprecht        output_lines = self.res.GetOutput().split('\n')
5999451b44SJordan Rupprecht        json_line = '\n'.join(output_lines[2:])
6099451b44SJordan Rupprecht        data = json.loads(json_line)
6199451b44SJordan Rupprecht        self.assertEqual(data["instrumentation_class"], "ThreadSanitizer")
6299451b44SJordan Rupprecht        self.assertEqual(data["issue_type"], "data-race")
6399451b44SJordan Rupprecht        self.assertEqual(len(data["mops"]), 2)
6499451b44SJordan Rupprecht
6599451b44SJordan Rupprecht        self.assertEqual(data["mops"][0]["thread_id"], report_thread_id)
6699451b44SJordan Rupprecht
6799451b44SJordan Rupprecht        other_thread_id = data["mops"][1]["thread_id"]
68*b3a0c4d7SRaphael Isemann        self.assertNotEqual(other_thread_id, report_thread_id)
6999451b44SJordan Rupprecht        other_thread = self.dbg.GetSelectedTarget(
7099451b44SJordan Rupprecht        ).process.GetThreadByIndexID(other_thread_id)
7199451b44SJordan Rupprecht        self.assertTrue(other_thread.IsValid())
7299451b44SJordan Rupprecht
7399451b44SJordan Rupprecht        self.runCmd("thread select %d" % other_thread_id)
7499451b44SJordan Rupprecht
7599451b44SJordan Rupprecht        self.expect(
7699451b44SJordan Rupprecht            "thread backtrace",
7799451b44SJordan Rupprecht            "The other thread should be stopped in f1 or f2",
7899451b44SJordan Rupprecht            substrs=[
7999451b44SJordan Rupprecht                "a.out",
8099451b44SJordan Rupprecht                "main.c"])
81