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