forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			225 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Python
		
	
	
	
| """Test stepping through ObjC method dispatch in various forms."""
 | |
| 
 | |
| from __future__ import print_function
 | |
| 
 | |
| 
 | |
| import os
 | |
| import time
 | |
| import lldb
 | |
| from lldbsuite.test.decorators import *
 | |
| from lldbsuite.test.lldbtest import *
 | |
| from lldbsuite.test import lldbutil
 | |
| 
 | |
| 
 | |
| class TestObjCStepping(TestBase):
 | |
| 
 | |
|     def getCategories(self):
 | |
|         return ['basic_process']
 | |
| 
 | |
|     mydir = TestBase.compute_mydir(__file__)
 | |
| 
 | |
|     def setUp(self):
 | |
|         # Call super's setUp().
 | |
|         TestBase.setUp(self)
 | |
|         # Find the line numbers that we will step to in main:
 | |
|         self.main_source = "stepping-tests.m"
 | |
|         self.source_randomMethod_line = line_number(
 | |
|             self.main_source, '// Source randomMethod start line.')
 | |
|         self.sourceBase_randomMethod_line = line_number(
 | |
|             self.main_source, '// SourceBase randomMethod start line.')
 | |
|         self.source_returnsStruct_start_line = line_number(
 | |
|             self.main_source, '// Source returnsStruct start line.')
 | |
|         self.sourceBase_returnsStruct_start_line = line_number(
 | |
|             self.main_source, '// SourceBase returnsStruct start line.')
 | |
|         self.stepped_past_nil_line = line_number(
 | |
|             self.main_source, '// Step over nil should stop here.')
 | |
| 
 | |
|     @skipUnlessDarwin
 | |
|     @add_test_categories(['pyapi'])
 | |
|     def test_with_python_api(self):
 | |
|         """Test stepping through ObjC method dispatch in various forms."""
 | |
|         self.build()
 | |
|         exe = os.path.join(os.getcwd(), "a.out")
 | |
| 
 | |
|         target = self.dbg.CreateTarget(exe)
 | |
|         self.assertTrue(target, VALID_TARGET)
 | |
| 
 | |
|         self.main_source_spec = lldb.SBFileSpec(self.main_source)
 | |
| 
 | |
|         breakpoints_to_disable = []
 | |
| 
 | |
|         break1 = target.BreakpointCreateBySourceRegex(
 | |
|             "// Set first breakpoint here.", self.main_source_spec)
 | |
|         self.assertTrue(break1, VALID_BREAKPOINT)
 | |
|         breakpoints_to_disable.append(break1)
 | |
| 
 | |
|         break2 = target.BreakpointCreateBySourceRegex(
 | |
|             "// Set second breakpoint here.", self.main_source_spec)
 | |
|         self.assertTrue(break2, VALID_BREAKPOINT)
 | |
|         breakpoints_to_disable.append(break2)
 | |
| 
 | |
|         break3 = target.BreakpointCreateBySourceRegex(
 | |
|             '// Set third breakpoint here.', self.main_source_spec)
 | |
|         self.assertTrue(break3, VALID_BREAKPOINT)
 | |
|         breakpoints_to_disable.append(break3)
 | |
| 
 | |
|         break4 = target.BreakpointCreateBySourceRegex(
 | |
|             '// Set fourth breakpoint here.', self.main_source_spec)
 | |
|         self.assertTrue(break4, VALID_BREAKPOINT)
 | |
|         breakpoints_to_disable.append(break4)
 | |
| 
 | |
|         break5 = target.BreakpointCreateBySourceRegex(
 | |
|             '// Set fifth breakpoint here.', self.main_source_spec)
 | |
|         self.assertTrue(break5, VALID_BREAKPOINT)
 | |
|         breakpoints_to_disable.append(break5)
 | |
| 
 | |
|         break_returnStruct_call_super = target.BreakpointCreateBySourceRegex(
 | |
|             '// Source returnsStruct call line.', self.main_source_spec)
 | |
|         self.assertTrue(break_returnStruct_call_super, VALID_BREAKPOINT)
 | |
|         breakpoints_to_disable.append(break_returnStruct_call_super)
 | |
| 
 | |
|         break_step_nil = target.BreakpointCreateBySourceRegex(
 | |
|             '// Set nil step breakpoint here.', self.main_source_spec)
 | |
|         self.assertTrue(break_step_nil, 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.
 | |
|         threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1)
 | |
|         if len(threads) != 1:
 | |
|             self.fail("Failed to stop at breakpoint 1.")
 | |
| 
 | |
|         thread = threads[0]
 | |
| 
 | |
|         mySource = thread.GetFrameAtIndex(0).FindVariable("mySource")
 | |
|         self.assertTrue(mySource, "Found mySource local variable.")
 | |
|         mySource_isa = mySource.GetChildMemberWithName("isa")
 | |
|         self.assertTrue(mySource_isa, "Found mySource->isa local variable.")
 | |
|         className = mySource_isa.GetSummary()
 | |
| 
 | |
|         if self.TraceOn():
 | |
|             print(mySource_isa)
 | |
| 
 | |
|         # Lets delete mySource so we can check that after stepping a child variable
 | |
|         # with no parent persists and is useful.
 | |
|         del (mySource)
 | |
| 
 | |
|         # Now step in, that should leave us in the Source randomMethod:
 | |
|         thread.StepInto()
 | |
|         line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine()
 | |
|         self.assertTrue(
 | |
|             line_number == self.source_randomMethod_line,
 | |
|             "Stepped into Source randomMethod.")
 | |
| 
 | |
|         # Now step in again, through the super call, and that should leave us
 | |
|         # in the SourceBase randomMethod:
 | |
|         thread.StepInto()
 | |
|         line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine()
 | |
|         self.assertTrue(
 | |
|             line_number == self.sourceBase_randomMethod_line,
 | |
|             "Stepped through super into SourceBase randomMethod.")
 | |
| 
 | |
|         threads = lldbutil.continue_to_breakpoint(process, break2)
 | |
|         self.assertTrue(
 | |
|             len(threads) == 1,
 | |
|             "Continued to second breakpoint in main.")
 | |
| 
 | |
|         # Again, step in twice gets us to a stret method and a stret super
 | |
|         # call:
 | |
|         thread = threads[0]
 | |
|         thread.StepInto()
 | |
|         line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine()
 | |
|         self.assertTrue(
 | |
|             line_number == self.source_returnsStruct_start_line,
 | |
|             "Stepped into Source returnsStruct.")
 | |
| 
 | |
|         threads = lldbutil.continue_to_breakpoint(
 | |
|             process, break_returnStruct_call_super)
 | |
|         self.assertTrue(
 | |
|             len(threads) == 1,
 | |
|             "Stepped to the call super line in Source returnsStruct.")
 | |
|         thread = threads[0]
 | |
| 
 | |
|         thread.StepInto()
 | |
|         line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine()
 | |
|         self.assertTrue(
 | |
|             line_number == self.sourceBase_returnsStruct_start_line,
 | |
|             "Stepped through super into SourceBase returnsStruct.")
 | |
| 
 | |
|         # Cool now continue to get past the call that initializes the Observer, and then do our steps in again to see that
 | |
|         # we can find our way when we're stepping through a KVO swizzled
 | |
|         # object.
 | |
| 
 | |
|         threads = lldbutil.continue_to_breakpoint(process, break3)
 | |
|         self.assertTrue(
 | |
|             len(threads) == 1,
 | |
|             "Continued to third breakpoint in main, our object should now be swizzled.")
 | |
| 
 | |
|         newClassName = mySource_isa.GetSummary()
 | |
| 
 | |
|         if self.TraceOn():
 | |
|             print(mySource_isa)
 | |
| 
 | |
|         self.assertTrue(
 | |
|             newClassName != className,
 | |
|             "The isa did indeed change, swizzled!")
 | |
| 
 | |
|         # Now step in, that should leave us in the Source randomMethod:
 | |
|         thread = threads[0]
 | |
|         thread.StepInto()
 | |
|         line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine()
 | |
|         self.assertTrue(
 | |
|             line_number == self.source_randomMethod_line,
 | |
|             "Stepped into Source randomMethod in swizzled object.")
 | |
| 
 | |
|         # Now step in again, through the super call, and that should leave us
 | |
|         # in the SourceBase randomMethod:
 | |
|         thread.StepInto()
 | |
|         line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine()
 | |
|         self.assertTrue(
 | |
|             line_number == self.sourceBase_randomMethod_line,
 | |
|             "Stepped through super into SourceBase randomMethod in swizzled object.")
 | |
| 
 | |
|         threads = lldbutil.continue_to_breakpoint(process, break4)
 | |
|         self.assertTrue(
 | |
|             len(threads) == 1,
 | |
|             "Continued to fourth breakpoint in main.")
 | |
|         thread = threads[0]
 | |
| 
 | |
|         # Again, step in twice gets us to a stret method and a stret super
 | |
|         # call:
 | |
|         thread.StepInto()
 | |
|         line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine()
 | |
|         self.assertTrue(
 | |
|             line_number == self.source_returnsStruct_start_line,
 | |
|             "Stepped into Source returnsStruct in swizzled object.")
 | |
| 
 | |
|         threads = lldbutil.continue_to_breakpoint(
 | |
|             process, break_returnStruct_call_super)
 | |
|         self.assertTrue(
 | |
|             len(threads) == 1,
 | |
|             "Stepped to the call super line in Source returnsStruct - second time.")
 | |
|         thread = threads[0]
 | |
| 
 | |
|         thread.StepInto()
 | |
|         line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine()
 | |
|         self.assertTrue(
 | |
|             line_number == self.sourceBase_returnsStruct_start_line,
 | |
|             "Stepped through super into SourceBase returnsStruct in swizzled object.")
 | |
| 
 | |
|         for bkpt in breakpoints_to_disable:
 | |
|             bkpt.SetEnabled(False)
 | |
| 
 | |
|         threads = lldbutil.continue_to_breakpoint(process, break_step_nil)
 | |
|         self.assertTrue(len(threads) == 1, "Continued to step nil breakpoint.")
 | |
| 
 | |
|         thread.StepInto()
 | |
|         line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine()
 | |
|         self.assertTrue(
 | |
|             line_number == self.stepped_past_nil_line,
 | |
|             "Step in over dispatch to nil stepped over.")
 |