/** nsmethodsignature - Program to test NSMethodSignature. Copyright (C) 2004 Free Software Foundation, Inc. Written by: David Ayers This file is part of the GNUstep Base Library. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. */ #include #include #include #include #include #include #include #define SRV_NAME @"nsmethodsignaturetest" struct _MyLargeStruct { double first; double second; }; typedef struct _MyLargeStruct MyLargeStruct; struct _MySmallStruct { char first; }; typedef struct _MySmallStruct MySmallStruct; /*------------------------------------*/ @interface MyClass : NSObject -(void)void_void; -(id)id_void; -(char)char_void; -(unsigned char)uchar_void; -(signed char)schar_void; -(short)short_void; -(unsigned short)ushort_void; -(signed short)sshort_void; -(int)int_void; -(unsigned int)uint_void; -(signed int)sint_void; -(long)long_void; -(unsigned long)ulong_void; -(signed long)slong_void; -(float)float_void; -(double)double_void; -(MyLargeStruct)largeStruct_void; -(MySmallStruct)smallStruct_void; -(void)void_id:(id)_id; -(void)void_char:(char)_char; -(void)void_uchar:(unsigned char)_char; -(void)void_schar:(signed char)_char; -(void)void_short:(short)_short; -(void)void_ushort:(unsigned short)_short; -(void)void_sshort:(signed short)_short; -(void)void_int:(int)_int; -(void)void_uint:(unsigned int)_int; -(void)void_sint:(signed int)_int; -(void)void_long:(long)_long; -(void)void_ulong:(unsigned long)_long; -(void)void_slong:(signed long)_long; -(void)void_float:(float)_float; -(void)void_double:(double)_double; -(void)void_largeStruct:(MyLargeStruct)_str; -(void)void_smallStruct:(MySmallStruct)_str; -(void)void_float:(float)_float double:(double)_double; -(void)void_double:(double)_double float:(float)_float; -(MyLargeStruct)largeStruct_id:(id)_id char:(char)_char short:(short)_short int:(int)_int long:(long)_long float:(float)_float double:(double)_double largeStruct:(MyLargeStruct)_lstr smallStruct:(MySmallStruct)_sstr; -(MySmallStruct)smallStruct_id:(id)_id uchar:(unsigned char)_uchar ushort:(unsigned short)_ushort uint:(unsigned int)_uint ulong:(unsigned long)_ulong float:(float)_float double:(double)_double largeStruct:(MyLargeStruct)_lstr smallStruct:(MySmallStruct)_sstr; -(const char *)runtimeSignatureForSelector:(SEL)selector; -(const char *)mframeSignatureForSelector:(SEL)selector; @end @implementation MyClass -(void)void_void {} -(id)id_void { return 0; } -(char)char_void { return 0; } -(unsigned char)uchar_void { return 0; } -(signed char)schar_void { return 0; } -(short)short_void { return 0; } -(unsigned short)ushort_void { return 0; } -(signed short)sshort_void { return 0; } -(int)int_void { return 0; } -(unsigned int)uint_void { return 0; } -(signed int)sint_void { return 0; } -(long)long_void { return 0; } -(unsigned long)ulong_void { return 0; } -(signed long)slong_void { return 0; } -(float)float_void { return 0; } -(double)double_void { return 0; } -(MyLargeStruct)largeStruct_void { MyLargeStruct str; return str; } -(MySmallStruct)smallStruct_void { MySmallStruct str; return str; } -(void)void_id:(id)_id {} -(void)void_char:(char)_char {} -(void)void_uchar:(unsigned char)_char {} -(void)void_schar:(signed char)_char {} -(void)void_short:(short)_short {} -(void)void_ushort:(unsigned short)_short {} -(void)void_sshort:(signed short)_short {} -(void)void_int:(int)_int {} -(void)void_uint:(unsigned int)_int {} -(void)void_sint:(signed int)_int {} -(void)void_long:(long)_long {} -(void)void_ulong:(unsigned long)_long {} -(void)void_slong:(signed long)_long {} -(void)void_float:(float)_float {} -(void)void_double:(double)_double {} -(void)void_largeStruct:(MyLargeStruct)_str {} -(void)void_smallStruct:(MySmallStruct)_str {} -(void)void_float:(float)_float double:(double)_double {} -(void)void_double:(double)_double float:(float)_float {} -(MyLargeStruct)largeStruct_id:(id)_id char:(char)_char short:(short)_short int:(int)_int long:(long)_long float:(float)_float double:(double)_double largeStruct:(MyLargeStruct)_lstr smallStruct:(MySmallStruct)_sstr { return _lstr; } -(MySmallStruct)smallStruct_id:(id)_id uchar:(unsigned char)_uchar ushort:(unsigned short)_ushort uint:(unsigned int)_uint ulong:(unsigned long)_ulong float:(float)_float double:(double)_double largeStruct:(MyLargeStruct)_lstr smallStruct:(MySmallStruct)_sstr { return _sstr; } -(const char *)runtimeSignatureForSelector:(SEL)selector { GSMethod meth = GSGetMethod(isa, selector, YES, YES); return meth->method_types; } -(const char *)mframeSignatureForSelector:(SEL)selector { const char *types = [self runtimeSignatureForSelector: selector]; NSMethodSignature *sig = [NSMethodSignature signatureWithObjCTypes: types]; return [sig methodType]; } @end /*------------------------------------*/ int failed = 0; void test_mframe_build_signature(void) { const char *mf_types; void *it = 0; GSMethod meth; GSMethodList list; Class cls = [MyClass class]; NSMethodSignature *sig; unsigned int i; for (it = 0, list = class_nextMethodList(cls, &it); list != 0; list = class_nextMethodList(cls, &it)) { id pool = [NSAutoreleasePool new]; for (i = 0; i < list->method_count; i++) { meth = &list->method_list[i]; sig = [NSMethodSignature signatureWithObjCTypes: meth->method_types]; mf_types = [sig methodType]; if (strcmp(meth->method_types, mf_types)) { NSLog(@"sel: %s\nrts:%s\nmfs:%s", GSNameFromSelector(meth->method_name), meth->method_types, mf_types); failed = 1; } } [pool release]; } } /* This test is useful if the nsmethodsignatureserver is running which was compiled with either a different GNUstep-base version or a different version of gcc. It the server isn't found the test is skipped. */ void test_compare_server_signature(void) { id objct = [MyClass new]; id proxy = [NSConnection rootProxyForConnectionWithRegisteredName: SRV_NAME host: nil]; if (proxy) { const char *rmtSig; const char *lclSig; #define TEST_SEL(SELNAME) { \ lclSig = [objct runtimeSignatureForSelector: @selector(SELNAME)]; \ rmtSig = [proxy runtimeSignatureForSelector: @selector(SELNAME)]; \ if (!GSSelectorTypesMatch(lclSig, rmtSig)) \ NSLog(@"runtime: sel:%s\nlcl:%s\nrmt:%s", \ GSNameFromSelector(@selector(SELNAME)), \ lclSig, rmtSig); \ lclSig = [objct mframeSignatureForSelector: @selector(SELNAME)]; \ rmtSig = [proxy mframeSignatureForSelector: @selector(SELNAME)]; \ if (!GSSelectorTypesMatch(lclSig, rmtSig)) \ NSLog(@"mframe : sel:%s\nlcl:%s\nrmt:%s", \ GSNameFromSelector(@selector(SELNAME)), \ lclSig, rmtSig); \ } TEST_SEL(void_void); TEST_SEL(id_void); TEST_SEL(char_void); TEST_SEL(uchar_void); TEST_SEL(schar_void); TEST_SEL(short_void); TEST_SEL(ushort_void); TEST_SEL(sshort_void); TEST_SEL(int_void); TEST_SEL(uint_void); TEST_SEL(sint_void); TEST_SEL(long_void); TEST_SEL(ulong_void); TEST_SEL(slong_void); TEST_SEL(float_void); TEST_SEL(double_void); TEST_SEL(largeStruct_void); TEST_SEL(smallStruct_void); TEST_SEL(void_id:); TEST_SEL(void_char:); TEST_SEL(void_uchar:); TEST_SEL(void_schar:); TEST_SEL(void_short:); TEST_SEL(void_ushort:); TEST_SEL(void_sshort:); TEST_SEL(void_int:); TEST_SEL(void_uint:); TEST_SEL(void_sint:); TEST_SEL(void_long:); TEST_SEL(void_ulong:); TEST_SEL(void_slong:); TEST_SEL(void_float:); TEST_SEL(void_double:); TEST_SEL(void_largeStruct:); TEST_SEL(void_smallStruct:); TEST_SEL(void_float:double:); TEST_SEL(void_double:float:); TEST_SEL(largeStruct_id:char:short:int:long:float:double:largeStruct:smallStruct:); TEST_SEL(smallStruct_id:uchar:ushort:uint:ulong:float:double:largeStruct:smallStruct:); } else { NSLog(@"Skipping test_compare_server_signature: proxy not found."); } } void test_GSSelectorTypesMatch(void) { const char *pairs[][2] = { {"@@::", "@12@0:4:8"}, {"@@::", "@12@+0:+4:+8"}, {"@@::", "@12@-0:-4:-8"}, {"@12@0:4:8", "@@::"}, {"@12@+0:+4:+8", "@@::"}, {"@12@-0:-4:-8", "@@::"}, {"@12@0:4:8", "@12@+0:+4:+8"}, {"@12@0:4:8", "@12@-0:-4:-8"}, {"@12@+0:+4:+8", "@12@0:4:8"}, {"@12@-0:-4:-8", "@12@0:4:8"}, {"@12@0:4:8", "@16@+4:+8:+12"}, {"@12@0:4:8", "@16@-4:-8:-12"}, {"@12@+0:+4:+8", "@16@4:8:12"}, {"@12@-0:-4:-8", "@16@4:8:12"}, {"{_MyLargeStruct2={_MyLargeStruct=dd}dd}@:", "{??={??=dd}dd}16@0:4"}, {"{_MyLargeStruct=dd}56@+8:+12@+16c+23s+26i+28l24f28d32{_MyLargeStruct=dd}40{_MySmallStruct=c}44", "{_MyLargeStruct=dd}46@+8:+12@+16c+17s+16i+20l+24f+28d24{_MyLargeStruct=dd}32{_MySmallStruct=c}45"}, {"{_MyLargeStruct=dd}56@+8:+12@+16c+23s+26i+28l24f28d32{_MyLargeStruct=dd}40{_MySmallStruct=c}44", "{??=dd}46@+8:+12@+16c+17s+16i+20l+24f+28d24{??=dd}32{??=c}45"}, {0, 0} }; unsigned int i = 0; while (pairs[i][0]) { if (GSSelectorTypesMatch(pairs[i][0], pairs[i][1]) == NO) { NSLog(@"pair %d does not match:\n%s\n%s", i, pairs[i][0], pairs[i][1]); failed = 1; } i++; } } void run_server(void) { id obj = [MyClass new]; NSConnection *conn = [NSConnection defaultConnection]; [conn setRootObject: obj]; if ([conn registerName: SRV_NAME] == NO) { NSLog(@"Failed to register name: " SRV_NAME ); abort(); } [[NSRunLoop currentRunLoop] run]; } int main(int argc, char *argv[]) { NSAutoreleasePool *pool; pool = [[NSAutoreleasePool alloc] init]; if ([[[[NSProcessInfo processInfo] arguments] lastObject] isEqual: @"srv"]) { run_server(); abort(); } NS_DURING { test_mframe_build_signature(); test_compare_server_signature(); test_GSSelectorTypesMatch(); if (failed) [NSException raise: NSInternalInconsistencyException format: @"discrepancies between gcc/mframe signatures"]; NSLog(@"MethodSignature Test Succeeded."); } NS_HANDLER { NSLog(@"MethodSignature Test Failed:"); NSLog(@"%@ %@ %@", [localException name], [localException reason], [localException userInfo]); } NS_ENDHANDLER [pool release]; exit(0); }