Index: .fossil-settings/clean-glob
==================================================================
--- .fossil-settings/clean-glob
+++ .fossil-settings/clean-glob
@@ -30,11 +30,14 @@
src/bridge/Info.plist
src/libobjfw.*
src/objfw-defs.h
src/runtime/Info.plist
src/runtime/libobjfwrt.*
+src/test/Info.plist
+src/test/libobjfwtest.*
src/tls/Info.plist
+src/tls/libobjfwtls.*
tests/DerivedData
tests/EBOOT.PBP
tests/Info.plist
tests/PARAM.SFO
tests/objc_sync/objc_sync
Index: .fossil-settings/ignore-glob
==================================================================
--- .fossil-settings/ignore-glob
+++ .fossil-settings/ignore-glob
@@ -32,11 +32,14 @@
src/bridge/Info.plist
src/libobjfw.*
src/objfw-defs.h
src/runtime/Info.plist
src/runtime/libobjfwrt.*
+src/test/Info.plist
+src/test/libobjfwtest.*
src/tls/Info.plist
+src/tls/libobjfwtls.*
tests/DerivedData
tests/EBOOT.PBP
tests/Info.plist
tests/PARAM.SFO
tests/iOS.xcodeproj/*.pbxuser
Index: .gitignore
==================================================================
--- .gitignore
+++ .gitignore
@@ -32,11 +32,14 @@
src/bridge/Info.plist
src/libobjfw.*
src/objfw-defs.h
src/runtime/Info.plist
src/runtime/libobjfwrt.*
+src/test/Info.plist
+src/test/libobjfwtest.*
src/tls/Info.plist
+src/tls/libobjfwtls.*
tests/DerivedData
tests/EBOOT.PBP
tests/Info.plist
tests/PARAM.SFO
tests/iOS.xcodeproj/*.pbxuser
Index: configure.ac
==================================================================
--- configure.ac
+++ configure.ac
@@ -400,16 +400,18 @@
AS_IF([test x"$enable_shared" != x"no"], [
BUILDSYS_SHARED_LIB
BUILDSYS_PLUGIN
AC_SUBST(OBJFW_SHARED_LIB, '${LIB_PREFIX}objfw${LIB_SUFFIX}')
+ AC_SUBST(OBJFWTEST_SHARED_LIB, '${LIB_PREFIX}objfwtest${LIB_SUFFIX}')
AC_SUBST(EXCEPTIONS_LIB_A, "exceptions.lib.a")
AC_SUBST(FORWARDING_LIB_A, "forwarding.lib.a")
AC_SUBST(LOOKUP_ASM_LIB_A, "lookup-asm.lib.a")
BUILDSYS_FRAMEWORK([
AC_SUBST(OBJFW_FRAMEWORK, "ObjFW.framework")
+ AC_SUBST(OBJFWTEST_FRAMEWORK, "ObjFWTest.framework")
build_framework="yes"
])
], [
AC_DEFINE(OF_NO_SHARED, 1, [Whether no shared library was built])
AC_SUBST(LIBOBJFW_DEP, "../src/libobjfw.a")
@@ -429,10 +431,11 @@
AS_IF([test x"$enable_shared" = x"no"], [
enable_static="yes"
])
AS_IF([test x"$enable_static" = x"yes"], [
AC_SUBST(OBJFW_STATIC_LIB, "libobjfw.a")
+ AC_SUBST(OBJFWTEST_STATIC_LIB, "libobjfwtest.a")
AC_SUBST(EXCEPTIONS_A, "exceptions.a")
AC_SUBST(FORWARDING_A, "forwarding.a")
AC_SUBST(LOOKUP_ASM_A, "lookup-asm.a")
])
@@ -2374,10 +2377,11 @@
AC_CONFIG_FILES([
buildsys.mk
extra.mk
src/Info.plist
+ src/test/Info.plist
tests/Info.plist
utils/objfw-config
])
AC_CONFIG_HEADERS([config.h src/objfw-defs.h])
AC_OUTPUT
Index: extra.mk.in
==================================================================
--- extra.mk.in
+++ extra.mk.in
@@ -25,10 +25,17 @@
OBJFWTLS_STATIC_LIB = @OBJFWTLS_STATIC_LIB@
OBJFWTLS_FRAMEWORK = @OBJFWTLS_FRAMEWORK@
OBJFWTLS_LIB_MAJOR = 1
OBJFWTLS_LIB_MINOR = 0
OBJFWTLS_LIB_PATCH = 2
+
+OBJFWTEST_SHARED_LIB = @OBJFWTEST_SHARED_LIB@
+OBJFWTEST_STATIC_LIB = @OBJFWTEST_STATIC_LIB@
+OBJFWTEST_FRAMEWORK = @OBJFWTEST_FRAMEWORK@
+OBJFWTEST_LIB_MAJOR = 1
+OBJFWTEST_LIB_MINOR = 0
+OBJFWTEST_LIB_PATCH = 0
BIN_PREFIX = @BIN_PREFIX@
BRIDGE = @BRIDGE@
CVINCLUDE_INLINE_H = @CVINCLUDE_INLINE_H@
ENCODINGS_A = @ENCODINGS_A@
Index: src/Makefile
==================================================================
--- src/Makefile
+++ src/Makefile
@@ -1,9 +1,9 @@
include ../extra.mk
SUBDIRS = ${RUNTIME} exceptions encodings forwarding
-SUBDIRS_AFTER = ${BRIDGE} ${TLS}
+SUBDIRS_AFTER = ${BRIDGE} ${TLS} test
DISTCLEAN = Info.plist objfw-defs.h
SHARED_LIB = ${OBJFW_SHARED_LIB}
STATIC_LIB = ${OBJFW_STATIC_LIB}
FRAMEWORK = ${OBJFW_FRAMEWORK}
ADDED src/test/Info.plist.in
Index: src/test/Info.plist.in
==================================================================
--- src/test/Info.plist.in
+++ src/test/Info.plist.in
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleExecutable
+ ObjFWTest
+ CFBundleName
+ ObjFWTest
+ CFBundleIdentifier
+ im.nil.objfw.test
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ FMWK
+ CFBundleVersion
+ @BUNDLE_VERSION@
+ CFBundleShortVersionString
+ @BUNDLE_SHORT_VERSION@
+ MinimumOSVersion
+ 9.0
+
+
ADDED src/test/Makefile
Index: src/test/Makefile
==================================================================
--- src/test/Makefile
+++ src/test/Makefile
@@ -0,0 +1,49 @@
+include ../../extra.mk
+
+DISTCLEAN = Info.plist
+
+SHARED_LIB = ${OBJFWTEST_SHARED_LIB}
+STATIC_LIB = ${OBJFWTEST_STATIC_LIB}
+FRAMEWORK = ${OBJFWTEST_FRAMEWORK}
+LIB_MAJOR = ${OBJFWTEST_LIB_MAJOR}
+LIB_MINOR = ${OBJFWTEST_LIB_MINOR}
+LIB_PATCH = ${OBJFWTEST_LIB_PATCH}
+
+SRCS = OTTestCase.m
+INCLUDES := ${SRCS:.m=.h} \
+ ObjFWTest.h
+SRCS += OTAppDelegate.m
+
+includesubdir = ObjFWTest
+
+include ../../buildsys.mk
+
+CPPFLAGS += -I. \
+ -I.. \
+ -I../.. \
+ -I../exceptions \
+ -I../runtime \
+ -DOBJFWTEST_LOCAL_INCLUDES
+LD = ${OBJC}
+FRAMEWORK_LIBS := -F.. -framework ObjFW ${LIBS}
+LIBS := -L.. -lobjfw -L../runtime ${RUNTIME_LIBS} ${LIBS}
+
+install-extra:
+ i=ObjFWTest.oc; \
+ ${INSTALL_STATUS}; \
+ if ${MKDIR_P} ${libdir}/objfw-config && ${INSTALL} -m 644 $$i ${libdir}/objfw-config/$$i; then \
+ ${INSTALL_OK}; \
+ else \
+ ${INSTALL_FAILED}; \
+ fi
+
+uninstall-extra:
+ i=ObjFWTest.oc; \
+ if test -f ${libdir}/objfw-config/$$i; then \
+ if rm -f ${libdir}/objfw-config/$$i; then \
+ ${DELETE_OK}; \
+ else \
+ ${DELETE_FAILED}; \
+ fi \
+ fi; \
+ rmdir ${libdir}/objfw-config >/dev/null 2>&1 || true
ADDED src/test/OTAppDelegate.h
Index: src/test/OTAppDelegate.h
==================================================================
--- src/test/OTAppDelegate.h
+++ src/test/OTAppDelegate.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2008-2024 Jonathan Schleifer
+ *
+ * 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.
+ */
+
+#import "OFApplication.h"
+
+OF_ASSUME_NONNULL_BEGIN
+
+@interface OTAppDelegate: OFObject
+@end
+
+OF_ASSUME_NONNULL_END
ADDED src/test/OTAppDelegate.m
Index: src/test/OTAppDelegate.m
==================================================================
--- src/test/OTAppDelegate.m
+++ src/test/OTAppDelegate.m
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2008-2024 Jonathan Schleifer
+ *
+ * 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 "OTAppDelegate.h"
+
+#import "OFSet.h"
+#import "OFValue.h"
+
+#import "OTTestCase.h"
+
+OF_APPLICATION_DELEGATE(OTAppDelegate)
+
+@implementation OTAppDelegate
+- (OFSet OF_GENERIC(Class) *)testClasses
+{
+ Class *classes = objc_copyClassList(NULL);
+ OFMutableSet *testClasses;
+
+ if (classes == NULL)
+ return nil;
+
+ @try {
+ testClasses = [OFMutableSet set];
+
+ for (Class *iter = classes; *iter != Nil; iter++)
+ if ([*iter isSubclassOfClass: [OTTestCase class]])
+ [testClasses addObject: *iter];
+ } @finally {
+ OFFreeMemory(classes);
+ }
+
+ [testClasses removeObject: [OTTestCase class]];
+
+ [testClasses makeImmutable];
+ return testClasses;
+}
+
+- (OFSet OF_GENERIC(OFValue *) *)testsInClass: (Class)class
+{
+ Method *methods = class_copyMethodList(class, NULL);
+ OFMutableSet *tests;
+
+ if (methods == NULL)
+ return nil;
+
+ @try {
+ tests = [OFMutableSet set];
+
+ for (Method *iter = methods; *iter != NULL; iter++) {
+ SEL selector = method_getName(*iter);
+
+ if (selector == NULL)
+ continue;
+
+ if (strncmp(sel_getName(selector), "test", 4) == 0)
+ [tests addObject:
+ [OFValue valueWithPointer: selector]];
+ }
+ } @finally {
+ OFFreeMemory(methods);
+ }
+
+ [tests makeImmutable];
+ return tests;
+}
+
+- (void)applicationDidFinishLaunching: (OFNotification *)notification
+{
+ OFSet OF_GENERIC(Class) *testClasses = [self testClasses];
+
+ for (Class class in testClasses) {
+ for (OFValue *test in [self testsInClass: class]) {
+ void *pool = objc_autoreleasePoolPush();
+ OTTestCase *instance =
+ [[[class alloc] init] autorelease];
+
+ [instance setUp];
+ [instance performSelector: test.pointerValue];
+ [instance tearDown];
+
+ objc_autoreleasePoolPop(pool);
+ }
+ }
+
+ [OFApplication terminate];
+}
+@end
ADDED src/test/OTTestCase.h
Index: src/test/OTTestCase.h
==================================================================
--- src/test/OTTestCase.h
+++ src/test/OTTestCase.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2008-2024 Jonathan Schleifer
+ *
+ * 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.
+ */
+
+#ifdef OBJFWTEST_LOCAL_INCLUDES
+# import "OFObject.h"
+#else
+# import
+#endif
+
+OF_ASSUME_NONNULL_BEGIN
+
+/**
+ * @class OTTestCase OTTestCase.h ObjFWTest/OTTestCase.h
+ */
+@interface OTTestCase: OFObject
+- (void)setUp;
+- (void)tearDown;
+@end
+
+OF_ASSUME_NONNULL_END
ADDED src/test/OTTestCase.m
Index: src/test/OTTestCase.m
==================================================================
--- src/test/OTTestCase.m
+++ src/test/OTTestCase.m
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2008-2024 Jonathan Schleifer
+ *
+ * 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 "OTTestCase.h"
+
+@implementation OTTestCase: OFObject
+- (void)setUp
+{
+}
+
+- (void)tearDown
+{
+}
+@end
ADDED src/test/ObjFWTest.h
Index: src/test/ObjFWTest.h
==================================================================
--- src/test/ObjFWTest.h
+++ src/test/ObjFWTest.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2008-2024 Jonathan Schleifer
+ *
+ * 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.
+ */
+
+#import "OTTestCase.h"
ADDED src/test/ObjFWTest.oc
Index: src/test/ObjFWTest.oc
==================================================================
--- src/test/ObjFWTest.oc
+++ src/test/ObjFWTest.oc
@@ -0,0 +1,3 @@
+package_format 1
+LIBS="-lobjfwtest $LIBS"
+FRAMEWORK_LIBS="-framework ObjFWTest $FRAMEWORK_LIBS"