/* * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #import "TestsAppDelegate.h" #if (defined(OF_DRAGONFLYBSD) && defined(__LP64__)) || defined(OF_NINTENDO_3DS) # define TOO_BIG (SIZE_MAX / 3) #else # define TOO_BIG (SIZE_MAX - 128) #endif static OFString *module = @"OFObject"; @interface MyObj: OFObject { id _objectValue; Class _classValue; bool _boolValue; char _charValue; short _shortValue; int _intValue; long _longValue; long long _longLongValue; unsigned char _unsignedCharValue; unsigned short _unsignedShortValue; unsigned int _unsignedIntValue; unsigned long _unsignedLongValue; unsigned long long _unsignedLongLongValue; float _floatValue; double _doubleValue; } @property (nonatomic, retain) id objectValue; @property (nonatomic) Class classValue; @property (nonatomic, getter=isBoolValue) bool boolValue; @property (nonatomic) char charValue; @property (nonatomic) short shortValue; @property (nonatomic) int intValue; @property (nonatomic) long longValue; @property (nonatomic) long long longLongValue; @property (nonatomic) unsigned char unsignedCharValue; @property (nonatomic) unsigned short unsignedShortValue; @property (nonatomic) unsigned int unsignedIntValue; @property (nonatomic) unsigned long unsignedLongValue; @property (nonatomic) unsigned long long unsignedLongLongValue; @property (nonatomic) float floatValue; @property (nonatomic) double doubleValue; @end @implementation MyObj @synthesize objectValue = _objectValue, classValue = _classValue; @synthesize boolValue = _boolValue, charValue = _charValue; @synthesize shortValue = _shortValue, intValue = _intValue; @synthesize longValue = _longValue, longLongValue = _longLongValue; @synthesize unsignedCharValue = _unsignedCharValue; @synthesize unsignedShortValue = _unsignedShortValue; @synthesize unsignedIntValue = _unsignedIntValue; @synthesize unsignedLongValue = _unsignedLongValue; @synthesize unsignedLongLongValue = _unsignedLongLongValue; @synthesize floatValue = _floatValue, doubleValue = _doubleValue; - (void)dealloc { [_objectValue release]; [super dealloc]; } @end @implementation TestsAppDelegate (OFObjectTests) - (void)objectTests { void *pool = objc_autoreleasePoolPush(); OFObject *o; MyObj *m; TEST(@"+[description]", [[OFObject description] isEqual: @"OFObject"] && [[MyObj description] isEqual: @"MyObj"]) o = [[[OFObject alloc] init] autorelease]; m = [[[MyObj alloc] init] autorelease]; TEST(@"-[description]", [o.description isEqual: @"<OFObject>"] && [m.description isEqual: @"<MyObj>"]) m.objectValue = @"Hello"; m.classValue = [m class]; TEST(@"-[valueForKey:]", [[m valueForKey: @"objectValue"] isEqual: @"Hello"] && [[m valueForKey: @"classValue"] isEqual: m.class] && [[m valueForKey: @"class"] isEqual: m.class]) EXPECT_EXCEPTION(@"-[valueForKey:] with undefined key", OFUndefinedKeyException, [m valueForKey: @"undefined"]) TEST(@"-[setValue:forKey:]", R([m setValue: @"World" forKey: @"objectValue"]) && R([m setValue: [OFObject class] forKey: @"classValue"]) && [m.objectValue isEqual: @"World"] && [m.classValue isEqual: [OFObject class]]) EXPECT_EXCEPTION(@"-[setValue:forKey:] with undefined key", OFUndefinedKeyException, [m setValue: @"x" forKey: @"undefined"]) m.boolValue = 1; m.charValue = 2; m.shortValue = 3; m.intValue = 4; m.longValue = 5; m.longLongValue = 6; m.unsignedCharValue = 7; m.unsignedShortValue = 8; m.unsignedIntValue = 9; m.unsignedLongValue = 10; m.unsignedLongLongValue = 11; m.floatValue = 12; m.doubleValue = 13; TEST(@"Auto-wrapping of -[valueForKey:]", [[m valueForKey: @"boolValue"] isEqual: [OFNumber numberWithBool: 1]] && [[m valueForKey: @"charValue"] isEqual: [OFNumber numberWithChar: 2]] && [[m valueForKey: @"shortValue"] isEqual: [OFNumber numberWithShort: 3]] && [[m valueForKey: @"intValue"] isEqual: [OFNumber numberWithInt: 4]] && [[m valueForKey: @"longValue"] isEqual: [OFNumber numberWithLong: 5]] && [[m valueForKey: @"longLongValue"] isEqual: [OFNumber numberWithLongLong: 6]] && [[m valueForKey: @"unsignedCharValue"] isEqual: [OFNumber numberWithUnsignedChar: 7]] && [[m valueForKey: @"unsignedShortValue"] isEqual: [OFNumber numberWithUnsignedShort: 8]] && [[m valueForKey: @"unsignedIntValue"] isEqual: [OFNumber numberWithUnsignedInt: 9]] && [[m valueForKey: @"unsignedLongValue"] isEqual: [OFNumber numberWithUnsignedLong: 10]] && [[m valueForKey: @"unsignedLongLongValue"] isEqual: [OFNumber numberWithUnsignedLongLong: 11]] && [[m valueForKey: @"floatValue"] isEqual: [OFNumber numberWithFloat: 12]] && [[m valueForKey: @"doubleValue"] isEqual: [OFNumber numberWithDouble: 13]]) TEST(@"Auto-wrapping of -[setValue:forKey:]", R([m setValue: [OFNumber numberWithBool: 0] forKey: @"boolValue"]) && R([m setValue: [OFNumber numberWithChar: 10] forKey: @"charValue"]) && R([m setValue: [OFNumber numberWithShort: 20] forKey: @"shortValue"]) && R([m setValue: [OFNumber numberWithInt: 30] forKey: @"intValue"]) && R([m setValue: [OFNumber numberWithLong: 40] forKey: @"longValue"]) && R([m setValue: [OFNumber numberWithLongLong: 50] forKey: @"longLongValue"]) && R([m setValue: [OFNumber numberWithUnsignedChar: 60] forKey: @"unsignedCharValue"]) && R([m setValue: [OFNumber numberWithUnsignedShort: 70] forKey: @"unsignedShortValue"]) && R([m setValue: [OFNumber numberWithUnsignedInt: 80] forKey: @"unsignedIntValue"]) && R([m setValue: [OFNumber numberWithUnsignedLong: 90] forKey: @"unsignedLongValue"]) && R([m setValue: [OFNumber numberWithUnsignedLongLong: 100] forKey: @"unsignedLongLongValue"]) && R([m setValue: [OFNumber numberWithFloat: 110] forKey: @"floatValue"]) && R([m setValue: [OFNumber numberWithDouble: 120] forKey: @"doubleValue"]) && m.isBoolValue == 0 && m.charValue == 10 && m.shortValue == 20 && m.intValue == 30 && m.longValue == 40 && m.longLongValue == 50 && m.unsignedCharValue == 60 && m.unsignedShortValue == 70 && m.unsignedIntValue == 80 && m.unsignedLongValue == 90 && m.unsignedLongLongValue == 100 && m.floatValue == 110 && m.doubleValue == 120) EXPECT_EXCEPTION(@"Catch -[setValue:forKey:] with nil key for scalar", OFInvalidArgumentException, [m setValue: (id _Nonnull)nil forKey: @"intValue"]) TEST(@"-[valueForKeyPath:]", (m = [[[MyObj alloc] init] autorelease]) && (m.objectValue = [[[MyObj alloc] init] autorelease]) && R([m.objectValue setObjectValue: [[[MyObj alloc] init] autorelease]]) && R([[m.objectValue objectValue] setDoubleValue: 0.5]) && [[m valueForKeyPath: @"objectValue.objectValue.doubleValue"] doubleValue] == 0.5) TEST(@"[-setValue:forKeyPath:]", R([m setValue: [OFNumber numberWithDouble: 0.75] forKeyPath: @"objectValue.objectValue.doubleValue"]) && [[m.objectValue objectValue] doubleValue] == 0.75) objc_autoreleasePoolPop(pool); } @end