/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, * 2018, 2019 * Jonathan Schleifer <js@heap.zone> * * 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 { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFObject *obj = [[[OFObject alloc] init] autorelease]; void *p, *q, *r; OFObject *o; MyObj *m; char *tmp; TEST(@"Allocating 4096 bytes", (p = [obj allocMemoryWithSize: 4096]) != NULL) TEST(@"Freeing memory", R([obj freeMemory: p])) TEST(@"Allocating and freeing 4096 bytes 3 times", (p = [obj allocMemoryWithSize: 4096]) != NULL && (q = [obj allocMemoryWithSize: 4096]) != NULL && (r = [obj allocMemoryWithSize: 4096]) != NULL && R([obj freeMemory: p]) && R([obj freeMemory: q]) && R([obj freeMemory: r])) tmp = [self allocMemoryWithSize: 1024]; EXPECT_EXCEPTION(@"Detect freeing of memory not allocated by object", OFMemoryNotPartOfObjectException, [obj freeMemory: tmp]) EXPECT_EXCEPTION(@"Detect out of memory on alloc", OFOutOfMemoryException, tmp = [obj allocMemoryWithSize: TOO_BIG]) EXPECT_EXCEPTION(@"Detect out of memory on resize", OFOutOfMemoryException, { p = [obj allocMemoryWithSize: 1]; p = [obj resizeMemory: p size: TOO_BIG]; }) [obj freeMemory: p]; TEST(@"Allocate when trying to resize NULL", (p = [obj resizeMemory: NULL size: 1024]) != NULL) [obj freeMemory: p]; EXPECT_EXCEPTION(@"Detect resizing of memory not allocated by object", OFMemoryNotPartOfObjectException, tmp = [obj resizeMemory: tmp size: 2048]) [self freeMemory: tmp]; 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 setObjectValue: @"Hello"]; [m setClassValue: [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 setBoolValue: 1]; [m setCharValue: 2]; [m setShortValue: 3]; [m setIntValue: 4]; [m setLongValue: 5 ]; [m setLongLongValue: 6]; [m setUnsignedCharValue: 7]; [m setUnsignedShortValue: 8]; [m setUnsignedIntValue: 9]; [m setUnsignedLongValue: 10]; [m setUnsignedLongLongValue: 11]; [m setFloatValue: 12]; [m setDoubleValue: 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"]) [pool drain]; } @end