1""" 2Use lldb Python API to verify that expression evaluation for property references uses the correct getters and setters 3""" 4 5 6 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11 12 13class ObjCPropertyTestCase(TestBase): 14 15 def setUp(self): 16 # Call super's setUp(). 17 TestBase.setUp(self) 18 19 # Find the line number to break for main.c. 20 self.source_name = 'main.m' 21 22 @add_test_categories(['pyapi']) 23 def test_objc_properties(self): 24 """Test that expr uses the correct property getters and setters""" 25 if self.getArchitecture() == 'i386': 26 self.skipTest("requires modern objc runtime") 27 28 self.build() 29 exe = self.getBuildArtifact("a.out") 30 31 # Create a target from the debugger. 32 33 target = self.dbg.CreateTarget(exe) 34 self.assertTrue(target, VALID_TARGET) 35 36 # Set up our breakpoints: 37 38 main_bkpt = target.BreakpointCreateBySourceRegex( 39 "Set a breakpoint here.", lldb.SBFileSpec(self.source_name)) 40 self.assertTrue(main_bkpt and 41 main_bkpt.GetNumLocations() == 1, 42 VALID_BREAKPOINT) 43 44 # Now launch the process, and do not stop at the entry point. 45 process = target.LaunchSimple( 46 None, None, self.get_process_working_directory()) 47 48 self.assertState(process.GetState(), lldb.eStateStopped, 49 PROCESS_STOPPED) 50 51 threads = lldbutil.get_threads_stopped_at_breakpoint( 52 process, main_bkpt) 53 self.assertEquals(len(threads), 1) 54 thread = threads[0] 55 frame = thread.GetFrameAtIndex(0) 56 57 mine = frame.FindVariable("mine") 58 self.assertTrue(mine.IsValid()) 59 access_count = mine.GetChildMemberWithName("_access_count") 60 self.assertTrue(access_count.IsValid()) 61 start_access_count = access_count.GetValueAsUnsigned(123456) 62 self.assertNotEqual(start_access_count, 123456) 63 64 # 65 # The first set of tests test calling the getter & setter of 66 # a property that actually only has a getter & setter and no 67 # @property. 68 # 69 nonexistant_value = frame.EvaluateExpression( 70 "mine.nonexistantInt", False) 71 nonexistant_error = nonexistant_value.GetError() 72 self.assertSuccess(nonexistant_error) 73 nonexistant_int = nonexistant_value.GetValueAsUnsigned(123456) 74 self.assertEquals(nonexistant_int, 6) 75 76 # Calling the getter function would up the access count, so make sure 77 # that happened. 78 79 new_access_count = access_count.GetValueAsUnsigned(123456) 80 self.assertEquals(new_access_count - start_access_count, 1) 81 start_access_count = new_access_count 82 83 # 84 # Now call the setter, then make sure that 85 nonexistant_change = frame.EvaluateExpression( 86 "mine.nonexistantInt = 10", False) 87 nonexistant_error = nonexistant_change.GetError() 88 self.assertSuccess(nonexistant_error) 89 90 # Calling the setter function would up the access count, so make sure 91 # that happened. 92 93 new_access_count = access_count.GetValueAsUnsigned(123456) 94 self.assertEquals(new_access_count - start_access_count, 1) 95 start_access_count = new_access_count 96 97 # 98 # Now we call the getter of a property that is backed by an ivar, 99 # make sure it works and that we actually update the backing ivar. 100 # 101 102 backed_value = frame.EvaluateExpression("mine.backedInt", False) 103 backed_error = backed_value.GetError() 104 self.assertSuccess(backed_error) 105 backing_value = mine.GetChildMemberWithName("_backedInt") 106 self.assertTrue(backing_value.IsValid()) 107 self.assertTrue(backed_value.GetValueAsUnsigned(12345) 108 == backing_value.GetValueAsUnsigned(23456)) 109 110 value_from_typedef = frame.EvaluateExpression("typedefd.backedInt", False) 111 self.assertSuccess(value_from_typedef.GetError()) 112 self.assertEqual(value_from_typedef.GetValueAsUnsigned(12345), 113 backing_value.GetValueAsUnsigned(23456)) 114 115 unbacked_value = frame.EvaluateExpression("mine.unbackedInt", False) 116 unbacked_error = unbacked_value.GetError() 117 self.assertSuccess(unbacked_error) 118 119 idWithProtocol_value = frame.EvaluateExpression( 120 "mine.idWithProtocol", False) 121 idWithProtocol_error = idWithProtocol_value.GetError() 122 self.assertSuccess(idWithProtocol_error) 123 self.assertEquals(idWithProtocol_value.GetTypeName(), "id") 124 125 # Make sure that class property getter works as expected 126 value = frame.EvaluateExpression("BaseClass.classInt", False) 127 self.assertSuccess(value.GetError()) 128 self.assertEquals(value.GetValueAsUnsigned(11111), 123) 129 130 # Make sure that class property setter works as expected 131 value = frame.EvaluateExpression("BaseClass.classInt = 234", False) 132 self.assertSuccess(value.GetError()) 133 134 # Verify that setter above actually worked 135 value = frame.EvaluateExpression("BaseClass.classInt", False) 136 self.assertSuccess(value.GetError()) 137 self.assertEquals(value.GetValueAsUnsigned(11111), 234) 138 139 # Test that accessing two distinct class and instance properties that 140 # share the same name works. 141 self.expect_expr("mine.propConflict", result_value="4") 142 self.expect_expr("BaseClass.propConflict", result_value="6") 143