xref: /llvm-project/lldb/test/API/functionalities/process_crash_info/TestProcessCrashInfo.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
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    def setUp(self):
16        TestBase.setUp(self)
17        self.runCmd("settings set auto-confirm true")
18        self.source = "main.c"
19        self.line = line_number(self.source, "// break here")
20
21    def tearDown(self):
22        self.runCmd("settings clear auto-confirm")
23        TestBase.tearDown(self)
24
25    @skipIfAsan  # The test process intentionally double-frees.
26    @skipUnlessDarwin
27    def test_cli(self):
28        """Test that `process status --verbose` fetches the extended crash
29        information dictionary from the command-line properly."""
30        self.build()
31        exe = self.getBuildArtifact("a.out")
32        self.expect("file " + exe, patterns=["Current executable set to .*a.out"])
33
34        self.expect("process launch", patterns=["Process .* launched: .*a.out"])
35
36        self.expect(
37            "process status --verbose",
38            patterns=[
39                "Extended Crash Information",
40                "Crash-Info Annotations",
41                "pointer being freed was not allocated",
42            ],
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.assertSuccess(error)
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(
79            self, lldb.SBFileSpec(self.source), self.line
80        )
81
82        stream = lldb.SBStream()
83        self.assertTrue(stream)
84
85        process = target.GetProcess()
86        self.assertTrue(process)
87
88        crash_info = process.GetExtendedCrashInformation()
89
90        error = crash_info.GetAsJSON(stream)
91        self.assertFalse(error.Success())
92        self.assertIn("No structured data.", error.GetCString())
93