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