/* * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im> * * All rights reserved. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3.0 only, * as published by the Free Software Foundation. * * This program 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 Lesser General Public License * version 3.0 for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3.0 along with this program. If not, see * <https://www.gnu.org/licenses/>. */ #include "config.h" #import "ObjFW.h" #import "ObjFWTest.h" static void *testKey = &testKey; @interface RuntimeTestClass: OFObject { OFString *_foo, *_bar; } @property (nonatomic, copy) OFString *foo; @property (retain) OFString *bar; - (id)nilSuperTest; @end @interface RuntimeTests: OTTestCase { RuntimeTestClass *_test; } @end @interface OFObject (SuperTest) - (id)superTest; @end @implementation RuntimeTests - (void)setUp { [super setUp]; _test = [[RuntimeTestClass alloc] init]; } - (void)dealloc { [_test release]; [super dealloc]; } - (void)testCallNonExistentMethodViaSuper { OTAssertThrowsSpecific([_test superTest], OFNotImplementedException); } - (void)testCallMethodViaSuperWithNilSelf { OTAssertNil([_test nilSuperTest]); } - (void)testPropertyCopyNonatomic { OFMutableString *string = [OFMutableString stringWithString: @"foo"]; OFString *foo = @"foo"; _test.foo = string; OTAssertEqualObjects(_test.foo, foo); OTAssertNotEqual(_test.foo, foo); OTAssertEqual(_test.foo.retainCount, 1); } - (void)testPropertyRetainAtomic { OFMutableString *string = [OFMutableString stringWithString: @"foo"]; _test.bar = string; OTAssertEqual(_test.bar, string); OTAssertEqual(string.retainCount, 3); } - (void)testAssociatedObjects { objc_setAssociatedObject(self, testKey, _test, OBJC_ASSOCIATION_ASSIGN); OTAssertEqual(_test.retainCount, 1); objc_setAssociatedObject(self, testKey, _test, OBJC_ASSOCIATION_RETAIN); OTAssertEqual(_test.retainCount, 2); OTAssertEqual(objc_getAssociatedObject(self, testKey), _test); OTAssertEqual(_test.retainCount, 3); objc_setAssociatedObject(self, testKey, _test, OBJC_ASSOCIATION_ASSIGN); OTAssertEqual(_test.retainCount, 2); objc_setAssociatedObject(self, testKey, _test, OBJC_ASSOCIATION_RETAIN_NONATOMIC); OTAssertEqual(_test.retainCount, 3); OTAssertEqual(objc_getAssociatedObject(self, testKey), _test); OTAssertEqual(_test.retainCount, 3); objc_removeAssociatedObjects(self); OTAssertEqual(_test.retainCount, 2); } #ifdef OF_OBJFW_RUNTIME - (void)testTaggedPointers { int classID; uintmax_t value; id object; if (sizeof(uintptr_t) == 8) value = 0xDEADBEEFDEADBEF; else if (sizeof(uintptr_t) == 4) value = 0xDEADBEF; else OTAssert(sizeof(uintptr_t) == 8 || sizeof(uintptr_t) == 4); OTAssertNotEqual(objc_registerTaggedPointerClass([OFString class]), -1); classID = objc_registerTaggedPointerClass([OFNumber class]); OTAssertNotEqual(classID, -1); object = objc_createTaggedPointer(classID, (uintptr_t)value); OTAssertNotNil(object); OTAssertEqual(object_getClass(object), [OFNumber class]); OTAssertEqual([object class], [OFNumber class]); OTAssertEqual(object_getTaggedPointerValue(object), value); OTAssertNotNil(objc_createTaggedPointer(classID, UINTPTR_MAX >> 4)); OTAssertNil(objc_createTaggedPointer(classID, (UINTPTR_MAX >> 4) + 1)); } #endif @end @implementation RuntimeTestClass @synthesize foo = _foo; @synthesize bar = _bar; - (void)dealloc { [_foo release]; [_bar release]; [super dealloc]; } - (id)superTest { return [super superTest]; } - (id)nilSuperTest { self = nil; return [self superTest]; } @end