xref: /llvm-project/lldb/test/API/macosx/abort_with_payload/TestAbortWithPayload.py (revision 2fd2fd2c46719c2020e09ce0bd43c4af56caa0ba)
1"""
2Test that the FrameRecognizer for __abort_with_payload
3works properly
4"""
5
6
7import lldb
8from lldbsuite.test.decorators import *
9import lldbsuite.test.lldbutil as lldbutil
10from lldbsuite.test.lldbtest import *
11
12
13class TestAbortWithPayload(TestBase):
14    NO_DEBUG_INFO_TESTCASE = True
15
16    @skipUnlessAppleSilicon
17    def test_abort_with_payload(self):
18        """There can be many tests in a test case - describe this test here."""
19        self.build()
20        self.abort_with_test(True)
21
22    @skipUnlessAppleSilicon
23    def test_abort_with_reason(self):
24        """There can be many tests in a test case - describe this test here."""
25        self.build()
26        self.abort_with_test(False)
27
28    def setUp(self):
29        # Call super's setUp().
30        TestBase.setUp(self)
31        self.main_source_file = lldb.SBFileSpec("main.c")
32
33    def abort_with_test(self, with_payload):
34        """If with_payload is True, we test the abort_with_payload call,
35        if false, we test abort_with_reason."""
36        launch_info = lldb.SBLaunchInfo([])
37        if not with_payload:
38            launch_info.SetArguments(["use_reason"], True)
39        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
40            self,
41            "Stop here before abort",
42            self.main_source_file,
43            launch_info=launch_info,
44        )
45
46        frame = thread.GetFrameAtIndex(0)
47        payload_str_var = frame.FindVariable("payload_string")
48        self.assertSuccess(payload_str_var.GetError(), "Got payload string var")
49        payload_var_addr = payload_str_var.unsigned
50
51        payload_size_var = frame.FindVariable("payload_string_len")
52        self.assertSuccess(payload_size_var.GetError(), "Got payload string len var")
53        payload_size_val = payload_size_var.unsigned
54
55        # Not let it run to crash:
56        process.Continue()
57
58        # At this point we should have stopped at the internal function.
59        # Make sure we selected the right thread:
60        sel_thread = process.GetSelectedThread()
61        self.assertEqual(thread, sel_thread, "Selected the original thread")
62        # Make sure the stop reason is right:
63        self.assertEqual(
64            thread.GetStopDescription(100),
65            "abort with payload or reason",
66            "Description was right",
67        )
68        frame_0 = thread.frames[0]
69        self.assertEqual(frame_0.name, "__abort_with_payload", "Frame 0 was right")
70
71        # Now check the recognized argument values and the ExtendedCrashInformation version:
72        options = lldb.SBVariablesOptions()
73        options.SetIncludeRecognizedArguments(True)
74        options.SetIncludeArguments(False)
75        options.SetIncludeLocals(False)
76        options.SetIncludeStatics(False)
77        options.SetIncludeRuntimeSupportValues(False)
78
79        arguments = frame_0.GetVariables(options)
80
81        correct_values = {
82            "namespace": 5,
83            "code": 100,
84            "payload_addr": payload_var_addr,
85            "payload_size": payload_size_val,
86            "payload_string": '"This is a payload that happens to be a string"',
87            "reason_string": '"This is the reason string"',
88            "reason_no_quote": "This is the reason string",
89            "flags": 0x85,
90        }
91
92        # First check the recognized argument values:
93        self.assertEqual(len(arguments), 6, "Got all six values")
94        self.assertEqual(arguments[0].name, "namespace")
95        self.assertEqual(
96            arguments[0].unsigned,
97            correct_values["namespace"],
98            "Namespace value correct",
99        )
100
101        self.assertEqual(arguments[1].name, "code")
102        self.assertEqual(
103            arguments[1].unsigned, correct_values["code"], "code value correct"
104        )
105
106        # We always stop at __abort_with_payload, regardless of whether the caller
107        # was abort_with_reason or abort_with_payload or any future API that
108        # funnels here. Since I don't want to have to know too much about the
109        # callers, I just always report what is in the function I've
110        #
111        # add the payload ones if it is the payload not the reason function.
112        self.assertEqual(arguments[2].name, "payload_addr")
113        self.assertEqual(arguments[3].name, "payload_size")
114        if with_payload:
115            self.assertEqual(
116                arguments[2].unsigned,
117                correct_values["payload_addr"],
118                "Payload matched variable address",
119            )
120            # We've made a payload that is a string, try to fetch that:
121            char_ptr_type = target.FindFirstType("char").GetPointerType()
122            self.assertTrue(char_ptr_type.IsValid(), "Got char ptr type")
123
124            str_val = arguments[2].Cast(char_ptr_type)
125            self.assertEqual(
126                str_val.summary, correct_values["payload_string"], "Got payload string"
127            )
128
129            self.assertEqual(
130                arguments[3].unsigned,
131                correct_values["payload_size"],
132                "payload size value correct",
133            )
134        else:
135            self.assertEqual(
136                arguments[2].unsigned, 0, "Got 0 payload addr for reason call"
137            )
138            self.assertEqual(
139                arguments[3].unsigned, 0, "Got 0 payload size for reason call"
140            )
141
142        self.assertEqual(arguments[4].name, "reason")
143        self.assertEqual(
144            arguments[4].summary,
145            correct_values["reason_string"],
146            "Reason value correct",
147        )
148
149        self.assertEqual(arguments[5].name, "flags")
150        self.assertEqual(
151            arguments[5].unsigned, correct_values["flags"], "Flags value correct"
152        )
153
154        # Also check that the same info was stored in the ExtendedCrashInformation dict:
155        dict = process.GetExtendedCrashInformation()
156        self.assertTrue(dict.IsValid(), "Got extended crash information dict")
157        self.assertEqual(
158            dict.GetType(), lldb.eStructuredDataTypeDictionary, "It is a dictionary"
159        )
160
161        abort_dict = dict.GetValueForKey("abort_with_payload")
162        self.assertTrue(abort_dict.IsValid(), "Got an abort_with_payload dict")
163        self.assertEqual(
164            abort_dict.GetType(),
165            lldb.eStructuredDataTypeDictionary,
166            "It is a dictionary",
167        )
168
169        namespace_val = abort_dict.GetValueForKey("namespace")
170        self.assertTrue(namespace_val.IsValid(), "Got a valid namespace")
171        self.assertEqual(
172            namespace_val.GetIntegerValue(0),
173            correct_values["namespace"],
174            "Namespace value correct",
175        )
176
177        code_val = abort_dict.GetValueForKey("code")
178        self.assertTrue(code_val.IsValid(), "Got a valid code")
179        self.assertEqual(
180            code_val.GetIntegerValue(0), correct_values["code"], "Code value correct"
181        )
182
183        if with_payload:
184            addr_val = abort_dict.GetValueForKey("payload_addr")
185            self.assertTrue(addr_val.IsValid(), "Got a payload_addr")
186            self.assertEqual(
187                addr_val.GetIntegerValue(0),
188                correct_values["payload_addr"],
189                "payload_addr right in dictionary",
190            )
191
192            size_val = abort_dict.GetValueForKey("payload_size")
193            self.assertTrue(size_val.IsValid(), "Got a payload size value")
194            self.assertEqual(
195                size_val.GetIntegerValue(0),
196                correct_values["payload_size"],
197                "payload size right in dictionary",
198            )
199
200        reason_val = abort_dict.GetValueForKey("reason")
201        self.assertTrue(reason_val.IsValid(), "Got a reason key")
202        self.assertEqual(
203            reason_val.GetStringValue(100),
204            correct_values["reason_no_quote"],
205            "reason right in dictionary",
206        )
207
208        flags_val = abort_dict.GetValueForKey("flags")
209        self.assertTrue(flags_val.IsValid(), "Got a flags value")
210        self.assertEqual(
211            flags_val.GetIntegerValue(0),
212            correct_values["flags"],
213            "flags right in dictionary",
214        )
215