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