From 18cb2af61e7312f86bffc795c2249e78367d1aea Mon Sep 17 00:00:00 2001 From: Frederik Carlier Date: Sun, 17 Nov 2024 00:31:23 +0100 Subject: [PATCH 1/4] Add test for selector forwarding --- Tests/base/GSFFIInvocation/TestInfo | 0 Tests/base/GSFFIInvocation/basic.m | 114 ++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 Tests/base/GSFFIInvocation/TestInfo create mode 100644 Tests/base/GSFFIInvocation/basic.m diff --git a/Tests/base/GSFFIInvocation/TestInfo b/Tests/base/GSFFIInvocation/TestInfo new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Tests/base/GSFFIInvocation/basic.m b/Tests/base/GSFFIInvocation/basic.m new file mode 100644 index 0000000000..b52d3895f2 --- /dev/null +++ b/Tests/base/GSFFIInvocation/basic.m @@ -0,0 +1,114 @@ +#import +#import "Testing.h" +#import "ObjectTesting.h" + +@protocol NSMenuItem +- (NSString*) keyEquivalent; +- (void) setKeyEquivalent: (NSString*)aKeyEquivalent; +@end + +@interface NSMenuItem : NSObject +{ + NSString *_keyEquivalent; +} +@end + +@implementation NSMenuItem +- (void) setKeyEquivalent: (NSString*)aKeyEquivalent +{ + ASSIGNCOPY(_keyEquivalent, aKeyEquivalent); +} + +- (NSString*) keyEquivalent +{ + return _keyEquivalent; +} +@end + +@interface GSFakeNSMenuItem : NSObject +{ + NSMenuItem* _originalItem; +} + +- (id) initWithItem: (NSMenuItem*)item; +- (NSMenuItem*) originalItem; +- (id) target; +- (SEL)action; +- (void) action: (id)sender; +@end + +@implementation GSFakeNSMenuItem +- (id) initWithItem: (NSMenuItem*)item +{ + self = [super init]; + if (self) + { + _originalItem = item; + } + return self; +} + +- (NSMenuItem*) originalItem +{ + return _originalItem; +} + +- (id)target +{ + return self; +} + +- (SEL)action +{ + return @selector(action:); +} + +- (id)forwardingTargetForSelector:(SEL)selector +{ + if ([_originalItem respondsToSelector:selector]) + return _originalItem; + return nil; +} + +- (void)forwardInvocation:(NSInvocation *)invocation +{ + SEL selector = [invocation selector]; + + // Forward any invocation to the original item if it supports it... + if ([_originalItem respondsToSelector:selector]) + [invocation invokeWithTarget:_originalItem]; +} + +-(NSMethodSignature*)methodSignatureForSelector:(SEL)selector +{ + NSMethodSignature *signature = [[_originalItem class] instanceMethodSignatureForSelector:selector]; + if(signature == nil) + { + signature = [NSMethodSignature signatureWithObjCTypes:"@^v^c"]; + } + return(signature); +} + +- (void)doesNotRecognizeSelector:(SEL)selector +{ + NSLog(@"%s:selector not recognized: %@", __PRETTY_FUNCTION__, NSStringFromSelector(selector)); +} +@end + +int main(int argc,char **argv) +{ + START_SET("GSFFIInvocation") + + NSMenuItem *item = [NSMenuItem alloc]; + [item setKeyEquivalent:@"Hello, World!"]; + + GSFakeNSMenuItem *fakeItem = [[GSFakeNSMenuItem alloc] initWithItem:item]; + + NSString *itemKeyEquivalent = [item keyEquivalent]; + NSString *fakeItemKeyEquivalent = [fakeItem keyEquivalent]; + + NSLog(@"Item key equivalent: %@, fake item key equivalent: %@", itemKeyEquivalent, fakeItemKeyEquivalent); + + END_SET("GSFFIInvocation") + return 0; +} From 0304fdd231439c11a8f51d03f4f761f09cbb52c7 Mon Sep 17 00:00:00 2001 From: Frederik Carlier Date: Sun, 17 Nov 2024 00:46:35 +0100 Subject: [PATCH 2/4] Add string test --- Tests/base/GSFFIInvocation/basic.m | 1 + Tests/base/GSFFIInvocation/string.m | 91 +++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 Tests/base/GSFFIInvocation/string.m diff --git a/Tests/base/GSFFIInvocation/basic.m b/Tests/base/GSFFIInvocation/basic.m index b52d3895f2..53b904c905 100644 --- a/Tests/base/GSFFIInvocation/basic.m +++ b/Tests/base/GSFFIInvocation/basic.m @@ -107,6 +107,7 @@ int main(int argc,char **argv) NSString *itemKeyEquivalent = [item keyEquivalent]; NSString *fakeItemKeyEquivalent = [fakeItem keyEquivalent]; + PASS_EQUAL(itemKeyEquivalent, fakeItemKeyEquivalent, "keyEquivalent selector is forwarded from the fake item to the actual item"); NSLog(@"Item key equivalent: %@, fake item key equivalent: %@", itemKeyEquivalent, fakeItemKeyEquivalent); END_SET("GSFFIInvocation") diff --git a/Tests/base/GSFFIInvocation/string.m b/Tests/base/GSFFIInvocation/string.m new file mode 100644 index 0000000000..ba273afca2 --- /dev/null +++ b/Tests/base/GSFFIInvocation/string.m @@ -0,0 +1,91 @@ +#import +#import "Testing.h" +#import "ObjectTesting.h" + +@interface GSFakeNSString : NSObject +{ + NSString* _originalItem; +} + +- (id) initWithItem: (NSString*)item; +- (NSString*) originalItem; +- (id) target; +- (SEL)action; +- (void) action: (id)sender; +@end + +@implementation GSFakeNSString +- (id) initWithItem: (NSString*)item +{ + self = [super init]; + if (self) + { + _originalItem = item; + } + return self; +} + +- (NSString*) originalItem +{ + return _originalItem; +} + +- (id)target +{ + return self; +} + +- (SEL)action +{ + return @selector(action:); +} + +- (id)forwardingTargetForSelector:(SEL)selector +{ + if ([_originalItem respondsToSelector:selector]) + return _originalItem; + return nil; +} + +- (void)forwardInvocation:(NSInvocation *)invocation +{ + SEL selector = [invocation selector]; + + // Forward any invocation to the original item if it supports it... + if ([_originalItem respondsToSelector:selector]) + [invocation invokeWithTarget:_originalItem]; +} + +-(NSMethodSignature*)methodSignatureForSelector:(SEL)selector +{ + NSMethodSignature *signature = [[_originalItem class] instanceMethodSignatureForSelector:selector]; + if(signature == nil) + { + signature = [NSMethodSignature signatureWithObjCTypes:"@^v^c"]; + } + return(signature); +} + +- (void)doesNotRecognizeSelector:(SEL)selector +{ + NSLog(@"%s:selector not recognized: %@", __PRETTY_FUNCTION__, NSStringFromSelector(selector)); +} +@end + +int main(int argc,char **argv) +{ + START_SET("GSFFIInvocation") + + NSString *string = @"Hello, World!"; + + GSFakeNSString *fakeString = [[GSFakeNSString alloc] initWithItem:string]; + + NSString *upperCaseString = [string uppercaseString]; + NSString *fakeUpperCaseString = [fakeString uppercaseString]; + + PASS_EQUAL(upperCaseString, fakeUpperCaseString, "uppercaseString selector is forwarded from the fake string to the actual NSString object"); + NSLog(@"Upper case string: %@, fake upper case string: %@", upperCaseString, fakeUpperCaseString); + + END_SET("GSFFIInvocation") + return 0; +} From e62ec64c17c44f2f2ee9ca8fb99c4a9364e1bae1 Mon Sep 17 00:00:00 2001 From: Frederik Carlier Date: Sun, 17 Nov 2024 12:58:16 +0100 Subject: [PATCH 3/4] PR feedback --- Tests/base/GSFFIInvocation/basic.m | 2 ++ Tests/base/GSFFIInvocation/string.m | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Tests/base/GSFFIInvocation/basic.m b/Tests/base/GSFFIInvocation/basic.m index 53b904c905..701628bd70 100644 --- a/Tests/base/GSFFIInvocation/basic.m +++ b/Tests/base/GSFFIInvocation/basic.m @@ -77,6 +77,8 @@ - (void)forwardInvocation:(NSInvocation *)invocation // Forward any invocation to the original item if it supports it... if ([_originalItem respondsToSelector:selector]) [invocation invokeWithTarget:_originalItem]; + else + [super forwardInvocation:invocation]; } -(NSMethodSignature*)methodSignatureForSelector:(SEL)selector diff --git a/Tests/base/GSFFIInvocation/string.m b/Tests/base/GSFFIInvocation/string.m index ba273afca2..db5c617792 100644 --- a/Tests/base/GSFFIInvocation/string.m +++ b/Tests/base/GSFFIInvocation/string.m @@ -54,6 +54,8 @@ - (void)forwardInvocation:(NSInvocation *)invocation // Forward any invocation to the original item if it supports it... if ([_originalItem respondsToSelector:selector]) [invocation invokeWithTarget:_originalItem]; + else + [super forwardInvocation:invocation]; } -(NSMethodSignature*)methodSignatureForSelector:(SEL)selector @@ -83,8 +85,8 @@ int main(int argc,char **argv) NSString *upperCaseString = [string uppercaseString]; NSString *fakeUpperCaseString = [fakeString uppercaseString]; - PASS_EQUAL(upperCaseString, fakeUpperCaseString, "uppercaseString selector is forwarded from the fake string to the actual NSString object"); NSLog(@"Upper case string: %@, fake upper case string: %@", upperCaseString, fakeUpperCaseString); + PASS_EQUAL(upperCaseString, fakeUpperCaseString, "uppercaseString selector is forwarded from the fake string to the actual NSString object"); END_SET("GSFFIInvocation") return 0; From b1d96dd2d2b21533f15f7e74011c317ed244b301 Mon Sep 17 00:00:00 2001 From: Frederik Carlier Date: Sun, 17 Nov 2024 16:37:49 +0100 Subject: [PATCH 4/4] Add separate test for forwardingTargetForSelector and forwardInvocation --- .../{string.m => forwardInvocation.m} | 25 --------- .../forwardingTargetForSelector.m | 55 +++++++++++++++++++ 2 files changed, 55 insertions(+), 25 deletions(-) rename Tests/base/GSFFIInvocation/{string.m => forwardInvocation.m} (79%) create mode 100644 Tests/base/GSFFIInvocation/forwardingTargetForSelector.m diff --git a/Tests/base/GSFFIInvocation/string.m b/Tests/base/GSFFIInvocation/forwardInvocation.m similarity index 79% rename from Tests/base/GSFFIInvocation/string.m rename to Tests/base/GSFFIInvocation/forwardInvocation.m index db5c617792..3d2390f419 100644 --- a/Tests/base/GSFFIInvocation/string.m +++ b/Tests/base/GSFFIInvocation/forwardInvocation.m @@ -9,9 +9,6 @@ @interface GSFakeNSString : NSObject - (id) initWithItem: (NSString*)item; - (NSString*) originalItem; -- (id) target; -- (SEL)action; -- (void) action: (id)sender; @end @implementation GSFakeNSString @@ -30,23 +27,6 @@ - (NSString*) originalItem return _originalItem; } -- (id)target -{ - return self; -} - -- (SEL)action -{ - return @selector(action:); -} - -- (id)forwardingTargetForSelector:(SEL)selector -{ - if ([_originalItem respondsToSelector:selector]) - return _originalItem; - return nil; -} - - (void)forwardInvocation:(NSInvocation *)invocation { SEL selector = [invocation selector]; @@ -67,11 +47,6 @@ -(NSMethodSignature*)methodSignatureForSelector:(SEL)selector } return(signature); } - -- (void)doesNotRecognizeSelector:(SEL)selector -{ - NSLog(@"%s:selector not recognized: %@", __PRETTY_FUNCTION__, NSStringFromSelector(selector)); -} @end int main(int argc,char **argv) diff --git a/Tests/base/GSFFIInvocation/forwardingTargetForSelector.m b/Tests/base/GSFFIInvocation/forwardingTargetForSelector.m new file mode 100644 index 0000000000..f76acf51a4 --- /dev/null +++ b/Tests/base/GSFFIInvocation/forwardingTargetForSelector.m @@ -0,0 +1,55 @@ +#import +#import "Testing.h" +#import "ObjectTesting.h" + +@interface GSFakeNSString : NSObject +{ + NSString* _originalItem; +} + +- (id) initWithItem: (NSString*)item; +- (NSString*) originalItem; +@end + +@implementation GSFakeNSString +- (id) initWithItem: (NSString*)item +{ + self = [super init]; + if (self) + { + _originalItem = item; + } + return self; +} + +- (NSString*) originalItem +{ + return _originalItem; +} + +- (id)forwardingTargetForSelector:(SEL)selector +{ + if ([_originalItem respondsToSelector:selector]) + return _originalItem; + return nil; +} + +@end + +int main(int argc,char **argv) +{ + START_SET("GSFFIInvocation") + + NSString *string = @"Hello, World!"; + + GSFakeNSString *fakeString = [[GSFakeNSString alloc] initWithItem:string]; + + NSString *upperCaseString = [string uppercaseString]; + NSString *fakeUpperCaseString = [fakeString uppercaseString]; + + NSLog(@"Upper case string: %@, fake upper case string: %@", upperCaseString, fakeUpperCaseString); + PASS_EQUAL(upperCaseString, fakeUpperCaseString, "uppercaseString selector is forwarded from the fake string to the actual NSString object"); + + END_SET("GSFFIInvocation") + return 0; +}