1"""Test printing ivars and ObjC objects captured in blocks that are made in methods of an ObjC class.""" 2 3import lldb 4from lldbsuite.test.decorators import * 5from lldbsuite.test.lldbtest import * 6from lldbsuite.test import lldbutil 7 8 9class TestObjCIvarsInBlocks(TestBase): 10 11 mydir = TestBase.compute_mydir(__file__) 12 13 def setUp(self): 14 # Call super's setUp(). 15 TestBase.setUp(self) 16 # Find the line numbers to break inside main(). 17 self.main_source = "main.m" 18 self.class_source = "ivars-in-blocks.m" 19 self.class_source_file_spec = lldb.SBFileSpec(self.class_source) 20 21 @add_test_categories(['pyapi']) 22 @skipIf(dwarf_version=['<', '4']) 23 @expectedFailureAll( 24 archs=["i[3-6]86"], 25 bugnumber="This test requires the 2.0 runtime, so it will fail on i386") 26 def test_with_python_api(self): 27 """Test printing the ivars of the self when captured in blocks""" 28 self.build() 29 exe = self.getBuildArtifact("a.out") 30 31 target = self.dbg.CreateTarget(exe) 32 self.assertTrue(target, VALID_TARGET) 33 34 breakpoint = target.BreakpointCreateBySourceRegex( 35 '// Break here inside the block.', self.class_source_file_spec) 36 self.assertTrue(breakpoint, VALID_BREAKPOINT) 37 38 breakpoint_two = target.BreakpointCreateBySourceRegex( 39 '// Break here inside the class method block.', self.class_source_file_spec) 40 self.assertTrue(breakpoint, VALID_BREAKPOINT) 41 42 process = target.LaunchSimple( 43 None, None, self.get_process_working_directory()) 44 self.assertTrue(process, "Created a process.") 45 self.assertTrue( 46 process.GetState() == lldb.eStateStopped, 47 "Stopped it too.") 48 49 thread_list = lldbutil.get_threads_stopped_at_breakpoint( 50 process, breakpoint) 51 self.assertTrue(len(thread_list) == 1) 52 thread = thread_list[0] 53 54 frame = thread.GetFrameAtIndex(0) 55 self.assertTrue(frame, "frame 0 is valid") 56 57 # First use the FindVariable API to see if we can find the ivar by 58 # undecorated name: 59 direct_blocky = frame.GetValueForVariablePath("blocky_ivar") 60 self.assertTrue(direct_blocky, "Found direct access to blocky_ivar.") 61 62 # Now get it as a member of "self" and make sure the two values are 63 # equal: 64 self_var = frame.GetValueForVariablePath("self") 65 self.assertTrue(self_var, "Found self in block.") 66 indirect_blocky = self_var.GetChildMemberWithName("blocky_ivar") 67 self.assertTrue(indirect_blocky, "Found blocky_ivar through self") 68 69 error = lldb.SBError() 70 direct_value = direct_blocky.GetValueAsSigned(error) 71 self.assertTrue(error.Success(), "Got direct value for blocky_ivar") 72 73 indirect_value = indirect_blocky.GetValueAsSigned(error) 74 self.assertTrue(error.Success(), "Got indirect value for blocky_ivar") 75 76 self.assertTrue( 77 direct_value == indirect_value, 78 "Direct and indirect values are equal.") 79 80 # Now make sure that we can get at the captured ivar through the expression parser. 81 # Doing a little trivial math will force this into the real expression 82 # parser: 83 direct_expr = frame.EvaluateExpression("blocky_ivar + 10") 84 self.assertTrue( 85 direct_expr, 86 "Got blocky_ivar through the expression parser") 87 88 # Again, get the value through self directly and make sure they are the 89 # same: 90 indirect_expr = frame.EvaluateExpression("self->blocky_ivar + 10") 91 self.assertTrue( 92 indirect_expr, 93 "Got blocky ivar through expression parser using self.") 94 95 direct_value = direct_expr.GetValueAsSigned(error) 96 self.assertTrue( 97 error.Success(), 98 "Got value from direct use of expression parser") 99 100 indirect_value = indirect_expr.GetValueAsSigned(error) 101 self.assertTrue( 102 error.Success(), 103 "Got value from indirect access using the expression parser") 104 105 self.assertTrue( 106 direct_value == indirect_value, 107 "Direct ivar access and indirect through expression parser produce same value.") 108 109 process.Continue() 110 self.assertTrue( 111 process.GetState() == lldb.eStateStopped, 112 "Stopped at the second breakpoint.") 113 114 thread_list = lldbutil.get_threads_stopped_at_breakpoint( 115 process, breakpoint_two) 116 self.assertTrue(len(thread_list) == 1) 117 thread = thread_list[0] 118 119 frame = thread.GetFrameAtIndex(0) 120 self.assertTrue(frame, "frame 0 is valid") 121 122 expr = frame.EvaluateExpression("(ret)") 123 self.assertTrue( 124 expr, "Successfully got a local variable in a block in a class method.") 125 126 ret_value_signed = expr.GetValueAsSigned(error) 127 self.trace('ret_value_signed = %i' % (ret_value_signed)) 128 self.assertTrue( 129 ret_value_signed == 5, 130 "The local variable in the block was what we expected.") 131