aboutsummaryrefslogtreecommitdiff
path: root/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py')
-rw-r--r--packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py262
1 files changed, 262 insertions, 0 deletions
diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py
new file mode 100644
index 000000000000..8358bd5e923f
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py
@@ -0,0 +1,262 @@
+"""
+Set breakpoints on objective-c class and instance methods in foundation.
+Also lookup objective-c data types and evaluate expressions.
+"""
+
+from __future__ import print_function
+
+
+
+import os, os.path, time
+import lldb
+import string
+from lldbsuite.test.lldbtest import *
+import lldbsuite.test.lldbutil as lldbutil
+
+file_index = 0
+@skipUnlessDarwin
+class FoundationTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break inside main().
+ self.main_source = "main.m"
+ self.line = line_number(self.main_source, '// Set break point at this line.')
+
+ def test_break(self):
+ """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'."""
+ self.build()
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ # Stop at +[NSString stringWithFormat:].
+ break_results = lldbutil.run_break_set_command(self, "_regexp-break +[NSString stringWithFormat:]")
+ lldbutil.check_breakpoint_result (self, break_results, symbol_name='+[NSString stringWithFormat:]', num_locations=1)
+
+ # Stop at -[MyString initWithNSString:].
+ lldbutil.run_break_set_by_symbol (self, '-[MyString initWithNSString:]', num_expected_locations=1, sym_exact=True)
+
+ # Stop at the "description" selector.
+ lldbutil.run_break_set_by_selector (self, 'description', num_expected_locations=1, module_name='a.out')
+
+ # Stop at -[NSAutoreleasePool release].
+ break_results = lldbutil.run_break_set_command(self, "_regexp-break -[NSAutoreleasePool release]")
+ lldbutil.check_breakpoint_result (self, break_results, symbol_name='-[NSAutoreleasePool release]', num_locations=1)
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ # First stop is +[NSString stringWithFormat:].
+ self.expect("thread backtrace", "Stop at +[NSString stringWithFormat:]",
+ substrs = ["Foundation`+[NSString stringWithFormat:]"])
+
+ self.runCmd("process continue")
+
+ # Second stop is still +[NSString stringWithFormat:].
+ self.expect("thread backtrace", "Stop at +[NSString stringWithFormat:]",
+ substrs = ["Foundation`+[NSString stringWithFormat:]"])
+
+ self.runCmd("process continue")
+
+ # Followed by a.out`-[MyString initWithNSString:].
+ self.expect("thread backtrace", "Stop at a.out`-[MyString initWithNSString:]",
+ substrs = ["a.out`-[MyString initWithNSString:]"])
+
+ self.runCmd("process continue")
+
+ # Followed by -[MyString description].
+ self.expect("thread backtrace", "Stop at -[MyString description]",
+ substrs = ["a.out`-[MyString description]"])
+
+ self.runCmd("process continue")
+
+ # Followed by the same -[MyString description].
+ self.expect("thread backtrace", "Stop at -[MyString description]",
+ substrs = ["a.out`-[MyString description]"])
+
+ self.runCmd("process continue")
+
+ # Followed by -[NSAutoreleasePool release].
+ self.expect("thread backtrace", "Stop at -[NSAutoreleasePool release]",
+ substrs = ["Foundation`-[NSAutoreleasePool release]"])
+
+ # rdar://problem/8542091
+ # rdar://problem/8492646
+ def test_data_type_and_expr(self):
+ """Lookup objective-c data types and evaluate expressions."""
+ self.build()
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ # Stop at -[MyString description].
+ lldbutil.run_break_set_by_symbol (self, '-[MyString description]', num_expected_locations=1, sym_exact=True)
+# self.expect("breakpoint set -n '-[MyString description]", BREAKPOINT_CREATED,
+# startstr = "Breakpoint created: 1: name = '-[MyString description]', locations = 1")
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ # The backtrace should show we stop at -[MyString description].
+ self.expect("thread backtrace", "Stop at -[MyString description]",
+ substrs = ["a.out`-[MyString description]"])
+
+ # Lookup objc data type MyString and evaluate some expressions.
+
+ self.expect("image lookup -t NSString", DATA_TYPES_DISPLAYED_CORRECTLY,
+ substrs = ['name = "NSString"',
+ 'compiler_type = "@interface NSString'])
+
+ self.expect("image lookup -t MyString", DATA_TYPES_DISPLAYED_CORRECTLY,
+ substrs = ['name = "MyString"',
+ 'compiler_type = "@interface MyString',
+ 'NSString * str;',
+ 'NSDate * date;'])
+
+ self.expect("frame variable --show-types --scope", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["ARG: (MyString *) self"],
+ patterns = ["ARG: \(.*\) _cmd",
+ "(objc_selector *)|(SEL)"])
+
+ # rdar://problem/8651752
+ # don't crash trying to ask clang how many children an empty record has
+ self.runCmd("frame variable *_cmd")
+
+ # rdar://problem/8492646
+ # test/foundation fails after updating to tot r115023
+ # self->str displays nothing as output
+ self.expect("frame variable --show-types self->str", VARIABLES_DISPLAYED_CORRECTLY,
+ startstr = "(NSString *) self->str")
+
+ # rdar://problem/8447030
+ # 'frame variable self->date' displays the wrong data member
+ self.expect("frame variable --show-types self->date", VARIABLES_DISPLAYED_CORRECTLY,
+ startstr = "(NSDate *) self->date")
+
+ # This should display the str and date member fields as well.
+ self.expect("frame variable --show-types *self", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["(MyString) *self",
+ "(NSString *) str",
+ "(NSDate *) date"])
+
+ # isa should be accessible.
+ self.expect("expression self->isa", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs = ["(Class)"])
+
+ # This should fail expectedly.
+ self.expect("expression self->non_existent_member",
+ COMMAND_FAILED_AS_EXPECTED, error=True,
+ startstr = "error: 'MyString' does not have a member named 'non_existent_member'")
+
+ # Use expression parser.
+ self.runCmd("expression self->str")
+ self.runCmd("expression self->date")
+
+ # (lldb) expression self->str
+ # error: instance variable 'str' is protected
+ # error: 1 errors parsing expression
+ #
+ # (lldb) expression self->date
+ # error: instance variable 'date' is protected
+ # error: 1 errors parsing expression
+ #
+
+ self.runCmd("breakpoint delete 1")
+ lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True)
+
+ self.runCmd("process continue")
+
+ # rdar://problem/8542091
+ # test/foundation: expr -o -- my not working?
+ #
+ # Test new feature with r115115:
+ # Add "-o" option to "expression" which prints the object description if available.
+ self.expect("expression --object-description -- my", "Object description displayed correctly",
+ patterns = ["Hello from.*a.out.*with timestamp: "])
+
+ @add_test_categories(['pyapi'])
+ def test_print_ivars_correctly (self):
+ self.build()
+ # See: <rdar://problem/8717050> lldb needs to use the ObjC runtime symbols for ivar offsets
+ # Only fails for the ObjC 2.0 runtime.
+ exe = os.path.join(os.getcwd(), "a.out")
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ break1 = target.BreakpointCreateByLocation(self.main_source, self.line)
+ self.assertTrue(break1, VALID_BREAKPOINT)
+
+ # Now launch the process, and do not stop at entry point.
+ process = target.LaunchSimple (None, None, self.get_process_working_directory())
+
+ self.assertTrue(process, PROCESS_IS_VALID)
+
+ # The stop reason of the thread should be breakpoint.
+ thread = process.GetThreadAtIndex(0)
+ if thread.GetStopReason() != lldb.eStopReasonBreakpoint:
+ from lldbsuite.test.lldbutil import stop_reason_to_str
+ self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS %
+ stop_reason_to_str(thread.GetStopReason()))
+
+ # Make sure we stopped at the first breakpoint.
+
+ cur_frame = thread.GetFrameAtIndex(0)
+
+ line_number = cur_frame.GetLineEntry().GetLine()
+ self.assertTrue (line_number == self.line, "Hit the first breakpoint.")
+
+ my_var = cur_frame.FindVariable("my")
+ self.assertTrue(my_var, "Made a variable object for my")
+
+ str_var = cur_frame.FindVariable("str")
+ self.assertTrue(str_var, "Made a variable object for str")
+
+ # Now make sure that the my->str == str:
+
+ my_str_var = my_var.GetChildMemberWithName("str")
+ self.assertTrue(my_str_var, "Found a str ivar in my")
+
+ str_value = int(str_var.GetValue(), 0)
+
+ my_str_value = int(my_str_var.GetValue(), 0)
+
+ self.assertTrue(str_value == my_str_value, "Got the correct value for my->str")
+
+ def test_expression_lookups_objc(self):
+ """Test running an expression detect spurious debug info lookups (DWARF)."""
+ self.build()
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ # Stop at -[MyString initWithNSString:].
+ lldbutil.run_break_set_by_symbol (self, '-[MyString initWithNSString:]', num_expected_locations=1, sym_exact=True)
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ global file_index
+ # Log any DWARF lookups
+ ++file_index
+ logfile = os.path.join(os.getcwd(), "dwarf-lookups-" + self.getArchitecture() + "-" + str(file_index) + ".txt")
+ self.runCmd("log enable -f %s dwarf lookups" % (logfile))
+ self.runCmd("expr self")
+ self.runCmd("log disable dwarf lookups")
+
+ def cleanup():
+ if os.path.exists (logfile):
+ os.unlink (logfile)
+
+ self.addTearDownHook(cleanup)
+
+ if os.path.exists (logfile):
+ f = open(logfile)
+ lines = f.readlines()
+ num_errors = 0
+ for line in lines:
+ if string.find(line, "$__lldb") != -1:
+ if num_errors == 0:
+ print("error: found spurious name lookups when evaluating an expression:")
+ num_errors += 1
+ print(line, end='')
+ self.assertTrue(num_errors == 0, "Spurious lookups detected")
+ f.close()