1"""
2Test lldb process crash info.
3"""
4
5import os
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11from lldbsuite.test import lldbtest
12
13
14class PlatformProcessCrashInfoTestCase(TestBase):
15
16    mydir = TestBase.compute_mydir(__file__)
17
18    def setUp(self):
19        TestBase.setUp(self)
20        self.runCmd("settings set auto-confirm true")
21        self.source = "main.c"
22        self.line = line_number(self.source, '// break here')
23
24    def tearDown(self):
25        self.runCmd("settings clear auto-confirm")
26        TestBase.tearDown(self)
27
28    @skipIfAsan # The test process intentionally double-frees.
29    @skipUnlessDarwin
30    def test_cli(self):
31        """Test that `process status --verbose` fetches the extended crash
32        information dictionary from the command-line properly."""
33        self.build()
34        exe = self.getBuildArtifact("a.out")
35        self.expect("file " + exe,
36                    patterns=["Current executable set to .*a.out"])
37
38        self.expect('process launch',
39                    patterns=["Process .* launched: .*a.out"])
40
41        self.expect('process status --verbose',
42                    patterns=["\"message\".*pointer being freed was not allocated"])
43
44
45    @skipIfAsan # The test process intentionally hits a memory bug.
46    @skipUnlessDarwin
47    def test_api(self):
48        """Test that lldb can fetch a crashed process' extended crash information
49        dictionary from the api properly."""
50        self.build()
51        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
52        self.assertTrue(target, VALID_TARGET)
53
54        target.LaunchSimple(None, None, os.getcwd())
55
56        stream = lldb.SBStream()
57        self.assertTrue(stream)
58
59        process = target.GetProcess()
60        self.assertTrue(process)
61
62        crash_info = process.GetExtendedCrashInformation()
63
64        error = crash_info.GetAsJSON(stream)
65
66        self.assertTrue(error.Success())
67
68        self.assertTrue(crash_info.IsValid())
69
70        self.assertIn("pointer being freed was not allocated", stream.GetData())
71
72    # dyld leaves permanent crash_info records when testing on device.
73    @skipIfDarwinEmbedded
74    def test_on_sane_process(self):
75        """Test that lldb doesn't fetch the extended crash information
76        dictionary from a 'sane' stopped process."""
77        self.build()
78        target, _, _, _ = lldbutil.run_to_line_breakpoint(self, lldb.SBFileSpec(self.source),
79                                        self.line)
80
81        stream = lldb.SBStream()
82        self.assertTrue(stream)
83
84        process = target.GetProcess()
85        self.assertTrue(process)
86
87        crash_info = process.GetExtendedCrashInformation()
88
89        error = crash_info.GetAsJSON(stream)
90        self.assertFalse(error.Success())
91        self.assertIn("No structured data.", error.GetCString())
92