Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / test / API / lang / objc / foundation / TestObjCMethods.py
blob634e4730c764b7c78496a431add3d6c9704395ef
1 """
2 Set breakpoints on objective-c class and instance methods in foundation.
3 Also lookup objective-c data types and evaluate expressions.
4 """
6 import os
7 import os.path
8 import lldb
9 from lldbsuite.test.decorators import *
10 from lldbsuite.test.lldbtest import *
11 from lldbsuite.test import lldbutil
13 file_index = 0
16 class FoundationTestCase(TestBase):
17 def setUp(self):
18 # Call super's setUp().
19 TestBase.setUp(self)
20 # Find the line number to break inside main().
21 self.main_source = "main.m"
22 self.line = line_number(self.main_source, "// Set break point at this line.")
24 def test_break(self):
25 """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'."""
26 self.build()
27 exe = self.getBuildArtifact("a.out")
28 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
30 # Stop at +[NSString stringWithFormat:].
31 break_results = lldbutil.run_break_set_command(
32 self, "_regexp-break +[NSString stringWithFormat:]"
34 lldbutil.check_breakpoint_result(
35 self,
36 break_results,
37 symbol_name="+[NSString stringWithFormat:]",
38 num_locations=1,
41 # Stop at -[MyString initWithNSString:].
42 lldbutil.run_break_set_by_symbol(
43 self,
44 "-[MyString initWithNSString:]",
45 num_expected_locations=1,
46 sym_exact=True,
49 # Stop at the "description" selector.
50 lldbutil.run_break_set_by_selector(
51 self, "description", num_expected_locations=1, module_name="a.out"
54 # Stop at -[NSAutoreleasePool release].
55 break_results = lldbutil.run_break_set_command(
56 self, "_regexp-break -[NSAutoreleasePool release]"
58 lldbutil.check_breakpoint_result(
59 self,
60 break_results,
61 symbol_name="-[NSAutoreleasePool release]",
62 num_locations=1,
65 self.runCmd("run", RUN_SUCCEEDED)
67 # First stop is +[NSString stringWithFormat:].
68 self.expect(
69 "thread backtrace",
70 "Stop at +[NSString stringWithFormat:]",
71 substrs=["Foundation`+[NSString stringWithFormat:]"],
74 self.runCmd("process continue")
76 # Second stop is still +[NSString stringWithFormat:].
77 self.expect(
78 "thread backtrace",
79 "Stop at +[NSString stringWithFormat:]",
80 substrs=["Foundation`+[NSString stringWithFormat:]"],
83 self.runCmd("process continue")
85 # Followed by a.out`-[MyString initWithNSString:].
86 self.expect(
87 "thread backtrace",
88 "Stop at a.out`-[MyString initWithNSString:]",
89 substrs=["a.out`-[MyString initWithNSString:]"],
92 self.runCmd("process continue")
94 # Followed by -[MyString description].
95 self.expect(
96 "thread backtrace",
97 "Stop at -[MyString description]",
98 substrs=["a.out`-[MyString description]"],
101 self.runCmd("process continue")
103 # Followed by the same -[MyString description].
104 self.expect(
105 "thread backtrace",
106 "Stop at -[MyString description]",
107 substrs=["a.out`-[MyString description]"],
110 self.runCmd("process continue")
112 # Followed by -[NSAutoreleasePool release].
113 self.expect(
114 "thread backtrace",
115 "Stop at -[NSAutoreleasePool release]",
116 substrs=["Foundation`-[NSAutoreleasePool release]"],
119 # rdar://problem/8542091
120 # rdar://problem/8492646
121 def test_data_type_and_expr(self):
122 """Lookup objective-c data types and evaluate expressions."""
123 self.build()
124 exe = self.getBuildArtifact("a.out")
125 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
127 # Stop at -[MyString description].
128 lldbutil.run_break_set_by_symbol(
129 self, "-[MyString description]", num_expected_locations=1, sym_exact=True
131 # self.expect("breakpoint set -n '-[MyString description]", BREAKPOINT_CREATED,
132 # startstr = "Breakpoint created: 1: name = '-[MyString description]',
133 # locations = 1")
135 self.runCmd("run", RUN_SUCCEEDED)
137 self.runCmd("settings set target.prefer-dynamic-value no-dynamic-values")
139 # The backtrace should show we stop at -[MyString description].
140 self.expect(
141 "thread backtrace",
142 "Stop at -[MyString description]",
143 substrs=["a.out`-[MyString description]"],
146 # Lookup objc data type MyString and evaluate some expressions.
148 self.expect(
149 "image lookup -t NSString",
150 DATA_TYPES_DISPLAYED_CORRECTLY,
151 substrs=['name = "NSString"', 'compiler_type = "@interface NSString'],
154 self.expect(
155 "image lookup -t MyString",
156 DATA_TYPES_DISPLAYED_CORRECTLY,
157 substrs=[
158 'name = "MyString"',
159 'compiler_type = "@interface MyString',
160 "NSString * str;",
161 "NSDate * date;",
165 self.expect(
166 "frame variable --show-types --scope",
167 VARIABLES_DISPLAYED_CORRECTLY,
168 substrs=["ARG: (MyString *) self"],
169 patterns=["ARG: \(.*\) _cmd", "(objc_selector *)|(SEL)"],
172 # rdar://problem/8651752
173 # don't crash trying to ask clang how many children an empty record has
174 self.runCmd("frame variable *_cmd")
176 # rdar://problem/8492646
177 # test/foundation fails after updating to tot r115023
178 # self->str displays nothing as output
179 self.expect(
180 "frame variable --show-types self->str",
181 VARIABLES_DISPLAYED_CORRECTLY,
182 startstr="(NSString *) self->str",
185 # rdar://problem/8447030
186 # 'frame variable self->date' displays the wrong data member
187 self.expect(
188 "frame variable --show-types self->date",
189 VARIABLES_DISPLAYED_CORRECTLY,
190 startstr="(NSDate *) self->date",
193 # This should display the str and date member fields as well.
194 self.expect(
195 "frame variable --show-types *self",
196 VARIABLES_DISPLAYED_CORRECTLY,
197 substrs=["(MyString) *self", "(NSString *) str", "(NSDate *) date"],
200 # isa should be accessible.
201 self.expect(
202 "expression self->isa", VARIABLES_DISPLAYED_CORRECTLY, substrs=["Class)"]
205 # This should fail expectedly.
206 self.expect(
207 "expression self->non_existent_member",
208 COMMAND_FAILED_AS_EXPECTED,
209 error=True,
210 substrs=[
211 "error:",
212 "'MyString' does not have a member named 'non_existent_member'",
216 # Use expression parser.
217 self.runCmd("expression self->str")
218 self.runCmd("expression self->date")
220 # (lldb) expression self->str
221 # error: instance variable 'str' is protected
222 # error: 1 errors parsing expression
224 # (lldb) expression self->date
225 # error: instance variable 'date' is protected
226 # error: 1 errors parsing expression
229 self.runCmd("breakpoint delete 1")
230 lldbutil.run_break_set_by_file_and_line(
231 self, "main.m", self.line, num_expected_locations=1, loc_exact=True
234 self.runCmd("process continue")
236 # rdar://problem/8542091
237 # test/foundation: expr -o -- my not working?
239 # Test new feature with r115115:
240 # Add "-o" option to "expression" which prints the object description
241 # if available.
242 self.expect(
243 "expression --object-description -- my",
244 "Object description displayed correctly",
245 patterns=["Hello from.*a.out.*with timestamp: "],
248 @add_test_categories(["pyapi"])
249 def test_print_ivars_correctly(self):
250 self.build()
251 # See: <rdar://problem/8717050> lldb needs to use the ObjC runtime symbols for ivar offsets
252 # Only fails for the ObjC 2.0 runtime.
253 exe = self.getBuildArtifact("a.out")
255 target = self.dbg.CreateTarget(exe)
256 self.assertTrue(target, VALID_TARGET)
258 break1 = target.BreakpointCreateByLocation(self.main_source, self.line)
259 self.assertTrue(break1, VALID_BREAKPOINT)
261 # Now launch the process, and do not stop at entry point.
262 process = target.LaunchSimple(None, None, self.get_process_working_directory())
264 self.assertTrue(process, PROCESS_IS_VALID)
266 # The stop reason of the thread should be breakpoint.
267 thread = process.GetThreadAtIndex(0)
268 if thread.GetStopReason() != lldb.eStopReasonBreakpoint:
269 from lldbsuite.test.lldbutil import stop_reason_to_str
271 self.fail(
272 STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS
273 % stop_reason_to_str(thread.GetStopReason())
276 # Make sure we stopped at the first breakpoint.
278 cur_frame = thread.GetFrameAtIndex(0)
280 line_number = cur_frame.GetLineEntry().GetLine()
281 self.assertEqual(line_number, self.line, "Hit the first breakpoint.")
283 my_var = cur_frame.FindVariable("my")
284 self.assertTrue(my_var, "Made a variable object for my")
286 str_var = cur_frame.FindVariable("str")
287 self.assertTrue(str_var, "Made a variable object for str")
289 # Now make sure that the my->str == str:
291 my_str_var = my_var.GetChildMemberWithName("str")
292 self.assertTrue(my_str_var, "Found a str ivar in my")
294 str_value = int(str_var.GetValue(), 0)
296 my_str_value = int(my_str_var.GetValue(), 0)
298 self.assertEqual(str_value, my_str_value, "Got the correct value for my->str")
300 def test_expression_lookups_objc(self):
301 """Test running an expression detect spurious debug info lookups (DWARF)."""
302 self.build()
303 exe = self.getBuildArtifact("a.out")
304 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
306 # Stop at -[MyString initWithNSString:].
307 lldbutil.run_break_set_by_symbol(
308 self,
309 "-[MyString initWithNSString:]",
310 num_expected_locations=1,
311 sym_exact=True,
314 self.runCmd("run", RUN_SUCCEEDED)
316 global file_index
317 # Log any DWARF lookups
318 ++file_index
319 logfile = os.path.join(
320 self.getBuildDir(),
321 "dwarf-lookups-" + self.getArchitecture() + "-" + str(file_index) + ".txt",
323 self.runCmd("log enable -f %s dwarf lookups" % (logfile))
324 self.runCmd("expr self")
325 self.runCmd("log disable dwarf lookups")
327 def cleanup():
328 if os.path.exists(logfile):
329 os.unlink(logfile)
331 self.addTearDownHook(cleanup)
333 if os.path.exists(logfile):
334 f = open(logfile)
335 lines = f.readlines()
336 num_errors = 0
337 for line in lines:
338 if "$__lldb" in line:
339 if num_errors == 0:
340 print(
341 "error: found spurious name lookups when evaluating an expression:"
343 num_errors += 1
344 print(line, end="")
345 self.assertEqual(num_errors, 0, "Spurious lookups detected")
346 f.close()