summaryrefslogtreecommitdiffstats
path: root/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2016-01-06 20:12:03 +0000
committerdim <dim@FreeBSD.org>2016-01-06 20:12:03 +0000
commit78b9749c0a4ea980a8b934645da6ae98fcc665e8 (patch)
treedd2a1ddf0476664c2b823409c36cbccd52662ca7 /packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value
parent60cb593f9d55fa5ca7a5372b731f2330345b4b9a (diff)
downloadFreeBSD-src-78b9749c0a4ea980a8b934645da6ae98fcc665e8.zip
FreeBSD-src-78b9749c0a4ea980a8b934645da6ae98fcc665e8.tar.gz
Vendor import of lldb trunk r256945:
https://llvm.org/svn/llvm-project/lldb/trunk@256945
Diffstat (limited to 'packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value')
-rw-r--r--packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/Makefile6
-rw-r--r--packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py177
-rw-r--r--packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/dynamic-value.m147
3 files changed, 330 insertions, 0 deletions
diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/Makefile
new file mode 100644
index 0000000..a981f4b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+OBJC_SOURCES := dynamic-value.m
+LDFLAGS = $(CFLAGS) -lobjc -framework Foundation
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py
new file mode 100644
index 0000000..acddfb8
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py
@@ -0,0 +1,177 @@
+"""
+Use lldb Python API to test dynamic values in ObjC
+"""
+
+from __future__ import print_function
+
+
+
+import os, time
+import re
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+class ObjCDynamicValueTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ # Find the line number to break for main.c.
+
+ self.source_name = 'dynamic-value.m'
+ self.set_property_line = line_number(self.source_name, '// This is the line in setProperty, make sure we step to here.')
+ self.handle_SourceBase = line_number(self.source_name,
+ '// Break here to check dynamic values.')
+ self.main_before_setProperty_line = line_number(self.source_name,
+ '// Break here to see if we can step into real method.')
+
+ @skipUnlessDarwin
+ @add_test_categories(['pyapi'])
+ @expectedFailureDarwin("llvm.org/pr20271 rdar://18684107")
+ def test_get_objc_dynamic_vals(self):
+ """Test fetching ObjC dynamic values."""
+ if self.getArchitecture() == 'i386':
+ # rdar://problem/9946499
+ self.skipTest("Dynamic types for ObjC V1 runtime not implemented")
+
+ self.build()
+ exe = os.path.join(os.getcwd(), "a.out")
+
+ # Create a target from the debugger.
+
+ target = self.dbg.CreateTarget (exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ # Set up our breakpoints:
+
+ handle_SourceBase_bkpt = target.BreakpointCreateByLocation(self.source_name, self.handle_SourceBase)
+ self.assertTrue(handle_SourceBase_bkpt and
+ handle_SourceBase_bkpt.GetNumLocations() == 1,
+ VALID_BREAKPOINT)
+
+ main_before_setProperty_bkpt = target.BreakpointCreateByLocation(self.source_name, self.main_before_setProperty_line)
+ self.assertTrue(main_before_setProperty_bkpt and
+ main_before_setProperty_bkpt.GetNumLocations() == 1,
+ VALID_BREAKPOINT)
+
+ # Now launch the process, and do not stop at the entry point.
+ process = target.LaunchSimple (None, None, self.get_process_working_directory())
+
+ self.assertTrue(process.GetState() == lldb.eStateStopped,
+ PROCESS_STOPPED)
+
+ threads = lldbutil.get_threads_stopped_at_breakpoint (process, main_before_setProperty_bkpt)
+ self.assertTrue (len(threads) == 1)
+ thread = threads[0]
+
+ #
+ # At this point, myObserver has a Source pointer that is actually a KVO swizzled SourceDerived
+ # make sure we can get that properly:
+
+ frame = thread.GetFrameAtIndex(0)
+ myObserver = frame.FindVariable('myObserver', lldb.eDynamicCanRunTarget)
+ self.assertTrue (myObserver)
+ myObserver_source = myObserver.GetChildMemberWithName ('_source', lldb.eDynamicCanRunTarget)
+ self.examine_SourceDerived_ptr (myObserver_source)
+
+ #
+ # Make sure a static value can be correctly turned into a dynamic value.
+
+ frame = thread.GetFrameAtIndex(0)
+ myObserver_static = frame.FindVariable('myObserver', lldb.eNoDynamicValues)
+ self.assertTrue (myObserver_static)
+ myObserver = myObserver_static.GetDynamicValue (lldb.eDynamicCanRunTarget)
+ myObserver_source = myObserver.GetChildMemberWithName ('_source', lldb.eDynamicCanRunTarget)
+ self.examine_SourceDerived_ptr (myObserver_source)
+
+ # The "frame var" code uses another path to get into children, so let's
+ # make sure that works as well:
+
+ result = lldb.SBCommandReturnObject()
+
+ self.expect('frame var -d run-target myObserver->_source', 'frame var finds its way into a child member',
+ patterns = ['\(SourceDerived \*\)'])
+
+ # check that our ObjC GetISA() does a good job at hiding KVO swizzled classes
+
+ self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden',
+ substrs = ['SourceDerived'])
+
+ self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden', matching = False,
+ substrs = ['NSKVONotify'])
+
+ # This test is not entirely related to the main thrust of this test case, but since we're here,
+ # try stepping into setProperty, and make sure we get into the version in Source:
+
+ thread.StepInto()
+
+ threads = lldbutil.get_stopped_threads (process, lldb.eStopReasonPlanComplete)
+ self.assertTrue (len(threads) == 1)
+ line_entry = threads[0].GetFrameAtIndex(0).GetLineEntry()
+
+ self.assertEqual (line_entry.GetLine(), self.set_property_line)
+ self.assertEqual (line_entry.GetFileSpec().GetFilename(), self.source_name)
+
+ # Okay, back to the main business. Continue to the handle_SourceBase and make sure we get the correct dynamic value.
+
+ threads = lldbutil.continue_to_breakpoint (process, handle_SourceBase_bkpt)
+ self.assertTrue (len(threads) == 1)
+ thread = threads[0]
+
+ frame = thread.GetFrameAtIndex(0)
+
+ # Get "object" using FindVariable:
+
+ noDynamic = lldb.eNoDynamicValues
+ useDynamic = lldb.eDynamicCanRunTarget
+
+ object_static = frame.FindVariable ('object', noDynamic)
+ object_dynamic = frame.FindVariable ('object', useDynamic)
+
+ # Delete this object to make sure that this doesn't cause havoc with the dynamic object that depends on it.
+ del (object_static)
+
+ self.examine_SourceDerived_ptr (object_dynamic)
+
+ # Get "this" using FindValue, make sure that works too:
+ object_static = frame.FindValue ('object', lldb.eValueTypeVariableArgument, noDynamic)
+ object_dynamic = frame.FindValue ('object', lldb.eValueTypeVariableArgument, useDynamic)
+ del (object_static)
+ self.examine_SourceDerived_ptr (object_dynamic)
+
+ # Get "this" using the EvaluateExpression:
+ object_static = frame.EvaluateExpression ('object', noDynamic)
+ object_dynamic = frame.EvaluateExpression ('object', useDynamic)
+ del (object_static)
+ self.examine_SourceDerived_ptr (object_dynamic)
+
+ # Continue again to the handle_SourceBase and make sure we get the correct dynamic value.
+ # This one looks exactly the same, but in fact this is an "un-KVO'ed" version of SourceBase, so
+ # its isa pointer points to SourceBase not NSKVOSourceBase or whatever...
+
+ threads = lldbutil.continue_to_breakpoint (process, handle_SourceBase_bkpt)
+ self.assertTrue (len(threads) == 1)
+ thread = threads[0]
+
+ frame = thread.GetFrameAtIndex(0)
+
+ # Get "object" using FindVariable:
+
+ object_static = frame.FindVariable ('object', noDynamic)
+ object_dynamic = frame.FindVariable ('object', useDynamic)
+
+ # Delete this object to make sure that this doesn't cause havoc with the dynamic object that depends on it.
+ del (object_static)
+
+ self.examine_SourceDerived_ptr (object_dynamic)
+
+ def examine_SourceDerived_ptr (self, object):
+ self.assertTrue (object)
+ self.assertTrue (object.GetTypeName().find ('SourceDerived') != -1)
+ derivedValue = object.GetChildMemberWithName ('_derivedValue')
+ self.assertTrue (derivedValue)
+ self.assertTrue (int (derivedValue.GetValue(), 0) == 30)
diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/dynamic-value.m b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/dynamic-value.m
new file mode 100644
index 0000000..2bcb76b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/dynamic-value.m
@@ -0,0 +1,147 @@
+#import <Foundation/Foundation.h>
+
+// SourceBase will be the base class of Source. We'll pass a Source object into a
+// function as a SourceBase, and then see if the dynamic typing can get us through the KVO
+// goo and all the way back to Source.
+
+@interface SourceBase: NSObject
+{
+ uint32_t _value;
+}
+- (SourceBase *) init;
+- (uint32_t) getValue;
+@end
+
+@implementation SourceBase
+- (SourceBase *) init
+{
+ [super init];
+ _value = 10;
+ return self;
+}
+- (uint32_t) getValue
+{
+ return _value;
+}
+@end
+
+// Source is a class that will be observed by the Observer class below.
+// When Observer sets itself up to observe this property (in initWithASource)
+// the KVO system will overwrite the "isa" pointer of the object with the "kvo'ed"
+// one.
+
+@interface Source : SourceBase
+{
+ int _property;
+}
+- (Source *) init;
+- (void) setProperty: (int) newValue;
+@end
+
+@implementation Source
+- (Source *) init
+{
+ [super init];
+ _property = 20;
+ return self;
+}
+- (void) setProperty: (int) newValue
+{
+ _property = newValue; // This is the line in setProperty, make sure we step to here.
+}
+@end
+
+@interface SourceDerived : Source
+{
+ int _derivedValue;
+}
+- (SourceDerived *) init;
+- (uint32_t) getValue;
+@end
+
+@implementation SourceDerived
+- (SourceDerived *) init
+{
+ [super init];
+ _derivedValue = 30;
+ return self;
+}
+- (uint32_t) getValue
+{
+ return _derivedValue;
+}
+@end
+
+// Observer is the object that will watch Source and cause KVO to swizzle it...
+
+@interface Observer : NSObject
+{
+ Source *_source;
+}
++ (Observer *) observerWithSource: (Source *) source;
+- (Observer *) initWithASource: (Source *) source;
+- (void) observeValueForKeyPath: (NSString *) path
+ ofObject: (id) object
+ change: (NSDictionary *) change
+ context: (void *) context;
+@end
+
+@implementation Observer
+
++ (Observer *) observerWithSource: (Source *) inSource;
+{
+ Observer *retval;
+
+ retval = [[Observer alloc] initWithASource: inSource];
+ return retval;
+}
+
+- (Observer *) initWithASource: (Source *) source
+{
+ [super init];
+ _source = source;
+ [_source addObserver: self
+ forKeyPath: @"property"
+ options: (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
+ context: NULL];
+ return self;
+}
+
+- (void) observeValueForKeyPath: (NSString *) path
+ ofObject: (id) object
+ change: (NSDictionary *) change
+ context: (void *) context
+{
+ printf ("Observer function called.\n");
+ return;
+}
+@end
+
+uint32_t
+handle_SourceBase (SourceBase *object)
+{
+ return [object getValue]; // Break here to check dynamic values.
+}
+
+int main ()
+{
+ Source *mySource;
+ Observer *myObserver;
+
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+ mySource = [[SourceDerived alloc] init];
+ myObserver = [Observer observerWithSource: mySource];
+
+ [mySource setProperty: 5]; // Break here to see if we can step into real method.
+
+ uint32_t return_value = handle_SourceBase (mySource);
+
+ SourceDerived *unwatchedSource = [[SourceDerived alloc] init];
+
+ return_value = handle_SourceBase (unwatchedSource);
+
+ [pool release];
+ return 0;
+
+}
OpenPOWER on IntegriCloud