// $Id: objc_test.m 2183 2008-02-07 16:24:08Z kimuraw $
//
// some tests require objc codes
#import <Foundation/Foundation.h>
@interface RBThreadTest : NSObject
{
}
@end
@interface NSObject (CallIP)
- (void)call;
@end
@implementation RBThreadTest
-(void)callWithAutoreleasePool:(id)closure {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[closure call];
[pool release];
}
-(NSException *)callWithExceptionTryCatch:(id)closure {
NSException *result = nil;
@try {
[closure call];
}
@catch (NSException * e) {
result = e;
}
return result;
}
@end
@interface RBExceptionTestBase : NSObject
{
}
@end
@implementation RBExceptionTestBase
-(NSException *)testExceptionRoundTrip
{
NSException *result = nil;
NS_DURING
// defined in test/tc_exception.rb
[self performSelector:@selector(testExceptionRaise)];
NS_HANDLER
result = localException;
NS_ENDHANDLER
return result;
}
@end
@interface Override : NSObject
{
}
@end
@implementation Override
+(int) foo
{
return 321;
}
-(int) foo
{
return 321;
}
- (NSRect) giveRect
{
return NSZeroRect;
}
+ (void)testFooOn:(id)instance
{
int i = [instance foo];
if (i != 123)
[NSException raise:@"TestOverride" format:@"assertion testFooOn failed, expected 123, got }
+ (void)testFooOnClassName:(NSString *)name
{
[self testFooOn:NSClassFromString(name)];
}
@end
@interface RetainCount : NSObject
{
}
@end
@implementation RetainCount
+(int) rbAllocCount
{
int retainCount;
id obj;
obj = [NSClassFromString(@"RBSubclass") alloc];
retainCount = [obj retainCount];
[obj release];
return retainCount;
}
+(id) ocObjectFromPlaceholder
{
return [[NSMutableString alloc] init];
}
+(int) rbInitCount
{
int retainCount;
id obj;
obj = [[NSClassFromString(@"RBSubclass") alloc] init];
retainCount = [obj retainCount];
[obj release];
return retainCount;
}
+(id) ocObject
{
return [[NSObject alloc] init];
}
+(id) rbObject
{
return [[NSClassFromString(@"RBSubclass") alloc] init];
}
+(int) rbNewCount
{
int retainCount;
id obj;
obj = [NSClassFromString(@"RBSubclass") new];
retainCount = [obj retainCount];
[obj release];
return retainCount;
}
+(id) rbNewObject
{
return [NSClassFromString(@"RBSubclass") new];
}
@end
// tc_uniqobj.rb
@interface UniqObjC : NSObject
@end
@implementation UniqObjC
- (void)start:(id)o
{
[o retain];
}
- (id)pass:(id)o
{
return o;
}
- (void)end:(id)o
{
[o release];
}
@end
// tc_passbyref.rb
@interface PassByRef : NSObject
@end
@implementation PassByRef
- (BOOL)passByRefObject:(id *)obj
{
if (obj != NULL) {
*obj = self;
return YES;
}
return NO;
}
- (BOOL)passByRefObjectWithTypeQualifiers:(inout id *)obj
{
if (obj != NULL) {
*obj = self;
return YES;
}
return NO;
}
- (BOOL)passByRefInteger:(int *)integer
{
if (integer != NULL) {
*integer = 666;
return YES;
}
return NO;
}
- (BOOL)passByRefFloat:(float *)floating
{
if (floating != NULL) {
*floating = 666.0;
return YES;
}
return NO;
}
- (void)passByRefVarious:(id *)object integer:(int *)integer floating:(float *)floating
{
if (object != NULL)
*object = self;
if (integer != NULL)
*integer = 666;
if (floating != NULL)
*floating = 666.0;
}
- (void)passByRefVariousTypeQualifiers:(in id *)object integer:(oneway int *)integer floating:(out float *)floating
{
if (object != NULL)
*object = self;
if (integer != NULL)
*integer = 333;
if (floating != NULL)
*floating = 333.0;
}
@end
// tc_subclass.rb
@interface __SkipInternalClass : NSData
@end
@implementation __SkipInternalClass {
}
@end
@interface SkipInternalClass : __SkipInternalClass
@end
@implementation SkipInternalClass {
}
@end
@interface CallerClass : NSObject
@end
@interface NSObject (TcSubclassFoo)
- (long)calledFoo:(id)arg;
@end
@implementation CallerClass
- (id)callFoo:(id)receiver
{
return (id)[receiver calledFoo:nil];
}
@end
@protocol Helper
- (char) testChar:(char) i;
- (int) testInt:(int) i;
- (short) testShort:(short) i;
- (long) testLong:(long) i;
- (float) testFloat:(float) f;
- (double) testDouble:(double) d;
- (long long)testLongLong:(long long)ll;
- (id)foo1;
- (int)foo2:(int)i;
- (void)foo3:(id)ary obj:(id)obj;
- (NSRect)foo4:(NSPoint)point size:(NSSize)size;
- (void)foo5:(NSRect *)rectPtr;
+ (int)superFoo;
@end
@interface TestRig : NSObject { }
- (void) run;
@end
@interface TestObjcExport : NSObject
@end
@implementation TestObjcExport
+ (void)runTests
{
Class helperClass = NSClassFromString(@"ObjcExportHelper");
id helper = [[helperClass alloc] init];
NSRect r;
int foo;
foo = [helperClass superFoo];
if (foo != 42)
[NSException raise:@"TestObjCExportError" format:@"assertion superFoo failed, expected 42, got
id s = [helper foo1];
if (![s isKindOfClass:[NSString class]] || ![s isEqualToString:@"s"])
[NSException raise:@"TestObjCExportError" format:@"assertion foo1 failed, expected
int i = [helper foo2:40];
if (i != 42)
[NSException raise:@"TestObjCExportError" format:@"assertion foo2 failed, expected
id ary = [NSMutableArray array];
id o = [[NSObject alloc] init];
[helper foo3:ary obj:o];
if ([ary count] != 1 || [ary objectAtIndex:0] != o)
[NSException raise:@"TestObjCExportError" format:@"assertion foo3 failed, object
foo = 42;
r = [helper foo4:NSMakePoint(1, 2) size:NSMakeSize(3, 4)];
if (r.origin.x != 1 || r.origin.y != 2 || r.size.width != 3 || r.size.height != 4)
[NSException raise:@"TestObjCExportError" format:@"assertion foo4 failed, expected if (foo != 42)
[NSException raise:@"TestObjCExportError" format:@"memory overflow"];
r = NSMakeRect(1,2,3,4);
[helper foo5:&r];
if (r.origin.x != 10 || r.origin.y != 20 || r.size.width != 30 || r.size.height != 40)
[NSException raise:@"TestObjCExportError" format:@"assertion foo5 failed, expected }
@end
@implementation TestRig
- (void) run
{
Class helperClass = NSClassFromString(@"RigHelper");
id helper = [[helperClass alloc] init];
id name = [helper name];
if (![name isKindOfClass:[NSString class]] || ![name isEqualToString:@"helper"])
[NSException raise:@"TestRigError" format:@"assertion name failed, expected
char c = [helper testChar:2];
if (c != 2)
[NSException raise:@"TestRigError" format:@"assertion testChar: failed, expected
int i = [helper testInt:2];
if (i != 2)
[NSException raise:@"TestRigError" format:@"assertion testInt: failed, expected
short s = [helper testShort:2];
if (s != 2)
[NSException raise:@"TestRigError" format:@"assertion testShort: failed, expected
long l = [helper testLong:2];
if (l != 2)
[NSException raise:@"TestRigError" format:@"assertion testLong: failed, expected
float f2 = 3.141592;
float f = [helper testFloat:f2];
if (f != f2)
[NSException raise:@"TestRigError" format:@"assertion testFloat: failed, expected
double d2 = 6666666.666;
double d = [helper testDouble:d2];
if (d != d2)
[NSException raise:@"TestRigError" format:@"assertion testDouble: failed, expected
long long ll2 = 1000000000;
long long ll = [helper testLongLong:ll2];
if (ll != ll2)
[NSException raise:@"TestRigError" format:@"assertion testLongLong: failed, expected }
@end
@interface TestRBObject : NSObject
@end
@implementation TestRBObject
- (long)addressOfObject:(id)obj
{
return (long)obj;
}
@end
@interface DirectOverride : NSObject
@end
@implementation DirectOverride
+ (id)classOverrideMe
{
return nil;
}
- (id)overrideMe
{
return nil;
}
+ (void)checkOverridenMethods
{
id obj;
obj = [DirectOverride classOverrideMe];
if (![obj isEqualToString:@"bar"])
[NSException raise:@"DirectOverride" format:@"assertion classOverrideMe failed, got
id directOverride = [[DirectOverride alloc] init];
obj = [directOverride overrideMe];
[directOverride release];
if (![obj isEqualToString:@"foo"])
[NSException raise:@"DirectOverride" format:@"assertion overrideMe failed, got }
@end
// This needs to be separate from DirectOverride since the test might damage
// this class.
@interface DirectOverrideParent : NSObject
@end
@implementation DirectOverrideParent
- (id)overrideMe
{
return @"foo";
}
- (void)checkOverride:(NSString *)want
{
id obj = [self overrideMe];
if (![obj isEqualToString:want])
[NSException raise:@"DirectOverrideInheritance"
format:@"assertion overrideMe failed, got }
@end
@interface DirectOverrideChild : DirectOverrideParent
@end
@implementation DirectOverrideChild
@end
#import <AddressBook/ABPeoplePickerC.h>
@interface TestFourCharCode : NSObject
@end
@implementation TestFourCharCode
+ (int)kEventClassABPeoplePickerValue
{
return kEventClassABPeoplePicker;
}
@end
@interface ObjcTestStret : NSObject
@end
@protocol StretHelper
- (NSRect)overrideMe:(int)x;
@end
@implementation ObjcTestStret
+ (void)run
{
Class helperClass = NSClassFromString(@"TestStret");
id helper = [[helperClass alloc] init];
NSRect rect;
int foo = 42;
rect = [helper overrideMe:50];
if (!NSEqualRects(rect, NSMakeRect(50, 50, 50, 50)))
[NSException raise:@"TestObjCExportError" format:@"assertion overrideMe failed, got if (foo != 42)
[NSException raise:@"TestObjCExportError" format:@"memory overflow"];
}
- (NSRect)overrideMe:(int)x
{
return NSZeroRect;
}
@end
@interface TestMagicCookie : NSObject
@end
@implementation TestMagicCookie
+ (BOOL)isKCFAllocatorUseContext:(id)ocid {
return ((unsigned long)ocid == (unsigned long)kCFAllocatorUseContext);
}
@end
@interface TestThreadedCallback : NSObject
@end
@interface NSObject (ThreadedInterface)
- (id)threaded;
- (void)done;
@end
static BOOL TestThreadedCallbackDone = NO;
@implementation TestThreadedCallback
+ (void)threadedCallback:(id)obj
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSNumber *number = [obj threaded];
//NSLog (@"got if (![number isKindOfClass:[NSNumber class]] || [number intValue] != 42)
[NSException raise:@"TestThreadedCallbackError" format:@"assertion threaded failed, expected a NSNumber with a 42 value, got [pool release];
TestThreadedCallbackDone = YES;
}
+ (void)callbackOnThreadRubyObject:(id)obj
{
TestThreadedCallbackDone = NO;
[NSThread detachNewThreadSelector:@selector(threadedCallback:) toTarget:self withObject:obj];
while (!TestThreadedCallbackDone && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.2]]) {}
}
@end
@interface HybridClass : NSObject
@end
@interface NSObject (HybridClassIf)
- (id)imethod;
+ (id)cmethod;
@end
@implementation HybridClass
+ (void)startTests
{
NSNumber *number;
HybridClass *hybrid;
number = [HybridClass cmethod];
if (![number isEqual:[NSNumber numberWithInt:42]])
[NSException raise:@"TestHybridClass" format:@"assertion cmethod failed, expected 42, got
hybrid = [[self alloc] init];
number = [hybrid imethod];
[hybrid release];
if (![number isEqual:[NSNumber numberWithInt:42]])
[NSException raise:@"TestHybridClass" format:@"assertion imethod failed, expected 42, got }
@end
@interface ObjcDataClass : NSObject
@end
@implementation ObjcDataClass
- (BOOL)boolNo { return NO; }
- (BOOL)boolYes { return YES; }
- (bool)cppBoolFalse { return false; }
- (bool)cppBoolTrue { return true; }
- (int)intZero { return 0; }
- (int)intOne { return 1; }
- (int)int42 { return 42; }
- (int)intMinusOne { return -1; }
- (unsigned int)biguint { return 2147483650UL; }
- (char)charZero { return (char)0; }
- (char)charOne { return (char)1; }
- (float)floatTwo { return 2.0f; }
- (double)doubleTwo { return 2.0; }
@end
@interface NSObject (TypeConversionTest)
- (BOOL)testBool;
- (char)testChar;
- (int)testInt;
- (float)testFloat;
- (double)testDouble;
@end
@interface ObjcConversionTest : NSObject
@end
@implementation ObjcConversionTest
- (NSString*)callbackTestBool:(id)target
{
BOOL b = [target testBool];
return [NSString stringWithFormat:@"}
- (NSString*)callbackTestChar:(id)target
{
char c = [target testChar];
return [NSString stringWithFormat:@"}
- (NSString*)callbackTestInt:(id)target
{
int i = [target testInt];
return [NSString stringWithFormat:@"}
- (NSString*)callbackTestFloat:(id)target
{
float f = [target testFloat];
return [NSString stringWithFormat:@"}
- (NSString*)callbackTestDouble:(id)target
{
double d = [target testDouble];
return [NSString stringWithFormat:@"}
@end
@interface NSObject (ObjcToRubyCacheTestUtility)
+ (BOOL)findInOcidToRbobjCache:(id)ocid;
- (void)callback:(id)obj;
@end
@interface ObjcToRubyCacheTest : NSObject
@end
@implementation ObjcToRubyCacheTest
+ (BOOL)testObjcToRubyCacheFor:(Class)klass with:(id)target
{
id obj = [[klass alloc] init];
[target callback:obj];
[obj release];
Class probe = [[NSBundle mainBundle] classNamed:@"RBCacheTestProbe"];
return [probe findInOcidToRbobjCache:obj];
}
@end
@interface OvmixArgRetained : NSObject
@end
@implementation OvmixArgRetained
+ (void)test:(id)obj
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSObject *o = [[[NSObject alloc] init] autorelease];
[obj performSelector:@selector(setObject:) withObject:o];
if ([obj performSelector:@selector(getObject)] != o)
[NSException raise:@"OvmixArgRetained" format:@"assertion1 failed"];
[pool release];
if ([obj performSelector:@selector(getObject)] != o)
[NSException raise:@"OvmixArgRetained" format:@"assertion2 failed"];
}
@end
@interface ObjcPtrTest : NSObject
@end
@implementation ObjcPtrTest
- (void*)returnVoidPtrForArrayOfString
{
NSString* str = [NSString stringWithUTF8String:"foobar"];
NSArray* ary = [NSArray arrayWithObject:str];
[ary retain];
return (void*)ary;
}
- (void*)returnVoidPtrForKCFBooleanTrue
{
return (void*)kCFBooleanTrue;
}
- (void*)returnVoidPtrForKCFBooleanFalse
{
return (void*)kCFBooleanFalse;
}
- (void*)returnVoidPtrForInt
{
static int i = -2147483648U;
return (void*)&i;
}
- (void*)returnVoidPtrForUInt
{
static unsigned int i = 4294967295U;
return (void*)&i;
}
- (void*)returnVoidPtrForCStr
{
static const char* str = "foobar";
return (void*)str;
}
@end
struct ttype1 {float a; float b;};
struct ttype2 {float a[2];};
@implementation NSObject (FooTests)
- (struct ttype1)test1 {
struct ttype1 r = {1., 2.};
return r;
}
- (struct ttype2)test2 {
struct ttype2 r;
r.a[0] = 1.;
r.a[1] = 2.;
return r;
}
@end
void Init_objc_test(){
// dummy initializer for ruby's `require'
}