1"""
2Tests that TSan correctly reports the filename and line number of a racy global C++ variable.
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 TsanCPPGlobalLocationTestCase(TestBase):
13
14    mydir = TestBase.compute_mydir(__file__)
15
16    @expectedFailureAll(
17        oslist=["linux"],
18        bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)")
19    @expectedFailureNetBSD
20    @skipIfFreeBSD  # llvm.org/pr21136 runtimes not yet available by default
21    @skipIfRemote
22    @skipUnlessThreadSanitizer
23    def test(self):
24        self.build()
25        self.tsan_tests()
26
27    def tsan_tests(self):
28        exe = self.getBuildArtifact("a.out")
29        self.expect(
30            "file " + exe,
31            patterns=["Current executable set to .*a.out"])
32
33        self.runCmd("run")
34
35        stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason()
36        if stop_reason == lldb.eStopReasonExec:
37            # On OS X 10.10 and older, we need to re-exec to enable
38            # interceptors.
39            self.runCmd("continue")
40
41        # the stop reason of the thread should be breakpoint.
42        self.expect("thread list", "A data race should be detected",
43                    substrs=['stopped', 'stop reason = Data race detected'])
44
45        self.expect(
46            "thread info -s",
47            "The extended stop info should contain the TSan provided fields",
48            substrs=[
49                "instrumentation_class",
50                "description",
51                "mops"])
52
53        output_lines = self.res.GetOutput().split('\n')
54        json_line = '\n'.join(output_lines[2:])
55        data = json.loads(json_line)
56        self.assertEqual(data["instrumentation_class"], "ThreadSanitizer")
57        self.assertEqual(data["issue_type"], "data-race")
58
59        self.assertTrue(data["location_filename"].endswith("/main.cpp"))
60        self.assertEqual(
61            data["location_line"],
62            line_number(
63                'main.cpp',
64                '// global variable'))
65