Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -1,8 +1,8 @@ include extra.mk -SUBDIRS = src utils new_tests +SUBDIRS = src utils tests DISTCLEAN = Info.plist \ aclocal.m4 \ autom4te.cache \ buildsys.mk \ config.h \ @@ -12,14 +12,14 @@ include buildsys.mk .PHONY: check docs release -utils new_tests: src +utils tests: src -check: new_tests - ${MAKE} -C new_tests -s run +check: tests + ${MAKE} -C tests -s run docs: rm -fr docs doxygen >/dev/null Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -439,11 +439,11 @@ AC_DEFINE_UNQUOTED(PLUGIN_SUFFIX, "$PLUGIN_SUFFIX", [Suffix for plugins]) AS_IF([test x"$enable_files" != x"no" -a x"$PLUGIN_SUFFIX" != x""], [ AC_SUBST(USE_SRCS_PLUGINS, '${SRCS_PLUGINS}') AC_SUBST(TESTPLUGIN, "plugin") AC_DEFINE(OF_HAVE_PLUGINS, 1, [Whether we have plugin support]) - AC_CONFIG_FILES(new_tests/plugin/Info.plist) + AC_CONFIG_FILES(tests/plugin/Info.plist) AS_IF([test x"$build_framework" = x"yes"], [ TESTPLUGIN_LIBS="-F../../src -F../../src/runtime" TESTPLUGIN_LIBS="$TESTPLUGIN_LIBS -framework ObjFW" TESTPLUGIN_LIBS="$TESTPLUGIN_LIBS \${RUNTIME_FRAMEWORK_LIBS}" DELETED new_tests/ForwardingTests.m Index: new_tests/ForwardingTests.m ================================================================== --- new_tests/ForwardingTests.m +++ /dev/null @@ -1,317 +0,0 @@ -/* - * 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" - -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -#define FORMAT @"%@ %@ %@ %@ %@ %@ %@ %@ %@ %g %g %g %g %g %g %g %g %g" -#define ARGS @"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", \ - 1.5, 2.25, 3.125, 4.0625, 5.03125, 6.5, 7.25, 8.0, 9.0 -#define RESULT @"a b c d e f g h i 1.5 2.25 3.125 4.0625 5.03125 6.5 7.25 8 9" - -@interface ForwardingTests: OTTestCase -@end - -static size_t forwardingsCount = 0; -static bool success = false; -static id target = nil; - -struct StretTest { - char buffer[1024]; -}; - -@interface ForwardingTestObject: OFObject -@end - -@interface ForwardingTestObject (NonExistentMethods) -+ (void)test; -- (void)test; -- (uint32_t)forwardingTargetTest: (intptr_t)a0 - : (intptr_t)a1 - : (double)a2 - : (double)a3; -- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)format, ...; -- (long double)forwardingTargetFPRetTest; -- (struct StretTest)forwardingTargetStRetTest; -- (void)forwardingTargetNilTest; -- (void)forwardingTargetSelfTest; -- (struct StretTest)forwardingTargetNilStRetTest; -- (struct StretTest)forwardingTargetSelfStRetTest; -@end - -@interface ForwardingTarget: OFObject -@end - -static void -test(id self, SEL _cmd) -{ - success = true; -} - -@implementation ForwardingTests -- (void)setUp -{ - [super setUp]; - - forwardingsCount = 0; - success = false; - target = nil; -} - -- (void)testForwardingMessageAndAddingClassMethod -{ - [ForwardingTestObject test]; - OTAssertTrue(success); - OTAssertEqual(forwardingsCount, 1); - - [ForwardingTestObject test]; - OTAssertEqual(forwardingsCount, 1); -} - -- (void)forwardingMessageAndAddingInstanceMethod -{ - ForwardingTestObject *testObject = - [[[ForwardingTestObject alloc] init] autorelease]; - - [testObject test]; - OTAssertTrue(success); - OTAssertEqual(forwardingsCount, 1); - - [testObject test]; - OTAssertEqual(forwardingsCount, 1); -} - -#ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR -- (void)testForwardingTargetForSelector -{ - ForwardingTestObject *testObject = - [[[ForwardingTestObject alloc] init] autorelease]; - - target = [[[ForwardingTarget alloc] init] autorelease]; - - OTAssertEqual( - [testObject forwardingTargetTest: 0xDEADBEEF - : -1 - : 1.25 - : 2.75], 0x12345678); -} - -- (void)testForwardingTargetForSelectorWithVariableArguments -{ - ForwardingTestObject *testObject = - [[[ForwardingTestObject alloc] init] autorelease]; - - target = [[[ForwardingTarget alloc] init] autorelease]; - - OTAssertEqualObjects( - ([testObject forwardingTargetVarArgTest: FORMAT, ARGS]), RESULT); -} - -/* - * Don't try fpret on Win64 if we don't have stret forwarding, as long double - * is handled as a struct there. - */ -# if !defined(OF_WINDOWS) || !defined(OF_AMD64) || \ - defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET) -- (void)testForwardingTargetForSelectorFPRet -{ - ForwardingTestObject *testObject = - [[[ForwardingTestObject alloc] init] autorelease]; - - target = [[[ForwardingTarget alloc] init] autorelease]; - - OTAssertEqual([testObject forwardingTargetFPRetTest], - 12345678.00006103515625); -} -# endif - -# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET -- (void)testForwardingTargetForSelectorStRet -{ - ForwardingTestObject *testObject = - [[[ForwardingTestObject alloc] init] autorelease]; - - target = [[[ForwardingTarget alloc] init] autorelease]; - - OTAssertEqual(memcmp([testObject forwardingTargetStRetTest].buffer, - "abcdefghijklmnopqrstuvwxyz", 27), 0); -} -# endif - -- (void)testForwardingTargetForSelectorReturningNilThrows -{ - ForwardingTestObject *testObject = - [[[ForwardingTestObject alloc] init] autorelease]; - - target = [[[ForwardingTarget alloc] init] autorelease]; - - OTAssertThrowsSpecific([testObject forwardingTargetNilTest], - OFNotImplementedException); -} - -- (void)testForwardingTargetForSelectorReturningSelfThrows -{ - ForwardingTestObject *testObject = - [[[ForwardingTestObject alloc] init] autorelease]; - - target = [[[ForwardingTarget alloc] init] autorelease]; - - OTAssertThrowsSpecific([testObject forwardingTargetSelfTest], - OFNotImplementedException); -} - -# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET -- (void)testForwardingTargetForSelectorStRetReturningNilThrows -{ - ForwardingTestObject *testObject = - [[[ForwardingTestObject alloc] init] autorelease]; - - target = [[[ForwardingTarget alloc] init] autorelease]; - - OTAssertThrowsSpecific([testObject forwardingTargetNilStRetTest], - OFNotImplementedException); -} - -- (void)testForwardingTargetForSelectorStRetReturningSelfThrows -{ - ForwardingTestObject *testObject = - [[[ForwardingTestObject alloc] init] autorelease]; - - target = [[[ForwardingTarget alloc] init] autorelease]; - - OTAssertThrowsSpecific([testObject forwardingTargetSelfStRetTest], - OFNotImplementedException); -} -# endif -#endif -@end - -@implementation ForwardingTestObject -+ (bool)resolveClassMethod: (SEL)selector -{ - forwardingsCount++; - - if (sel_isEqual(selector, @selector(test))) { - class_replaceMethod(object_getClass(self), @selector(test), - (IMP)test, "v#:"); - return YES; - } - - return NO; -} - -+ (bool)resolveInstanceMethod: (SEL)selector -{ - forwardingsCount++; - - if (sel_isEqual(selector, @selector(test))) { - class_replaceMethod(self, @selector(test), (IMP)test, "v@:"); - return YES; - } - - return NO; -} - -- (id)forwardingTargetForSelector: (SEL)selector -{ - /* - * Do some useless calculations in as many registers as possible to - * check if the arguments are properly saved and restored. - */ - volatile register intptr_t r0 = 0, r1 = 1, r2 = 2, r3 = 3, r4 = 4, - r5 = 5, r6 = 6, r7 = 7, r8 = 8, r9 = 9, r10 = 10, r11 = 11; - volatile register double f0 = 0.5, f1 = 1.5, f2 = 2.5, f3 = 3.5, - f4 = 4.5, f5 = 5.5, f6 = 6.5, f7 = 7.5, f8 = 8.5, f9 = 9.5, - f10 = 10.5, f11 = 11.5; - double add = r0 * r1 * r2 * r3 * r4 * r5 * r6 * r7 * r8 * r9 * r10 * - r11 * f0 * f1 * f2 * f3 * f4 * f5 * f6 * f7 * f8 * f9 * f10 * f11; - - if (sel_isEqual(selector, @selector(forwardingTargetTest::::)) || - sel_isEqual(selector, @selector(forwardingTargetVarArgTest:)) || - sel_isEqual(selector, @selector(forwardingTargetFPRetTest)) || - sel_isEqual(selector, @selector(forwardingTargetStRetTest))) - return (id)((char *)target + (ptrdiff_t)add); - - if (sel_isEqual(selector, @selector(forwardingTargetNilTest)) || - sel_isEqual(selector, @selector(forwardingTargetNilStRetTest))) - return nil; - - if (sel_isEqual(selector, @selector(forwardingTargetSelfTest)) || - sel_isEqual(selector, @selector(forwardingTargetSelfStRetTest))) - return self; - - abort(); - - OF_UNREACHABLE -} -@end - -@implementation ForwardingTarget -- (uint32_t)forwardingTargetTest: (intptr_t)a0 - : (intptr_t)a1 - : (double)a2 - : (double)a3 -{ - OFEnsure(self == target); - - if (a0 != (intptr_t)0xDEADBEEF) - return 0; - if (a1 != -1) - return 0; - if (a2 != 1.25) - return 0; - if (a3 != 2.75) - return 0; - - return 0x12345678; -} - -- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)format, ... -{ - va_list args; - OFString *ret; - - OFEnsure(self == target); - - va_start(args, format); - ret = [[[OFString alloc] initWithFormat: format - arguments: args] autorelease]; - va_end(args); - - return ret; -} - -- (long double)forwardingTargetFPRetTest -{ - OFEnsure(self == target); - - return 12345678.00006103515625; -} - -- (struct StretTest)forwardingTargetStRetTest -{ - struct StretTest ret = { { 0 } }; - - OFEnsure(self == target); - - memcpy(ret.buffer, "abcdefghijklmnopqrstuvwxyz", 27); - - return ret; -} -@end DELETED new_tests/Makefile Index: new_tests/Makefile ================================================================== --- new_tests/Makefile +++ /dev/null @@ -1,230 +0,0 @@ -include ../extra.mk - -SUBDIRS = ${TESTPLUGIN} ${SUBPROCESS} - -CLEAN = EBOOT.PBP \ - boot.dol \ - ${PROG_NOINST}.arm9 \ - ${PROG_NOINST}.nds \ - ${PROG_NOINST}.nro \ - ${PROG_NOINST}.rpx \ - testfile_bin.m \ - testfile_ini.m - -PROG_NOINST = tests${PROG_SUFFIX} -SRCS = ${OF_BLOCK_TESTS_M} \ - ForwardingTests.m \ - OFArrayTests.m \ - OFCharacterSetTests.m \ - OFColorTests.m \ - OFConcreteArrayTests.m \ - OFConcreteDictionaryTests.m \ - OFConcreteMutableArrayTests.m \ - OFConcreteMutableDictionaryTests.m \ - OFConcreteMutableSetTests.m \ - OFConcreteSetTests.m \ - OFCryptographicHashTests.m \ - OFDataTests.m \ - OFDateTests.m \ - OFDictionaryTests.m \ - OFHMACTests.m \ - OFINIFileTests.m \ - OFIRITests.m \ - OFInvocationTests.m \ - OFJSONTests.m \ - OFListTests.m \ - OFLocaleTests.m \ - OFMatrix4x4Tests.m \ - OFMemoryStreamTests.m \ - OFMethodSignatureTests.m \ - OFMutableArrayTests.m \ - OFMutableDataTests.m \ - OFMutableDictionaryTests.m \ - OFMutableSetTests.m \ - OFMutableStringTests.m \ - OFMutableUTF8StringTests.m \ - OFNotificationCenterTests.m \ - OFNumberTests.m \ - OFObjectTests.m \ - OFPBKDF2Tests.m \ - OFPropertyListTests.m \ - OFScryptTests.m \ - OFSetTests.m \ - OFStreamTests.m \ - OFStringTests.m \ - OFSystemInfoTests.m \ - OFUTF8StringTests.m \ - OFValueTests.m \ - OFXMLElementBuilderTests.m \ - OFXMLNodeTests.m \ - OFXMLParserTests.m \ - ${RUNTIME_ARC_TESTS_M} \ - RuntimeTests.m \ - ${USE_SRCS_PLUGINS} \ - ${USE_SRCS_SOCKETS} \ - ${USE_SRCS_SUBPROCESSES} \ - ${USE_SRCS_THREADS} \ - ${USE_SRCS_WINDOWS} \ - testfile_bin.m \ - testfile_ini.m -SRCS_PLUGINS = OFPluginTests.m -SRCS_SOCKETS = OFDNSResolverTests.m \ - ${OF_HTTP_CLIENT_TESTS_M} \ - OFHTTPCookieManagerTests.m \ - OFHTTPCookieTests.m \ - OFKernelEventObserverTests.m \ - OFSocketTests.m \ - OFTCPSocketTests.m \ - OFUDPSocketTests.m \ - ${USE_SRCS_IPX} \ - ${USE_SRCS_UNIX_SOCKETS} \ - ${USE_SRCS_APPLETALK} -SRCS_APPLETALK = OFDDPSocketTests.m -SRCS_IPX = OFIPXSocketTests.m \ - OFSPXSocketTests.m \ - OFSPXStreamSocketTests.m -SRCS_UNIX_SOCKETS = OFUNIXDatagramSocketTests.m \ - OFUNIXStreamSocketTests.m -SRCS_SUBPROCESSES = OFSubprocessTests.m -SRCS_THREADS = OFThreadTests.m -SRCS_WINDOWS = OFWindowsRegistryKeyTests.m - -include ../buildsys.mk - -testfile_bin.m: testfile.bin - ${SHELL} ../utils/objfw-embed testfile.bin testfile.bin $@ -testfile_ini.m: testfile.ini - ${SHELL} ../utils/objfw-embed testfile.ini testfile.ini $@ - -.PHONY: run run-on-ios run-on-android -run: - rm -f libobjfw.so.${OBJFW_LIB_MAJOR} - rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} - rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib - rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} - rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} - rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll - rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib - if test -f ../src/libobjfw.so; then \ - ${LN_S} ../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ - ${LN_S} ../src/libobjfw.so \ - libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ - elif test -f ../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ - ${LN_S} ../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \ - libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ - fi - if test -f ../src/objfw${OBJFW_LIB_MAJOR}.dll; then \ - ${LN_S} ../src/objfw${OBJFW_LIB_MAJOR}.dll \ - objfw${OBJFW_LIB_MAJOR}.dll; \ - fi - if test -f ../src/libobjfw.dylib; then \ - ${LN_S} ../src/libobjfw.dylib \ - libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ - fi - if test -f ../src/runtime/libobjfwrt.so; then \ - ${LN_S} ../src/runtime/libobjfwrt.so \ - libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ - ${LN_S} ../src/runtime/libobjfwrt.so \ - libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ - elif test -f ../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; then \ - ${LN_S} ../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ - fi - if test -f ../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll; then \ - ${LN_S} ../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll \ - objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ - fi - if test -f ../src/runtime/libobjfwrt.dylib; then \ - ${LN_S} ../src/runtime/libobjfwrt.dylib \ - libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ - fi - LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \ - DYLD_FRAMEWORK_PATH=../src:../src/runtime$${DYLD_FRAMEWORK_PATH+:}$$DYLD_FRAMEWORK_PATH \ - DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ - LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ - ASAN_OPTIONS=allocator_may_return_null=1 \ - ${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \ - rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \ - rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ - rm -f objfw${OBJFW_LIB_MAJOR}.dll; \ - rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ - rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ - rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ - rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ - rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ - exit $$EXIT - -run-on-android: all - echo "Uploading files to Android device..." - if test -f ../src/libobjfw.so; then \ - adb push ../src/libobjfw.so \ - /data/local/tmp/objfw/libobjfw.so.${OBJFW_LIB_MAJOR}; \ - fi - if test -f ../src/runtime/libobjfwrt.so; then \ - adb push ../src/runtime/libobjfwrt.so \ - /data/local/tmp/objfw/libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ - fi - adb push tests /data/local/tmp/objfw/tests - adb push testfile.txt /data/local/tmp/objfw/testfile.txt - if test -f plugin/TestPlugin.so; then \ - adb push plugin/TestPlugin.so \ - /data/local/tmp/objfw/plugin/TestPlugin.so; \ - fi - echo "Running tests binary on Android device..." - adb shell 'cd /data/local/tmp/objfw && LD_LIBRARY_PATH=. exec ${WRAPPER} ./tests' - -EBOOT.PBP: ${PROG_NOINST} - psp-fixup-imports ${PROG_NOINST} - mksfo "ObjFW Tests" PARAM.SFO - psp-strip ${PROG_NOINST} - pack-pbp $@ PARAM.SFO NULL NULL NULL NULL NULL ${PROG_NOINST} NULL - -boot.dol: ${PROG_NOINST} - elf2dol ${PROG_NOINST} $@ - -${PROG_NOINST}: ${LIBOBJFW_DEP} ${LIBOBJFWRT_DEP} ../src/test/libobjfwtest.a - -${PROG_NOINST}.3dsx: ${PROG_NOINST} - 3dsxtool $< $@ - -${PROG_NOINST}.arm9: ${PROG_NOINST} - arm-none-eabi-objcopy -O binary $< $@ - -${PROG_NOINST}.nds: ${PROG_NOINST}.arm9 testfile.txt - rm -fr nds-data - mkdir -p nds-data - cp testfile.txt nds-data - ndstool -c $@ -9 ${PROG_NOINST} -d nds-data - rm -fr nds-data - -${PROG_NOINST}.nro: ${PROG_NOINST} testfile.txt - rm -fr romfs - mkdir -p romfs - cp testfile.txt romfs - nacptool --create "ObjFW tests" "Jonathan Schleifer" \ - "${PACKAGE_VERSION}" tests.nacp - elf2nro ${PROG_NOINST} $@ --nacp=tests.nacp --romfsdir=romfs - rm -fr romfs tests.nacp - -${PROG_NOINST}.rpx: ${PROG_NOINST} - elf2rpl $< $@ - -CPPFLAGS += -I../src \ - -I../src/exceptions \ - -I../src/runtime \ - -I../src/test \ - -I.. \ - -DOBJFWTEST_LOCAL_INCLUDES \ - -DPROG_SUFFIX=\"${PROG_SUFFIX}\" -OBJCFLAGS_RuntimeARCTests.m = -fobjc-arc -fobjc-arc-exceptions -# Repetition is required for Wii U, as otherwise it cannot find main. Just -# moving -lobjfwtest later doesn't work either, as then the linker cannot find -# ObjFW symbols. So the only solution is to list everything twice. -LIBS := -L../src/test \ - -lobjfwtest \ - ${TESTS_LIBS} \ - ${LIBS} \ - -lobjfwtest \ - ${TESTS_LIBS} \ - ${LIBS} -LDFLAGS += ${MAP_LDFLAGS} -LD = ${OBJC} DELETED new_tests/OFArrayTests.h Index: new_tests/OFArrayTests.h ================================================================== --- new_tests/OFArrayTests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFArrayTests: OTTestCase -{ - OFArray *_array; -} - -@property (readonly, nonatomic) Class arrayClass; -@end DELETED new_tests/OFArrayTests.m Index: new_tests/OFArrayTests.m ================================================================== --- new_tests/OFArrayTests.m +++ /dev/null @@ -1,313 +0,0 @@ -/* - * 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 "OFArrayTests.h" - -@interface CustomArray: OFArray -{ - OFArray *_array; -} -@end - -static OFString *const cArray[] = { - @"Foo", - @"Bar", - @"Baz" -}; - -@implementation OFArrayTests -- (Class)arrayClass -{ - return [CustomArray class]; -} - -- (void)setUp -{ - [super setUp]; - - _array = [[self.arrayClass alloc] - initWithObjects: cArray - count: sizeof(cArray) / sizeof(*cArray)]; -} - -- (void)dealloc -{ - [_array release]; - - [super dealloc]; -} - -- (void)testArray -{ - OFArray *array = [self.arrayClass array]; - - OTAssertNotNil(array); - OTAssertEqual(array.count, 0); -} - -- (void)testArrayWithObjects -{ - OFArray *array = [self.arrayClass arrayWithObjects: - @"Foo", @"Bar", @"Baz", nil]; - - OTAssertNotNil(array); - OTAssertEqual(array.count, 3); - OTAssertEqualObjects([array objectAtIndex: 0], @"Foo"); - OTAssertEqualObjects([array objectAtIndex: 1], @"Bar"); - OTAssertEqualObjects([array objectAtIndex: 2], @"Baz"); -} - -- (void)testArrayWithObjectsCount -{ - OFArray *array1 = [self.arrayClass arrayWithObjects: - @"Foo", @"Bar", @"Baz", nil]; - OFArray *array2 = [self.arrayClass arrayWithObjects: cArray count: 3]; - - OTAssertEqualObjects(array1, array2); -} - -- (void)testDescription -{ - OTAssertEqualObjects(_array.description, - @"(\n\tFoo,\n\tBar,\n\tBaz\n)"); -} - -- (void)testCount -{ - OTAssertEqual(_array.count, 3); -} - -- (void)testIsEqual -{ - OFArray *array = [self.arrayClass arrayWithObjects: cArray count: 3]; - - OTAssertEqualObjects(array, _array); - OTAssertNotEqual(array, _array); -} - -- (void)testObjectAtIndex -{ - OTAssertEqualObjects([_array objectAtIndex: 0], cArray[0]); - OTAssertEqualObjects([_array objectAtIndex: 1], cArray[1]); - OTAssertEqualObjects([_array objectAtIndex: 2], cArray[2]); -} - -- (void)testObjectAtIndexFailsWhenOutOfRange -{ - OTAssertThrowsSpecific([_array objectAtIndex: _array.count], - OFOutOfRangeException); -} - -- (void)testContainsObject -{ - OTAssertTrue([_array containsObject: cArray[1]]); - OTAssertFalse([_array containsObject: @"nonexistent"]); -} - -- (void)testContainsObjectIdenticalTo -{ - OTAssertTrue([_array containsObjectIdenticalTo: cArray[1]]); - OTAssertFalse([_array containsObjectIdenticalTo: - [OFString stringWithString: cArray[1]]]); -} - -- (void)testIndexOfObject -{ - OTAssertEqual([_array indexOfObject: cArray[1]], 1); - OTAssertEqual([_array indexOfObject: @"nonexistent"], OFNotFound); -} - -- (void)testIndexOfObjectIdenticalTo -{ - OTAssertEqual([_array indexOfObjectIdenticalTo: cArray[1]], 1); - OTAssertEqual([_array indexOfObjectIdenticalTo: - [OFString stringWithString: cArray[1]]], - OFNotFound); -} - -- (void)objectsInRange -{ - OTAssertEqualObjects([_array objectsInRange: OFMakeRange(1, 2)], - ([self.arrayClass arrayWithObjects: cArray[1], cArray[2], nil])); -} - -- (void)testEnumerator -{ - OFEnumerator *enumerator = [_array objectEnumerator]; - - OTAssertEqualObjects([enumerator nextObject], cArray[0]); - OTAssertEqualObjects([enumerator nextObject], cArray[1]); - OTAssertEqualObjects([enumerator nextObject], cArray[2]); - OTAssertNil([enumerator nextObject]); -} - -- (void)testFastEnumeration -{ - size_t i = 0; - - for (OFString *object in _array) { - OTAssertLessThan(i, 3); - OTAssertEqualObjects(object, cArray[i++]); - } -} - -- (void)testComponentsJoinedByString -{ - OFArray *array; - - array = [self.arrayClass arrayWithObjects: @"", @"a", @"b", @"c", nil]; - OTAssertEqualObjects([array componentsJoinedByString: @" "], - @" a b c"); - - array = [self.arrayClass arrayWithObject: @"foo"]; - OTAssertEqualObjects([array componentsJoinedByString: @" "], @"foo"); -} - -- (void)testComponentsJoinedByStringOptions -{ - OFArray *array; - - array = [self.arrayClass - arrayWithObjects: @"", @"foo", @"", @"", @"bar", @"", nil]; - OTAssertEqualObjects( - [array componentsJoinedByString: @" " - options: OFArraySkipEmptyComponents], - @"foo bar"); -} - -- (void)testSortedArray -{ - OFArray *array = [_array arrayByAddingObjectsFromArray: - [OFArray arrayWithObjects: @"0", @"z", nil]]; - - OTAssertEqualObjects([array sortedArray], - ([OFArray arrayWithObjects: @"0", @"Bar", @"Baz", @"Foo", @"z", - nil])); - - OTAssertEqualObjects( - [array sortedArrayUsingSelector: @selector(compare:) - options: OFArraySortDescending], - ([OFArray arrayWithObjects: @"z", @"Foo", @"Baz", @"Bar", @"0", - nil])); -} - -- (void)testReversedArray -{ - OTAssertEqualObjects(_array.reversedArray, - ([OFArray arrayWithObjects: cArray[2], cArray[1], cArray[0], nil])); -} - -#ifdef OF_HAVE_BLOCKS -- (void)testEnumerateObjectsUsingBlock -{ - __block size_t i = 0; - - [_array enumerateObjectsUsingBlock: - ^ (id object, size_t idx, bool *stop) { - OTAssertEqualObjects(object, [_array objectAtIndex: i++]); - }]; - - OTAssertEqual(i, _array.count); -} - -- (void)testMappedArrayUsingBlock -{ - OTAssertEqualObjects( - [_array mappedArrayUsingBlock: ^ id (id object, size_t idx) { - switch (idx) { - case 0: - return @"foobar"; - case 1: - return @"qux"; - } - - return @""; - }].description, - @"(\n\tfoobar,\n\tqux,\n\t\n)"); -} - -- (void)testFilteredArrayUsingBlock -{ - OTAssertEqualObjects( - [_array filteredArrayUsingBlock: ^ bool (id object, size_t idx) { - return [object isEqual: @"Foo"]; - }].description, - @"(\n\tFoo\n)"); - -} - -- (void)testFoldUsingBlock -{ - OTAssertEqualObjects( - [([self.arrayClass arrayWithObjects: [OFMutableString string], - @"foo", @"bar", @"baz", nil]) - foldUsingBlock: ^ id (id left, id right) { - [left appendString: right]; - return left; - }], - @"foobarbaz"); -} -#endif - -- (void)testValueForKey -{ - OTAssertEqualObjects( - [([self.arrayClass arrayWithObjects: @"foo", @"bar", @"quxqux", - nil]) valueForKey: @"length"], - ([self.arrayClass arrayWithObjects: [OFNumber numberWithInt: 3], - [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil])); - - OTAssertEqualObjects( - [([self.arrayClass arrayWithObjects: @"1", @"2", nil]) - valueForKey: @"@count"], - [OFNumber numberWithInt: 2]); -} -@end - -@implementation CustomArray -- (instancetype)initWithObjects: (id const *)objects count: (size_t)count -{ - self = [super init]; - - @try { - _array = [[OFArray alloc] initWithObjects: objects - count: count]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_array release]; - - [super dealloc]; -} - -- (id)objectAtIndex: (size_t)idx -{ - return [_array objectAtIndex: idx]; -} - -- (size_t)count -{ - return [_array count]; -} -@end DELETED new_tests/OFBlockTests.m Index: new_tests/OFBlockTests.m ================================================================== --- new_tests/OFBlockTests.m +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFBlockTests: OTTestCase -@end - -#if defined(OF_OBJFW_RUNTIME) -extern struct objc_class _NSConcreteStackBlock; -extern struct objc_class _NSConcreteGlobalBlock; -extern struct objc_class _NSConcreteMallocBlock; -#elif defined(OF_APPLE_RUNTIME) -extern void *_NSConcreteStackBlock; -extern void *_NSConcreteGlobalBlock; -extern void *_NSConcreteMallocBlock; -#endif - -/* Clang on Win32 generates broken code that crashes for global blocks. */ -#if !defined(OF_WINDOWS) || !defined(__clang__) -static void (^globalBlock)(void) = ^ {}; -#endif - -static int -(^returnStackBlock(void))(void) -{ - __block int i = 42; - - return [Block_copy(^ int { return ++i; }) autorelease]; -} - -static double -forwardTest(void) -{ - __block double d; - void (^block)(void) = Block_copy(^ { - d = 5; - }); - - block(); - Block_release(block); - - return d; -} - -@implementation OFBlockTests -- (void)testClassOfStackBlock -{ - __block int x; - void (^stackBlock)(void) = ^ { - x = 0; - (void)x; - }; - - OTAssertEqual((Class)&_NSConcreteStackBlock, - objc_getClass("OFStackBlock")); - OTAssertTrue([stackBlock isKindOfClass: [OFBlock class]]); -} - -#if !defined(OF_WINDOWS) || !defined(__clang__) -- (void)testClassOfGlobalBlock -{ - OTAssertEqual((Class)&_NSConcreteGlobalBlock, - objc_getClass("OFGlobalBlock")); - OTAssertTrue([globalBlock isKindOfClass: [OFBlock class]]); -} -#endif - -- (void)testClassOfMallocBlock -{ - OTAssertEqual((Class)&_NSConcreteMallocBlock, - objc_getClass("OFMallocBlock")); -} - -- (void)testCopyStackBlock -{ - __block int x; - void (^stackBlock)(void) = ^ { - x = 0; - (void)x; - }; - void (^mallocBlock)(void); - - mallocBlock = [[stackBlock copy] autorelease]; - OTAssertEqual([mallocBlock class], objc_getClass("OFMallocBlock")); - OTAssertTrue([mallocBlock isKindOfClass: [OFBlock class]]); -} - -- (void)testCopyStackBlockAndReferenceVariable -{ - OTAssertEqual(forwardTest(), 5); -} - -- (void)testCopyStackBlockAndReferenceCopiedVariable -{ - int (^voidBlock)(void) = returnStackBlock(); - - OTAssertEqual(voidBlock(), 43); - OTAssertEqual(voidBlock(), 44); - OTAssertEqual(voidBlock(), 45); -} - -#if !defined(OF_WINDOWS) || !defined(__clang__) -- (void)testCopyGlobalBlock -{ - OTAssertEqual([[globalBlock copy] autorelease], (id)globalBlock); -} -#endif - -- (void)testCopyMallocBlock -{ - __block int x; - void (^stackBlock)(void) = ^ { - x = 0; - (void)x; - }; - void (^mallocBlock)(void); - - mallocBlock = [[stackBlock copy] autorelease]; - OTAssertEqual([[mallocBlock copy] autorelease], (id)mallocBlock); - OTAssertEqual([mallocBlock retainCount], 2); -} -@end DELETED new_tests/OFCharacterSetTests.m Index: new_tests/OFCharacterSetTests.m ================================================================== --- new_tests/OFCharacterSetTests.m +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -#import "OFCharacterSet.h" -#import "OFBitSetCharacterSet.h" -#import "OFRangeCharacterSet.h" - -@interface OFCharacterSetTests: OTTestCase -@end - -@interface CustomCharacterSet: OFCharacterSet -@end - -@implementation CustomCharacterSet -- (bool)characterIsMember: (OFUnichar)character -{ - return (character % 2 == 0); -} -@end - -@implementation OFCharacterSetTests -- (void)testCustomCharacterSet -{ - OFCharacterSet *characterSet = - [[[CustomCharacterSet alloc] init] autorelease]; - - for (OFUnichar c = 0; c < 65536; c++) - if (c % 2 == 0) - OTAssertTrue([characterSet characterIsMember: c]); - else - OTAssertFalse([characterSet characterIsMember: c]); -} - -- (void)testBitSetCharacterSet -{ - OFCharacterSet *characterSet = - [OFCharacterSet characterSetWithCharactersInString: @"0123456789"]; - - OTAssertTrue( - [characterSet isKindOfClass: [OFBitSetCharacterSet class]]); - - for (OFUnichar c = 0; c < 65536; c++) - if (c >= '0' && c <= '9') - OTAssertTrue([characterSet characterIsMember: c]); - else if ([characterSet characterIsMember: c]) - OTAssertFalse([characterSet characterIsMember: c]); -} - -- (void)testRangeCharacterSet -{ - OFCharacterSet *characterSet = - [OFCharacterSet characterSetWithRange: OFMakeRange('0', 10)]; - - OTAssertTrue( - [characterSet isKindOfClass: [OFRangeCharacterSet class]]); - - for (OFUnichar c = 0; c < 65536; c++) - if (c >= '0' && c <= '9') - OTAssertTrue([characterSet characterIsMember: c]); - else - OTAssertFalse([characterSet characterIsMember: c]); -} - -- (void)testInvertedCharacterSet -{ - OFCharacterSet *characterSet = [[OFCharacterSet - characterSetWithRange: OFMakeRange('0', 10)] invertedSet]; - - for (OFUnichar c = 0; c < 65536; c++) - if (c >= '0' && c <= '9') - OTAssertFalse([characterSet characterIsMember: c]); - else - OTAssertTrue([characterSet characterIsMember: c]); -} - -- (void)testInvertingInvertedSetReturnsOriginal -{ - OFCharacterSet *characterSet = - [OFCharacterSet characterSetWithRange: OFMakeRange('0', 10)]; - - OTAssertEqual(characterSet, characterSet.invertedSet.invertedSet); -} -@end DELETED new_tests/OFColorTests.m Index: new_tests/OFColorTests.m ================================================================== --- new_tests/OFColorTests.m +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFColorTests: OTTestCase -{ - OFColor *_color; -} -@end - -@implementation OFColorTests -- (void)setUp -{ - [super setUp]; - - _color = [[OFColor alloc] initWithRed: 63.f / 255 - green: 127.f / 255 - blue: 1 - alpha: 1]; -} - -- (void)dealloc -{ - [_color release]; - - [super dealloc]; -} - -#ifdef OF_OBJFW_RUNTIME -- (void)testReturnsTaggedPointer -{ - OTAssertTrue(object_isTaggedPointer(_color)); -} -#endif - -- (void)testGetRedGreenBlueAlpha -{ - float red, green, blue, alpha; - - [_color getRed: &red green: &green blue: &blue alpha: &alpha]; - OTAssertEqual(red, 63.f / 255); - OTAssertEqual(green, 127.f / 255); - OTAssertEqual(blue, 1); - OTAssertEqual(alpha, 1); -} -@end DELETED new_tests/OFConcreteArrayTests.m Index: new_tests/OFConcreteArrayTests.m ================================================================== --- new_tests/OFConcreteArrayTests.m +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 "OFArrayTests.h" - -#import "OFConcreteArray.h" - -@interface OFConcreteArrayTests: OFArrayTests -@end - -@implementation OFConcreteArrayTests -- (Class)arrayClass -{ - return [OFConcreteArray class]; -} -@end DELETED new_tests/OFConcreteDictionaryTests.m Index: new_tests/OFConcreteDictionaryTests.m ================================================================== --- new_tests/OFConcreteDictionaryTests.m +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 "OFDictionaryTests.h" - -#import "OFConcreteDictionary.h" - -@interface OFConcreteDictionaryTests: OFDictionaryTests -@end - -@implementation OFConcreteDictionaryTests -- (Class)dictionaryClass -{ - return [OFConcreteDictionary class]; -} -@end DELETED new_tests/OFConcreteMutableArrayTests.m Index: new_tests/OFConcreteMutableArrayTests.m ================================================================== --- new_tests/OFConcreteMutableArrayTests.m +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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 "OFMutableArrayTests.h" - -#import "OFConcreteMutableArray.h" - -@interface OFConcreteMutableArrayTests: OFMutableArrayTests -@end - -static OFString *const cArray[] = { - @"Foo", - @"Bar", - @"Baz" -}; - -@implementation OFConcreteMutableArrayTests -- (Class)arrayClass -{ - return [OFConcreteMutableArray class]; -} - -- (void)testDetectMutationDuringEnumeration -{ - OFEnumerator *enumerator = [_mutableArray objectEnumerator]; - OFString *object; - size_t i; - - i = 0; - while ((object = [enumerator nextObject]) != nil) { - OTAssertEqualObjects(object, cArray[i]); - - [_mutableArray replaceObjectAtIndex: i withObject: @""]; - i++; - } - OTAssertEqual(i, _mutableArray.count); - - [_mutableArray removeObjectAtIndex: 0]; - OTAssertThrowsSpecific([enumerator nextObject], - OFEnumerationMutationException); -} - -- (void)testDetectMutationDuringFastEnumeration -{ - bool detected = false; - size_t i; - - i = 0; - for (OFString *object in _mutableArray) { - OTAssertEqualObjects(object, cArray[i]); - - [_mutableArray replaceObjectAtIndex: i withObject: @""]; - i++; - } - OTAssertEqual(i, _mutableArray.count); - - @try { - for (OFString *object in _mutableArray) { - (void)object; - [_mutableArray removeObjectAtIndex: 0]; - } - } @catch (OFEnumerationMutationException *e) { - detected = true; - } - OTAssertTrue(detected); -} - -#ifdef OF_HAVE_BLOCKS -- (void)testDetectMutationDuringEnumerateObjectsUsingBlock -{ - __block size_t i; - - i = 0; - [_mutableArray enumerateObjectsUsingBlock: - ^ (id object, size_t idx, bool *stop) { - OTAssertEqualObjects(object, cArray[idx]); - - [_mutableArray replaceObjectAtIndex: idx withObject: @""]; - i++; - }]; - OTAssertEqual(i, _mutableArray.count); - - OTAssertThrowsSpecific( - [_mutableArray enumerateObjectsUsingBlock: - ^ (id object, size_t idx, bool *stop) { - [_mutableArray removeObjectAtIndex: 0]; - }], - OFEnumerationMutationException); -} -#endif -@end DELETED new_tests/OFConcreteMutableDictionaryTests.m Index: new_tests/OFConcreteMutableDictionaryTests.m ================================================================== --- new_tests/OFConcreteMutableDictionaryTests.m +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 "OFMutableDictionaryTests.h" - -#import "OFConcreteMutableDictionary.h" - -@interface OFConcreteMutableDictionaryTests: OFMutableDictionaryTests -@end - -@implementation OFConcreteMutableDictionaryTests -- (Class)dictionaryClass -{ - return [OFConcreteMutableDictionary class]; -} - -- (void)testDetectMutationDuringEnumeration -{ - OFMutableDictionary *mutableDictionary = - [[_dictionary mutableCopy] autorelease]; - OFEnumerator *keyEnumerator = [mutableDictionary keyEnumerator]; - OFEnumerator *objectEnumerator = [mutableDictionary objectEnumerator]; - OFString *key; - size_t i; - - i = 0; - while ((key = [keyEnumerator nextObject]) != nil) { - [mutableDictionary setObject: @"test" forKey: key]; - i++; - } - OTAssertEqual(i, mutableDictionary.count); - - [mutableDictionary removeObjectForKey: @"key2"]; - OTAssertThrowsSpecific([keyEnumerator nextObject], - OFEnumerationMutationException); - OTAssertThrowsSpecific([objectEnumerator nextObject], - OFEnumerationMutationException); -} - -- (void)testDetectMutationDuringFastEnumeration -{ - OFMutableDictionary *mutableDictionary = - [[_dictionary mutableCopy] autorelease]; - bool detected = false; - size_t i; - - i = 0; - for (OFString *key in mutableDictionary) { - [mutableDictionary setObject: @"test" forKey: key]; - i++; - } - OTAssertEqual(i, mutableDictionary.count); - - @try { - for (OFString *key in mutableDictionary) - [mutableDictionary removeObjectForKey: key]; - } @catch (OFEnumerationMutationException *e) { - detected = true; - } - OTAssertTrue(detected); -} - -#ifdef OF_HAVE_BLOCKS -- (void)testDetectMutationDuringEnumerateObjectsUsingBlock -{ - OFMutableDictionary *mutableDictionary = - [[_dictionary mutableCopy] autorelease]; - __block size_t i; - - i = 0; - [mutableDictionary enumerateKeysAndObjectsUsingBlock: - ^ (id key, id object, bool *stop) { - [mutableDictionary setObject: @"test" forKey: key]; - i++; - }]; - OTAssertEqual(i, mutableDictionary.count); - - OTAssertThrowsSpecific( - [mutableDictionary enumerateKeysAndObjectsUsingBlock: - ^ (id key, id object, bool *stop) { - [mutableDictionary removeObjectForKey: key]; - }], - OFEnumerationMutationException); -} -#endif -@end DELETED new_tests/OFConcreteMutableSetTests.m Index: new_tests/OFConcreteMutableSetTests.m ================================================================== --- new_tests/OFConcreteMutableSetTests.m +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 "OFMutableSetTests.h" - -#import "OFConcreteMutableSet.h" - -@interface OFConcreteMutableSetTests: OFMutableSetTests -@end - -@implementation OFConcreteMutableSetTests -- (Class)setClass -{ - return [OFConcreteMutableSet class]; -} - -- (void)testDetectMutationDuringEnumeration -{ - OFEnumerator *enumerator = [_mutableSet objectEnumerator]; - - [_mutableSet removeObject: @"foo"]; - - OTAssertThrowsSpecific([enumerator nextObject], - OFEnumerationMutationException); -} - -- (void)testDetectMutationDuringFastEnumeration -{ - bool detected = false; - - @try { - for (OFString *object in _mutableSet) - [_mutableSet removeObject: object]; - } @catch (OFEnumerationMutationException *e) { - detected = true; - } - - OTAssertTrue(detected); -} - -#ifdef OF_HAVE_BLOCKS -- (void)testDetectMutationDuringEnumerateObjectsUsingBlock -{ - OTAssertThrowsSpecific( - [_mutableSet enumerateObjectsUsingBlock: ^ (id object, bool *stop) { - [_mutableSet removeObject: object]; - }], - OFEnumerationMutationException); -} -#endif -@end DELETED new_tests/OFConcreteSetTests.m Index: new_tests/OFConcreteSetTests.m ================================================================== --- new_tests/OFConcreteSetTests.m +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 "OFSetTests.h" - -#import "OFConcreteSet.h" - -@interface OFConcreteSetTests: OFSetTests -@end - -@implementation OFConcreteSetTests -- (Class)setClass -{ - return [OFConcreteSet class]; -} -@end DELETED new_tests/OFCryptographicHashTests.m Index: new_tests/OFCryptographicHashTests.m ================================================================== --- new_tests/OFCryptographicHashTests.m +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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" - -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFCryptographicHashTests: OTTestCase -{ - OFStream *_stream; -} -@end - -const unsigned char testFileMD5[16] = - "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38"; -const unsigned char testFileRIPEMD160[20] = - "\x46\x02\x97\xF5\x85\xDF\xB9\x21\x00\xC8\xF9\x87\xC6\xEC\x84\x0D" - "\xCE\xE6\x08\x8B"; -const unsigned char testFileSHA1[20] = - "\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96" - "\xF5\x94\xE7\x17"; -const unsigned char testFileSHA224[28] = - "\x27\x69\xD8\x04\x2D\x0F\xCA\x84\x6C\xF1\x62\x44\xBA\x0C\xBD\x46" - "\x64\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7"; -const unsigned char testFileSHA256[32] = - "\x1A\x02\xD6\x46\xF5\xA6\xBA\xAA\xFF\x7F\xD5\x87\xBA\xC3\xF6\xC6" - "\xB5\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69"; -const unsigned char testFileSHA384[48] = - "\x7E\xDE\x62\xE2\x10\xA5\x1E\x18\x8A\x11\x7F\x78\xD7\xC7\x55\xB6" - "\x43\x94\x1B\xD2\x78\x5C\xCF\xF3\x8A\xB8\x98\x22\xC7\x0E\xFE\xF1" - "\xEC\x53\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54"; -const unsigned char testFileSHA512[64] = - "\x8F\x36\x6E\x3C\x19\x4B\xBB\xC7\x82\xAA\xCD\x7D\x55\xA2\xD3\x29" - "\x29\x97\x6A\x3F\xEB\x9B\xB2\xCB\x75\xC9\xEC\xC8\x10\x07\xD6\x07" - "\x31\x4A\xB1\x30\x97\x82\x58\xA5\x1F\x71\x42\xE6\x56\x07\x99\x57" - "\xB2\xB8\x3B\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0"; - -@implementation OFCryptographicHashTests -- (void)setUp -{ - OFIRI *IRI; - - [super setUp]; - - IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; - _stream = [[OFIRIHandler openItemAtIRI: IRI mode: @"r"] retain]; -} - -- (void)tearDown -{ - [_stream close]; - - [super tearDown]; -} - -- (void)dealloc -{ - [_stream release]; - - [super dealloc]; -} - -- (void)testHash: (Class)hashClass - expectedDigest: (const unsigned char *)expectedDigest -{ - id hash = - [hashClass hashWithAllowsSwappableMemory: true]; - id copy; - - OTAssertNotNil(hash); - - while (!_stream.atEndOfStream) { - char buffer[64]; - size_t length = [_stream readIntoBuffer: buffer length: 64]; - [hash updateWithBuffer: buffer length: length]; - } - - copy = [[hash copy] autorelease]; - - [hash calculate]; - [copy calculate]; - - OTAssertEqual(memcmp(hash.digest, expectedDigest, hash.digestSize), 0); - OTAssertEqual(memcmp(hash.digest, expectedDigest, hash.digestSize), 0); - - OTAssertThrowsSpecific([hash updateWithBuffer: "" length: 1], - OFHashAlreadyCalculatedException); -} - -- (void)testMD5 -{ - [self testHash: [OFMD5Hash class] expectedDigest: testFileMD5]; -} - -- (void)testRIPEMD160 -{ - [self testHash: [OFRIPEMD160Hash class] - expectedDigest: testFileRIPEMD160]; -} - -- (void)testSHA1 -{ - [self testHash: [OFSHA1Hash class] expectedDigest: testFileSHA1]; -} - -- (void)testSHA224 -{ - [self testHash: [OFSHA224Hash class] expectedDigest: testFileSHA224]; -} - -- (void)testSHA256 -{ - [self testHash: [OFSHA256Hash class] expectedDigest: testFileSHA256]; -} - -- (void)testSHA384 -{ - [self testHash: [OFSHA384Hash class] expectedDigest: testFileSHA384]; -} - -- (void)testSHA512 -{ - [self testHash: [OFSHA512Hash class] expectedDigest: testFileSHA512]; -} -@end DELETED new_tests/OFDDPSocketTests.m Index: new_tests/OFDDPSocketTests.m ================================================================== --- new_tests/OFDDPSocketTests.m +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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" - -#include -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFDDPSocketTests: OTTestCase -@end - -@implementation OFDDPSocketTests -- (void)testDDPSocket -{ - OFDDPSocket *sock; - OFSocketAddress address1, address2; - char buffer[5]; - - sock = [OFDDPSocket socket]; - - @try { - address1 = [sock bindToNetwork: 0 - node: 0 - port: 0 - protocolType: 11]; - } @catch (OFBindSocketFailedException *e) { - switch (e.errNo) { - case EAFNOSUPPORT: - case EPROTONOSUPPORT: - OTSkip(@"AppleTalk unsupported"); - case EADDRNOTAVAIL: - OTSkip(@"AppleTalk not configured"); - default: - @throw e; - } - } - - [sock sendBuffer: "Hello" length: 5 receiver: &address1]; - - OTAssertEqual([sock receiveIntoBuffer: buffer - length: 5 - sender: &address2], 5); - OTAssertEqual(memcmp(buffer, "Hello", 5), 0); - OTAssertTrue(OFSocketAddressEqual(&address1, &address2)); - OTAssertEqual(OFSocketAddressHash(&address1), - OFSocketAddressHash(&address2)); -} -@end DELETED new_tests/OFDNSResolverTests.m Index: new_tests/OFDNSResolverTests.m ================================================================== --- new_tests/OFDNSResolverTests.m +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFDNSResolverTests: OTTestCase -@end - -@implementation OFDNSResolverTests -+ (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, id) *) *)summary -{ - OFMutableArray *summary = [OFMutableArray array]; - OFDNSResolver *resolver = [OFDNSResolver resolver]; - OFMutableString *staticHosts = [OFMutableString string]; - -#define ADD(name, value) \ - [summary addObject: [OFPair pairWithFirstObject: name \ - secondObject: value]]; -#define ADD_DOUBLE(name, value) \ - ADD(name, [OFNumber numberWithDouble: value]) -#define ADD_UINT(name, value) \ - ADD(name, [OFNumber numberWithUnsignedInt: value]); -#define ADD_BOOL(name, value) \ - ADD(name, [OFNumber numberWithBool: value]); - - for (OFString *host in resolver.staticHosts) { - OFString *IPs; - - if (staticHosts.length > 0) - [staticHosts appendString: @"; "]; - - IPs = [[resolver.staticHosts objectForKey: host] - componentsJoinedByString: @", "]; - - [staticHosts appendFormat: @"%@=(%@)", host, IPs]; - } - ADD(@"Static hosts", staticHosts) - - ADD(@"Name servers", - [resolver.nameServers componentsJoinedByString: @", "]); - ADD(@"Local domain", resolver.localDomain); - ADD(@"Search domains", - [resolver.searchDomains componentsJoinedByString: @", "]); - - ADD_DOUBLE(@"Timeout", resolver.timeout); - ADD_UINT(@"Max attempts", resolver.maxAttempts); - ADD_UINT(@"Min number of dots in absolute name", - resolver.minNumberOfDotsInAbsoluteName); - ADD_BOOL(@"Forces TCP", resolver.forcesTCP); - ADD_DOUBLE(@"Config reload interval", resolver.configReloadInterval); - -#undef ADD -#undef ADD_DOUBLE -#undef ADD_UINT -#undef ADD_BOOL - - return summary; -} -@end DELETED new_tests/OFDataTests.h Index: new_tests/OFDataTests.h ================================================================== --- new_tests/OFDataTests.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFDataTests: OTTestCase -{ - OFData *_data; - unsigned char _items[2][4096]; -} - -@property (readonly, nonatomic) Class dataClass; -@end DELETED new_tests/OFDataTests.m Index: new_tests/OFDataTests.m ================================================================== --- new_tests/OFDataTests.m +++ /dev/null @@ -1,291 +0,0 @@ -/* - * 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" - -#include - -#import "OFDataTests.h" - -@implementation OFDataTests -- (Class)dataClass -{ - return [OFData class]; -} - -- (void)setUp -{ - [super setUp]; - - memset(&_items[0], 0xFF, 4096); - memset(&_items[1], 0x42, 4096); - - _data = [[self.dataClass alloc] initWithItems: _items - count: 2 - itemSize: 4096]; -} - -- (void)dealloc -{ - [_data release]; - - [super dealloc]; -} - -- (void)testCount -{ - OTAssertEqual(_data.count, 2); -} - -- (void)testItemSize -{ - OTAssertEqual(_data.itemSize, 4096); -} - -- (void)testItems -{ - OTAssertEqual(memcmp(_data.items, _items, 2 * _data.itemSize), 0); -} - -- (void)testItemAtIndex -{ - OTAssertEqual( - memcmp([_data itemAtIndex: 1], &_items[1], _data.itemSize), 0); -} - -- (void)testItemAtIndexThrowsOnOutOfRangeIndex -{ - OTAssertThrowsSpecific([_data itemAtIndex: _data.count], - OFOutOfRangeException); -} - -- (void)testFirstItem -{ - OTAssertEqual(memcmp(_data.firstItem, &_items[0], _data.itemSize), 0); -} - -- (void)testLastItem -{ - OTAssertEqual(memcmp(_data.lastItem, &_items[1], _data.itemSize), 0); -} - -- (void)testIsEqual -{ - OTAssertEqualObjects( - _data, [OFData dataWithItems: _items count: 2 itemSize: 4096]); - OTAssertNotEqualObjects( - _data, [OFData dataWithItems: _items count: 1 itemSize: 4096]); -} - -- (void)testHash -{ - OTAssertEqual(_data.hash, - [[OFData dataWithItems: _items count: 2 itemSize: 4096] hash]); - OTAssertNotEqual(_data.hash, - [[OFData dataWithItems: _items count: 1 itemSize: 4096] hash]); -} - -- (void)testCompare -{ - OFData *data1 = [self.dataClass dataWithItems: "aa" count: 2]; - OFData *data2 = [self.dataClass dataWithItems: "ab" count: 2]; - OFData *data3 = [self.dataClass dataWithItems: "aaa" count: 3]; - - OTAssertEqual([data1 compare: data2], OFOrderedAscending); - OTAssertEqual([data2 compare: data1], OFOrderedDescending); - OTAssertEqual([data1 compare: data1], OFOrderedSame); - OTAssertEqual([data1 compare: data3], OFOrderedAscending); - OTAssertEqual([data2 compare: data3], OFOrderedDescending); -} - -- (void)testCopy -{ - OTAssertEqualObjects([[_data copy] autorelease], _data); -} - -- (void)testRangeOfDataOptionsRange -{ - OFData *data = [self.dataClass dataWithItems: "aaabaccdacaabb" - count: 7 - itemSize: 2]; - OFRange range; - - range = [data rangeOfData: [self.dataClass dataWithItems: "aa" - count: 1 - itemSize: 2] - options: 0 - range: OFMakeRange(0, 7)]; - OTAssertEqual(range.location, 0); - OTAssertEqual(range.length, 1); - - range = [data rangeOfData: [self.dataClass dataWithItems: "aa" - count: 1 - itemSize: 2] - options: OFDataSearchBackwards - range: OFMakeRange(0, 7)]; - OTAssertEqual(range.location, 5); - OTAssertEqual(range.length, 1); - - range = [data rangeOfData: [self.dataClass dataWithItems: "ac" - count: 1 - itemSize: 2] - options: 0 - range: OFMakeRange(0, 7)]; - OTAssertEqual(range.location, 2); - OTAssertEqual(range.length, 1); - - range = [data rangeOfData: [self.dataClass dataWithItems: "aabb" - count: 2 - itemSize: 2] - options: 0 - range: OFMakeRange(0, 7)]; - OTAssertEqual(range.location, 5); - OTAssertEqual(range.length, 2); - - range = [data rangeOfData: [self.dataClass dataWithItems: "aa" - count: 1 - itemSize: 2] - options: 0 - range: OFMakeRange(1, 6)]; - OTAssertEqual(range.location, 5); - OTAssertEqual(range.length, 1); - - range = [data rangeOfData: [self.dataClass dataWithItems: "aa" - count: 1 - itemSize: 2] - options: OFDataSearchBackwards - range: OFMakeRange(0, 5)]; - OTAssertEqual(range.location, 0); - OTAssertEqual(range.length, 1); -} - -- (void)testRangeOfDataOptionsRangeThrowsOnDifferentItemSize -{ - OTAssertThrowsSpecific( - [_data rangeOfData: [OFData dataWithItems: "a" count: 1] - options: 0 - range: OFMakeRange(0, 1)], - OFInvalidArgumentException); -} - -- (void)testRangeOfDataOptionsRangeThrowsOnOutOfRangeRange -{ - OTAssertThrowsSpecific( - [_data rangeOfData: [OFData dataWithItemSize: 4096] - options: 0 - range: OFMakeRange(1, 2)], - OFOutOfRangeException); - - OTAssertThrowsSpecific( - [_data rangeOfData: [OFData dataWithItemSize: 4096] - options: 0 - range: OFMakeRange(2, 1)], - OFOutOfRangeException); -} - -- (void)testSubdataWithRange -{ - OFData *data1 = [self.dataClass dataWithItems: "aaabaccdacaabb" - count: 7 - itemSize: 2]; - OFData *data2 = [self.dataClass dataWithItems: "abcde" count: 5]; - - OTAssertEqualObjects( - [data1 subdataWithRange: OFMakeRange(2, 4)], - [OFData dataWithItems: "accdacaa" count: 4 itemSize: 2]); - - OTAssertEqualObjects( - [data2 subdataWithRange: OFMakeRange(2, 3)], - [OFData dataWithItems: "cde" count: 3]); -} - -- (void)testSubdataWithRangeThrowsOnOutOfRangeRange -{ - OFData *data1 = [self.dataClass dataWithItems: "aaabaccdacaabb" - count: 7 - itemSize: 2]; - OFData *data2 = [self.dataClass dataWithItems: "abcde" count: 5]; - - OTAssertThrowsSpecific([data1 subdataWithRange: OFMakeRange(7, 1)], - OFOutOfRangeException); - - OTAssertThrowsSpecific([data1 subdataWithRange: OFMakeRange(8, 0)], - OFOutOfRangeException); - - OTAssertThrowsSpecific([data2 subdataWithRange: OFMakeRange(6, 1)], - OFOutOfRangeException); -} - -- (void)testStringByMD5Hashing -{ - OTAssertEqualObjects(_data.stringByMD5Hashing, - @"37d65c8816008d58175b1d71ee892de3"); -} - -- (void)testStringByRIPEMD160Hashing -{ - OTAssertEqualObjects(_data.stringByRIPEMD160Hashing, - @"ab33a6a725f9fcec6299054dc604c0eb650cd889"); -} - -- (void)testStringBySHA1Hashing -{ - OTAssertEqualObjects(_data.stringBySHA1Hashing, - @"eb50cfcc29d0bed96b3bafe03e99110bcf6663b3"); -} - -- (void)testStringBySHA224Hashing -{ - OTAssertEqualObjects(_data.stringBySHA224Hashing, - @"204f8418a914a6828f8eb27871e01f74366f6d8fac8936029ebf0041"); -} - -- (void)testStringBySHA256Hashing -{ - OTAssertEqualObjects(_data.stringBySHA256Hashing, - @"27c521859f6f5b10aeac4e210a6d005c" - @"85e382c594e2622af9c46c6da8906821"); -} - -- (void)testStringBySHA384Hashing -{ - OTAssertEqualObjects(_data.stringBySHA384Hashing, - @"af99a52c26c00f01fe649dcc53d7c7a0" - @"a9ee0150b971955be2af395708966120" - @"5f2634f70df083ef63b232d5b8549db4"); -} - -- (void)testStringBySHA512Hashing -{ - OTAssertEqualObjects(_data.stringBySHA512Hashing, - @"1cbd53bf8bed9b45a63edda645ee1217" - @"24d2f0323c865e1039ba13320bc6c66e" - @"c79b6cdf6d08395c612b7decb1e59ad1" - @"e72bfa007c2f76a823d10204d47d2e2d"); -} - -- (void)testStringByBase64Encoding -{ - OTAssertEqualObjects([[self.dataClass dataWithItems: "abcde" count: 5] - stringByBase64Encoding], @"YWJjZGU="); -} - -- (void)testDataWithBase64EncodedString -{ - OTAssertEqualObjects( - [self.dataClass dataWithBase64EncodedString: @"YWJjZGU="], - [OFData dataWithItems: "abcde" count: 5]); -} -@end DELETED new_tests/OFDateTests.m Index: new_tests/OFDateTests.m ================================================================== --- new_tests/OFDateTests.m +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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" - -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -#import "OFStrPTime.h" - -@interface OFDateTests: OTTestCase -{ - OFDate *_date[2]; -} -@end - -@implementation OFDateTests -- (void)setUp -{ - [super setUp]; - - _date[0] = [[OFDate alloc] initWithTimeIntervalSince1970: 0]; - _date[1] = [[OFDate alloc] - initWithTimeIntervalSince1970: 3600 * 25 + 5.000002]; -} - -- (void)dealloc -{ - [_date[0] release]; - [_date[1] release]; - - [super dealloc]; -} - -- (void)testStrPTime -{ - struct tm tm; - int16_t timeZone; - const char *dateString = "Wed, 09 Jun 2021 +0200x"; - - OTAssertEqual(OFStrPTime(dateString, "%a, %d %b %Y %z", &tm, &timeZone), - dateString + 22); - OTAssertEqual(tm.tm_wday, 3); - OTAssertEqual(tm.tm_mday, 9); - OTAssertEqual(tm.tm_mon, 5); - OTAssertEqual(tm.tm_year, 2021 - 1900); - OTAssertEqual(timeZone, 2 * 60); -} - -- (void)testDateByAddingTimeInterval -{ - OTAssertEqualObjects( - [_date[0] dateByAddingTimeInterval: 3600 * 25 + 5.000002], - _date[1]); -} - -- (void)testDescription -{ - OTAssertEqualObjects(_date[0].description, @"1970-01-01T00:00:00Z"); - OTAssertEqualObjects(_date[1].description, @"1970-01-02T01:00:05Z"); -} - -- (void)testDateWithDateStringFormat -{ - OTAssertEqualObjects( - [[OFDate dateWithDateString: @"2000-06-20T12:34:56+0200" - format: @"%Y-%m-%dT%H:%M:%S%z"] description], - @"2000-06-20T10:34:56Z"); -} - -- (void)testDateWithDateStringFormatFailsWithTrailingCharacters -{ - OTAssertThrowsSpecific( - [OFDate dateWithDateString: @"2000-06-20T12:34:56+0200x" - format: @"%Y-%m-%dT%H:%M:%S%z"], - OFInvalidFormatException); -} - -- (void)testDateWithLocalDateStringFormatFormat -{ - OTAssertEqualObjects( - [[OFDate dateWithLocalDateString: @"2000-06-20T12:34:56" - format: @"%Y-%m-%dT%H:%M:%S"] - localDateStringWithFormat: @"%Y-%m-%dT%H:%M:%S"], - @"2000-06-20T12:34:56"); - - OTAssertEqualObjects( - [[OFDate dateWithLocalDateString: @"2000-06-20T12:34:56-0200" - format: @"%Y-%m-%dT%H:%M:%S%z"] - description], - @"2000-06-20T14:34:56Z"); -} - -- (void)testDateWithLocalDateStringFormatFailsWithTrailingCharacters -{ - OTAssertThrowsSpecific( - [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56x" - format: @"%Y-%m-%dT%H:%M:%S"], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56+0200x" - format: @"%Y-%m-%dT%H:%M:%S%z"], - OFInvalidFormatException); -} - -- (void)testIsEqual -{ - OTAssertEqualObjects(_date[0], - [OFDate dateWithTimeIntervalSince1970: 0]); - - OTAssertNotEqualObjects(_date[0], - [OFDate dateWithTimeIntervalSince1970: 0.0000001]); -} - -- (void)testCompare -{ - OTAssertEqual([_date[0] compare: _date[1]], OFOrderedAscending); -} - -- (void)testSecond -{ - OTAssertEqual(_date[0].second, 0); - OTAssertEqual(_date[1].second, 5); -} - -- (void)testMicrosecond -{ - OTAssertEqual(_date[0].microsecond, 0); - OTAssertEqual(_date[1].microsecond, 2); -} - -- (void)testMinute -{ - OTAssertEqual(_date[0].minute, 0); - OTAssertEqual(_date[1].minute, 0); -} - -- (void)testHour -{ - OTAssertEqual(_date[0].hour, 0); - OTAssertEqual(_date[1].hour, 1); -} - -- (void)testDayOfMonth -{ - OTAssertEqual(_date[0].dayOfMonth, 1); - OTAssertEqual(_date[1].dayOfMonth, 2); -} - -- (void)testMonthOfYear -{ - OTAssertEqual(_date[0].monthOfYear, 1); - OTAssertEqual(_date[1].monthOfYear, 1); -} - -- (void)testYear -{ - OTAssertEqual(_date[0].year, 1970); - OTAssertEqual(_date[1].year, 1970); -} - -- (void)testDayOfWeek -{ - OTAssertEqual(_date[0].dayOfWeek, 4); - OTAssertEqual(_date[1].dayOfWeek, 5); -} - -- (void)testDayOfYear -{ - OTAssertEqual(_date[0].dayOfYear, 1); - OTAssertEqual(_date[1].dayOfYear, 2); -} - -- (void)testEarlierDate -{ - OTAssertEqualObjects([_date[0] earlierDate: _date[1]], _date[0]); -} - -- (void)testLaterDate -{ - OTAssertEqualObjects([_date[0] laterDate: _date[1]], _date[1]); -} -@end DELETED new_tests/OFDictionaryTests.h Index: new_tests/OFDictionaryTests.h ================================================================== --- new_tests/OFDictionaryTests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFDictionaryTests: OTTestCase -{ - OFDictionary *_dictionary; -} - -@property (readonly, nonatomic) Class dictionaryClass; -@end DELETED new_tests/OFDictionaryTests.m Index: new_tests/OFDictionaryTests.m ================================================================== --- new_tests/OFDictionaryTests.m +++ /dev/null @@ -1,295 +0,0 @@ -/* - * 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 "OFDictionaryTests.h" - -static OFString *keys[] = { - @"key1", - @"key2" -}; -static OFString *objects[] = { - @"value1", - @"value2" -}; - -@interface CustomDictionary: OFDictionary -{ - OFDictionary *_dictionary; -} -@end - -@implementation OFDictionaryTests -- (Class)dictionaryClass -{ - return [CustomDictionary class]; -} - -- (void)setUp -{ - [super setUp]; - - _dictionary = [[self.dictionaryClass alloc] initWithObjects: objects - forKeys: keys - count: 2]; -} - -- (void)dealloc -{ - [_dictionary release]; - - [super dealloc]; -} - -- (void)testObjectForKey -{ - OTAssertEqualObjects([_dictionary objectForKey: keys[0]], objects[0]); - OTAssertEqualObjects([_dictionary objectForKey: keys[1]], objects[1]); -} - -- (void)testCount -{ - OTAssertEqual(_dictionary.count, 2); -} - -- (void)testIsEqual -{ - OTAssertEqualObjects(_dictionary, - [OFDictionary dictionaryWithObjects: objects - forKeys: keys - count: 2]); - OTAssertNotEqualObjects(_dictionary, - [OFDictionary dictionaryWithObjects: keys - forKeys: objects - count: 2]); -} - -- (void)testHash -{ - OTAssertEqual(_dictionary.hash, - [[OFDictionary dictionaryWithObjects: objects - forKeys: keys - count: 2] hash]); - OTAssertNotEqual(_dictionary.hash, - [[OFDictionary dictionaryWithObject: objects[0] - forKey: keys[0]] hash]); -} - -- (void)testCopy -{ - OTAssertEqualObjects([[_dictionary copy] autorelease], _dictionary); -} - -- (void)testValueForKey -{ - OTAssertEqualObjects([_dictionary valueForKey: keys[0]], objects[0]); - OTAssertEqualObjects([_dictionary valueForKey: keys[1]], objects[1]); - OTAssertEqualObjects( - [_dictionary valueForKey: @"@count"], [OFNumber numberWithInt: 2]); -} - -- (void)testSetValueForKey -{ - OTAssertThrowsSpecific([_dictionary setValue: @"x" forKey: @"x"], - OFUndefinedKeyException); -} - -- (void)testContainsObject -{ - OTAssertTrue([_dictionary containsObject: objects[0]]); - OTAssertFalse([_dictionary containsObject: @"nonexistent"]); -} - -- (void)testContainsObjectIdenticalTo -{ - OTAssertTrue([_dictionary containsObjectIdenticalTo: objects[0]]); - OTAssertFalse([_dictionary containsObjectIdenticalTo: - [[objects[0] mutableCopy] autorelease]]); -} - -- (void)testDescription -{ - OTAssert( - [_dictionary.description isEqual: - @"{\n\tkey1 = value1;\n\tkey2 = value2;\n}"] || - [_dictionary.description isEqual: - @"{\n\tkey2 = value2;\n\tkey1 = value1;\n}"]); -} - -- (void)testAllKeys -{ - OTAssert( - [_dictionary.allKeys isEqual: - ([OFArray arrayWithObjects: keys[0], keys[1], nil])] || - [_dictionary.allKeys isEqual: - ([OFArray arrayWithObjects: keys[1], keys[0], nil])]); -} - -- (void)testAllObjects -{ - OTAssert( - [_dictionary.allObjects isEqual: - ([OFArray arrayWithObjects: objects[0], objects[1], nil])] || - [_dictionary.allObjects isEqual: - ([OFArray arrayWithObjects: objects[1], objects[0], nil])]); -} - -- (void)testKeyEnumerator -{ - OFEnumerator *enumerator = [_dictionary keyEnumerator]; - OFString *first, *second; - - first = [enumerator nextObject]; - second = [enumerator nextObject]; - OTAssertNil([enumerator nextObject]); - - OTAssert( - ([first isEqual: keys[0]] && [second isEqual: keys[1]]) || - ([first isEqual: keys[1]] && [second isEqual: keys[0]])); -} - -- (void)testObjectEnumerator -{ - OFEnumerator *enumerator = [_dictionary objectEnumerator]; - OFString *first, *second; - - first = [enumerator nextObject]; - second = [enumerator nextObject]; - OTAssertNil([enumerator nextObject]); - - OTAssert( - ([first isEqual: objects[0]] && [second isEqual: objects[1]]) || - ([first isEqual: objects[1]] && [second isEqual: objects[0]])); -} - -- (void)testFastEnumeration -{ - size_t i = 0; - OFString *first = nil, *second = nil; - - for (OFString *key in _dictionary) { - OTAssertLessThan(i, 2); - - switch (i++) { - case 0: - first = key; - break; - case 1: - second = key; - break; - } - } - - OTAssertEqual(i, 2); - OTAssert( - ([first isEqual: keys[0]] && [second isEqual: keys[1]]) || - ([first isEqual: keys[1]] && [second isEqual: keys[0]])); -} - -#ifdef OF_HAVE_BLOCKS -- (void)testEnumerateKeysAndObjectsUsingBlock -{ - __block size_t i = 0; - __block OFString *first = nil, *second = nil; - - [_dictionary enumerateKeysAndObjectsUsingBlock: - ^ (id key, id object, bool *stop) { - OTAssertLessThan(i, 2); - - switch (i++) { - case 0: - first = key; - break; - case 1: - second = key; - break; - } - }]; - - OTAssertEqual(i, 2); - OTAssert( - ([first isEqual: keys[0]] && [second isEqual: keys[1]]) || - ([first isEqual: keys[1]] && [second isEqual: keys[0]])); -} - -- (void)testMappedDictionaryUsingBlock -{ - OTAssertEqualObjects([_dictionary mappedDictionaryUsingBlock: - ^ id (id key, id object) { - if ([key isEqual: keys[0]]) - return @"val1"; - if ([key isEqual: keys[1]]) - return @"val2"; - - return nil; - }], - ([OFDictionary dictionaryWithKeysAndObjects: - @"key1", @"val1", @"key2", @"val2", nil])); -} - -- (void)testFilteredDictionaryUsingBlock -{ - OTAssertEqualObjects([_dictionary filteredDictionaryUsingBlock: - ^ bool (id key, id object) { - return [key isEqual: keys[0]]; - }], - [OFDictionary dictionaryWithObject: objects[0] - forKey: keys[0]]); -} -#endif -@end - -@implementation CustomDictionary -- (instancetype)initWithObjects: (const id *)objects_ - forKeys: (const id *)keys_ - count: (size_t)count -{ - self = [super init]; - - @try { - _dictionary = [[OFDictionary alloc] initWithObjects: objects_ - forKeys: keys_ - count: count]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_dictionary release]; - - [super dealloc]; -} - -- (id)objectForKey: (id)key -{ - return [_dictionary objectForKey: key]; -} - -- (size_t)count -{ - return _dictionary.count; -} - -- (OFEnumerator *)keyEnumerator -{ - return [_dictionary keyEnumerator]; -} -@end DELETED new_tests/OFHMACTests.m Index: new_tests/OFHMACTests.m ================================================================== --- new_tests/OFHMACTests.m +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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" - -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFHMACTests: OTTestCase -{ - OFStream *_stream; -} -@end - -static const uint8_t key[] = - "yM9h8K6IWnJRvxC/0F8XRWG7RnACDBz8wqK2tbXrYVLoKC3vPLeJikyJSM47tVHc" - "DlXHww9zULAC2sJUlm2Kg1z4oz2aXY3Y1PQSB4VkC/m0DQ7hCI6cAg4TWnKdzWTy" - "cvYGX+Y6HWeDY79/PGSd8fNItme6I8w4HDBqU7BP2sum3jbePJqoiSnhcyJZQTeZ" - "jw0ZXoyrfHgOYD2M+NsTDaGpLblFtQ7n5CczjKtafG40PkEwx1dcrd46U9i3GyTK"; -static const size_t keyLength = sizeof(key); -static const uint8_t MD5Digest[] = - "\xCC\x1F\xEF\x09\x29\xA3\x25\x1A\x06\xA9\x83\x99\xF9\xBC\x8F\x42"; -static const uint8_t SHA1Digest[] = - "\x94\xB9\x0A\x6F\xFB\xA7\x13\x6A\x75\x55" - "\xD5\x7F\x5D\xB7\xF4\xCA\xEB\x4A\xDE\xBF"; -static const uint8_t RIPEMD160Digest[] = - "\x2C\xE1\xED\x41\xC6\xF3\x51\xA8\x04\xD2" - "\xC3\x9B\x08\x33\x3B\xD5\xC9\x00\x39\x50"; -static const uint8_t SHA256Digest[] = - "\xFB\x8C\xDA\x88\xB3\x81\x32\x16\xD7\xD8\x62\xD4\xA6\x26\x9D\x77" - "\x01\x99\x62\x65\x29\x02\x41\xE6\xEF\xA1\x02\x31\xA8\x9D\x77\x5D"; -static const uint8_t SHA384Digest[] = - "\x2F\x4A\x47\xAE\x13\x8E\x96\x52\xF1\x8F\x05\xFD\x65\xCD\x9A\x97" - "\x93\x2F\xC9\x02\xD6\xC6\xAB\x2E\x15\x76\xC0\xA7\xA0\x05\xF4\xEF" - "\x14\x52\x33\x4B\x9C\x5F\xD8\x07\x4E\x98\xAE\x97\x46\x29\x24\xB4"; -static const uint8_t SHA512Digest[] = - "\xF5\x8C\x3F\x9C\xA2\x2F\x0A\xF3\x26\xD8\xC0\x7E\x20\x63\x88\x61" - "\xC9\xE1\x1F\xD7\xC7\xE5\x59\x33\xD5\x2F\xAF\x56\x1C\x94\xC8\xA4" - "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E" - "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99"; - -@implementation OFHMACTests -- (void)setUp -{ - OFIRI *IRI; - - [super setUp]; - - IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; - _stream = [[OFIRIHandler openItemAtIRI: IRI mode: @"r"] retain]; -} - -- (void)tearDown -{ - [_stream close]; - - [super tearDown]; -} - -- (void)dealloc -{ - [_stream release]; - - [super dealloc]; -} - -- (void)testWithHashClass: (Class)hashClass - expectedDigest: (const unsigned char *)expectedDigest -{ - OFHMAC *HMAC = [OFHMAC HMACWithHashClass: hashClass - allowsSwappableMemory: true]; - - OTAssertNotNil(HMAC); - - OTAssertThrowsSpecific([HMAC updateWithBuffer: "" length: 0], - OFInvalidArgumentException); - - [HMAC setKey: key length: keyLength]; - - while (!_stream.atEndOfStream) { - char buffer[64]; - size_t length = [_stream readIntoBuffer: buffer length: 64]; - [HMAC updateWithBuffer: buffer length: length]; - } - - [HMAC calculate]; - - OTAssertEqual(memcmp(HMAC.digest, expectedDigest, HMAC.digestSize), 0); -} - -- (void)testHMACWithMD5 -{ - [self testWithHashClass: [OFMD5Hash class] expectedDigest: MD5Digest]; -} - -- (void)testHMACWithRIPEMD160 -{ - [self testWithHashClass: [OFRIPEMD160Hash class] - expectedDigest: RIPEMD160Digest]; -} - -- (void)testHMACWithSHA1 -{ - [self testWithHashClass: [OFSHA1Hash class] expectedDigest: SHA1Digest]; -} - -- (void)testHMACWithSHA256 -{ - [self testWithHashClass: [OFSHA256Hash class] - expectedDigest: SHA256Digest]; -} - -- (void)testHMACWithSHA384 -{ - [self testWithHashClass: [OFSHA384Hash class] - expectedDigest: SHA384Digest]; -} - -- (void)testHMACWithSHA512 -{ - [self testWithHashClass: [OFSHA512Hash class] - expectedDigest: SHA512Digest]; -} -@end DELETED new_tests/OFHTTPClientTests.m Index: new_tests/OFHTTPClientTests.m ================================================================== --- new_tests/OFHTTPClientTests.m +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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" - -#include -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFHTTPClientTests: OTTestCase -{ - OFHTTPResponse *_response; -} -@end - -@interface HTTPClientTestsServer: OFThread -{ - OFCondition *_condition; - uint16_t _port; -} - -@property (readonly, nonatomic) OFCondition *condition; -@property (readonly) uint16_t port; -@end - -@implementation OFHTTPClientTests -- (void)dealloc -{ - [_response release]; - - [super dealloc]; -} - -- (void)client: (OFHTTPClient *)client - wantsRequestBody: (OFStream *)body - request: (OFHTTPRequest *)request -{ - [body writeString: @"Hello"]; -} - -- (void)client: (OFHTTPClient *)client - didPerformRequest: (OFHTTPRequest *)request - response: (OFHTTPResponse *)response_ - exception: (id)exception -{ - OTAssertNil(exception); - - [_response release]; - _response = [response_ retain]; - - [[OFRunLoop mainRunLoop] stop]; -} - -- (void)testClient -{ - HTTPClientTestsServer *server; - OFIRI *IRI; - OFHTTPRequest *request; - OFHTTPClient *client; - OFData *data; - - server = [[[HTTPClientTestsServer alloc] init] autorelease]; - server.supportsSockets = true; - - [server.condition lock]; - - [server start]; - - [server.condition wait]; - [server.condition unlock]; - - IRI = [OFIRI IRIWithString: - [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo", - server.port]]; - - request = [OFHTTPRequest requestWithIRI: IRI]; - request.headers = [OFDictionary - dictionaryWithObject: @"5" - forKey: @"Content-Length"]; - - client = [OFHTTPClient client]; - client.delegate = self; - [client asyncPerformRequest: request]; - - [[OFRunLoop mainRunLoop] runUntilDate: - [OFDate dateWithTimeIntervalSinceNow: 2]]; - - OTAssertNotNil(_response); - OTAssertNotNil([_response.headers objectForKey: @"Content-Length"]); - - data = [_response readDataUntilEndOfStream]; - OTAssertEqual(data.count, 7); - OTAssertEqual(data.itemSize, 1); - OTAssertEqual(memcmp(data.items, "foo\nbar", 7), 0); - - OTAssertNil([server join]); -} -@end - -@implementation HTTPClientTestsServer -@synthesize condition = _condition, port = _port; - -- (instancetype)init -{ - self = [super init]; - - @try { - _condition = [[OFCondition alloc] init]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_condition release]; - - [super dealloc]; -} - -- (id)main -{ - OFTCPSocket *listener, *client; - OFSocketAddress address; - bool sawHost = false, sawContentLength = false, sawContentType = false; - bool sawUserAgent = false; - char buffer[5]; - - [_condition lock]; - - listener = [OFTCPSocket socket]; - address = [listener bindToHost: @"127.0.0.1" port: 0]; - _port = OFSocketAddressIPPort(&address); - [listener listen]; - - [_condition signal]; - [_condition unlock]; - client = [listener accept]; - - if (![[client readLine] isEqual: @"GET /foo HTTP/1.1"]) - return @"Wrong request"; - - for (size_t i = 0; i < 4; i++) { - OFString *line = [client readLine]; - - if ([line isEqual: [OFString stringWithFormat: - @"Host: 127.0.0.1:%" @PRIu16, _port]]) - sawHost = true; - else if ([line isEqual: @"Content-Length: 5"]) - sawContentLength = true; - if ([line isEqual: @"Content-Type: application/" - @"x-www-form-urlencoded; charset=UTF-8"]) - sawContentType = true; - else if ([line hasPrefix: @"User-Agent:"]) - sawUserAgent = true; - } - - if (!sawHost) - return @"Missing host"; - if (!sawContentLength) - return @"Missing content length"; - if (!sawContentType) - return @"Missing content type"; - if (!sawUserAgent) - return @"Missing user agent"; - - if (![[client readLine] isEqual: @""]) - return @"Missing empty line"; - - [client readIntoBuffer: buffer exactLength: 5]; - if (memcmp(buffer, "Hello", 5) != 0) - return @"Missing body"; - - [client writeString: @"HTTP/1.0 200 OK\r\n" - @"cONTeNT-lENgTH: 7\r\n" - @"\r\n" - @"foo\n" - @"bar"]; - [client close]; - - return nil; -} -@end DELETED new_tests/OFHTTPCookieManagerTests.m Index: new_tests/OFHTTPCookieManagerTests.m ================================================================== --- new_tests/OFHTTPCookieManagerTests.m +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFHTTPCookieManagerTests: OTTestCase -@end - -@implementation OFHTTPCookieManagerTests -- (void)testCookieManager -{ - OFHTTPCookieManager *manager = [OFHTTPCookieManager manager]; - OFIRI *IRI1, *IRI2, *IRI3, *IRI4; - OFHTTPCookie *cookie1, *cookie2, *cookie3, *cookie4, *cookie5; - - IRI1 = [OFIRI IRIWithString: @"http://nil.im/foo"]; - IRI2 = [OFIRI IRIWithString: @"https://nil.im/foo/bar"]; - IRI3 = [OFIRI IRIWithString: @"https://test.nil.im/foo/bar"]; - IRI4 = [OFIRI IRIWithString: @"http://webkeks.org/foo/bar"]; - - cookie1 = [OFHTTPCookie cookieWithName: @"test" - value: @"1" - domain: @"nil.im"]; - [manager addCookie: cookie1 forIRI: IRI1]; - OTAssertEqualObjects([manager cookiesForIRI: IRI1], - [OFArray arrayWithObject: cookie1]); - - cookie2 = [OFHTTPCookie cookieWithName: @"test" - value: @"2" - domain: @"webkeks.org"]; - [manager addCookie: cookie2 forIRI: IRI1]; - OTAssertEqualObjects([manager cookiesForIRI: IRI1], - [OFArray arrayWithObject: cookie1]); - OTAssertEqualObjects([manager cookiesForIRI: IRI4], [OFArray array]); - - cookie3 = [OFHTTPCookie cookieWithName: @"test" - value: @"3" - domain: @"nil.im"]; - cookie3.secure = true; - [manager addCookie: cookie3 forIRI: IRI2]; - OTAssertEqualObjects([manager cookiesForIRI: IRI2], - [OFArray arrayWithObject: cookie3]); - OTAssertEqualObjects([manager cookiesForIRI: IRI1], [OFArray array]); - - cookie3.expires = [OFDate dateWithTimeIntervalSinceNow: -1]; - cookie4 = [OFHTTPCookie cookieWithName: @"test" - value: @"4" - domain: @"nil.im"]; - cookie4.domain = @".nil.im"; - [manager addCookie: cookie4 forIRI: IRI2]; - OTAssertEqualObjects([manager cookiesForIRI: IRI2], - [OFArray arrayWithObject: cookie4]); - OTAssertEqualObjects([manager cookiesForIRI: IRI3], - [OFArray arrayWithObject: cookie4]); - - cookie5 = [OFHTTPCookie cookieWithName: @"bar" - value: @"5" - domain: @"test.nil.im"]; - [manager addCookie: cookie5 forIRI: IRI1]; - OTAssertEqualObjects([manager cookiesForIRI: IRI1], - [OFArray arrayWithObject: cookie4]); - OTAssertEqualObjects([manager cookiesForIRI: IRI3], - ([OFArray arrayWithObjects: cookie4, cookie5, nil])); - - OTAssertEqualObjects(manager.cookies, - ([OFArray arrayWithObjects: cookie3, cookie4, cookie5, nil])); - [manager purgeExpiredCookies]; - OTAssertEqualObjects(manager.cookies, - ([OFArray arrayWithObjects: cookie4, cookie5, nil])); -} -@end DELETED new_tests/OFHTTPCookieTests.m Index: new_tests/OFHTTPCookieTests.m ================================================================== --- new_tests/OFHTTPCookieTests.m +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFHTTPCookieTests: OTTestCase -@end - -@implementation OFHTTPCookieTests -- (void)testCookiesWithResponseHeaderFieldsForIRI -{ - OFIRI *IRI = [OFIRI IRIWithString: @"http://nil.im"]; - OFHTTPCookie *cookie1 = [OFHTTPCookie cookieWithName: @"foo" - value: @"bar" - domain: @"nil.im"]; - OFHTTPCookie *cookie2 = [OFHTTPCookie cookieWithName: @"qux" - value: @"cookie" - domain: @"nil.im"]; - OFDictionary *headers; - - headers = [OFDictionary dictionaryWithObject: @"foo=bar" - forKey: @"Set-Cookie"]; - OTAssertEqualObjects( - [OFHTTPCookie cookiesWithResponseHeaderFields: headers forIRI: IRI], - [OFArray arrayWithObject: cookie1]); - - headers = [OFDictionary dictionaryWithObject: @"foo=bar,qux=cookie" - forKey: @"Set-Cookie"]; - OTAssertEqualObjects( - [OFHTTPCookie cookiesWithResponseHeaderFields: headers forIRI: IRI], - ([OFArray arrayWithObjects: cookie1, cookie2, nil])); - - cookie1.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890]; - cookie2.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890]; - cookie1.path = @"/x"; - cookie2.domain = @"webkeks.org"; - cookie2.path = @"/objfw"; - cookie2.secure = true; - cookie2.HTTPOnly = true; - [cookie2.extensions addObject: @"foo"]; - [cookie2.extensions addObject: @"bar"]; - - headers = [OFDictionary - dictionaryWithObject: @"foo=bar; " - @"Expires=Fri, 13 Feb 2009 23:31:30 GMT; " - @"Path=/x," - @"qux=cookie; " - @"Expires=Fri, 13 Feb 2009 23:31:30 GMT; " - @"Domain=webkeks.org; " - @"Path=/objfw; " - @"Secure; " - @"HTTPOnly; " - @"foo; " - @"bar" - forKey: @"Set-Cookie"]; - OTAssertEqualObjects( - [OFHTTPCookie cookiesWithResponseHeaderFields: headers forIRI: IRI], - ([OFArray arrayWithObjects: cookie1, cookie2, nil])); -} - -- (void)testRequestHeaderFieldsWithCookies -{ - OFHTTPCookie *cookie1 = [OFHTTPCookie cookieWithName: @"foo" - value: @"bar" - domain: @"nil.im"]; - OFHTTPCookie *cookie2 = [OFHTTPCookie cookieWithName: @"qux" - value: @"cookie" - domain: @"nil.im"]; - - OTAssertEqualObjects([OFHTTPCookie requestHeaderFieldsWithCookies: - ([OFArray arrayWithObjects: cookie1, cookie2, nil])], - [OFDictionary dictionaryWithObject: @"foo=bar; qux=cookie" - forKey: @"Cookie"]); -} -@end DELETED new_tests/OFINIFileTests.m Index: new_tests/OFINIFileTests.m ================================================================== --- new_tests/OFINIFileTests.m +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFINIFileTests: OTTestCase -{ - OFINIFile *_file; -} -@end - -@implementation OFINIFileTests -- (void)setUp -{ - OFIRI *IRI; - - [super setUp]; - - IRI = [OFIRI IRIWithString: @"embedded:testfile.ini"]; - _file = [[OFINIFile alloc] initWithIRI: IRI - encoding: OFStringEncodingISO8859_1]; -} - -- (void)dealloc -{ - [_file release]; - - [super dealloc]; -} - -- (void)testCategoryForName -{ - OTAssertNotNil([_file categoryForName: @"tests"]); - OTAssertNotNil([_file categoryForName: @"foobar"]); - OTAssertNotNil([_file categoryForName: @"types"]); -} - -- (void)testStringValueForKey -{ - OTAssertEqualObjects( - [[_file categoryForName: @"tests"] stringValueForKey: @"foo"], - @"bar"); - - OTAssertEqualObjects([[_file categoryForName: @"foobar"] - stringValueForKey: @"quxquxqux"], - @"hello\"wörld"); -} - -- (void)testLongLongValueForKeyDefaultValue -{ - OTAssertEqual([[_file categoryForName: @"types"] - longLongValueForKey: @"integer" - defaultValue: 2], - 0x20); -} - -- (void)testBoolValueForKeyDefaultValue -{ - OTAssertTrue([[_file categoryForName: @"types"] - boolValueForKey: @"bool" - defaultValue: false]); -} - -- (void)testFloatValueForKeyDefaultValue -{ - OTAssertEqual([[_file categoryForName: @"types"] - floatValueForKey: @"float" - defaultValue: 1], - 0.5f); -} - -- (void)testDoubleValueForKeyDefaultValue -{ - OTAssertEqual([[_file categoryForName: @"types"] - doubleValueForKey: @"double" - defaultValue: 3], - 0.25); -} - -- (void)testArrayValueForKey -{ - OFINICategory *types = [_file categoryForName: @"types"]; - OFArray *array = [OFArray arrayWithObjects: @"1", @"2", nil]; - - OTAssertEqualObjects([types arrayValueForKey: @"array1"], array); - OTAssertEqualObjects([types arrayValueForKey: @"array2"], array); - OTAssertEqualObjects([types arrayValueForKey: @"array3"], - [OFArray array]); -} - -- (void)testWriteToIRIEncoding -{ - OFString *expectedOutput = @"[tests]\r\n" - @"foo=baz\r\n" - @"foobar=baz\r\n" - @";comment\r\n" - @"new=new\r\n" - @"\r\n" - @"[foobar]\r\n" - @";foobarcomment\r\n" - @"qux=\" asd\"\r\n" - @"quxquxqux=\"hello\\\"wörld\"\r\n" - @"qux2=\"a\\f\"\r\n" - @"qux3=a\fb\r\n" - @"\r\n" - @"[types]\r\n" - @"integer=16\r\n" - @"bool=false\r\n" - @"float=0.25\r\n" - @"array1=foo\r\n" - @"array1=bar\r\n" - @"double=0.75\r\n"; - OFINICategory *tests = [_file categoryForName: @"tests"]; - OFINICategory *foobar = [_file categoryForName: @"foobar"]; - OFINICategory *types = [_file categoryForName: @"types"]; - OFArray *array = [OFArray arrayWithObjects: @"foo", @"bar", nil]; -#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS) - OFIRI *writeIRI; -#endif - - [tests setStringValue: @"baz" forKey: @"foo"]; - [tests setStringValue: @"new" forKey: @"new"]; - [foobar setStringValue: @"a\fb" forKey: @"qux3"]; - [types setLongLongValue: 0x10 forKey: @"integer"]; - [types setBoolValue: false forKey: @"bool"]; - [types setFloatValue: 0.25f forKey: @"float"]; - [types setDoubleValue: 0.75 forKey: @"double"]; - [types setArrayValue: array forKey: @"array1"]; - - [foobar removeValueForKey: @"quxqux "]; - [types removeValueForKey: @"array2"]; - - /* FIXME: Find a way to write files on Nintendo DS */ -#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS) - writeIRI = [OFSystemInfo temporaryDirectoryIRI]; - if (writeIRI == nil) - writeIRI = [[OFFileManager defaultManager] currentDirectoryIRI]; - writeIRI = [writeIRI IRIByAppendingPathComponent: @"objfw-tests.ini" - isDirectory: false]; - - [_file writeToIRI: writeIRI - encoding: OFStringEncodingISO8859_1]; - - @try { - OTAssertEqualObjects([OFString - stringWithContentsOfIRI: writeIRI - encoding: OFStringEncodingISO8859_1], - expectedOutput); - } @finally { - [[OFFileManager defaultManager] removeItemAtIRI: writeIRI]; - } -#else - (void)expectedOutput; -#endif -} -@end DELETED new_tests/OFIPXSocketTests.m Index: new_tests/OFIPXSocketTests.m ================================================================== --- new_tests/OFIPXSocketTests.m +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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" - -#include -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFIPXSocketTests: OTTestCase -@end - -@implementation OFIPXSocketTests -- (void)testIPXSocket -{ - OFIPXSocket *sock = [OFIPXSocket socket]; - const unsigned char zeroNode[IPX_NODE_LEN] = { 0 }; - OFSocketAddress address1, address2; - OFDictionary *networkInterfaces; - char buffer[5]; - unsigned char node1[IPX_NODE_LEN], node2[IPX_NODE_LEN]; - unsigned char node[IPX_NODE_LEN]; - - @try { - address1 = [sock bindToNetwork: 0 - node: zeroNode - port: 0 - packetType: 0]; - } @catch (OFBindSocketFailedException *e) { - switch (e.errNo) { - case EAFNOSUPPORT: - OTSkip(@"IPX unsupported"); - case EADDRNOTAVAIL: - OTSkip(@"IPX not configured"); - default: - @throw e; - } - } - - /* - * Find any network interface with IPX and send to it. Any should be - * fine since we bound to 0.0. - */ - networkInterfaces = [OFSystemInfo networkInterfaces]; - for (OFString *name in networkInterfaces) { - OFNetworkInterface interface = [networkInterfaces - objectForKey: name]; - OFData *addresses = [interface - objectForKey: OFNetworkInterfaceIPXAddresses]; - - if (addresses.count == 0) - continue; - - OFSocketAddressSetIPXNetwork(&address1, - OFSocketAddressIPXNetwork([addresses itemAtIndex: 0])); - OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); - OFSocketAddressSetIPXNode(&address1, node); - } - - OFSocketAddressGetIPXNode(&address1, node); - if (OFSocketAddressIPXNetwork(&address1) == 0 && - memcmp(node, zeroNode, 6) == 0) - OTSkip(@"Could not determine own IPX address"); - - [sock sendBuffer: "Hello" length: 5 receiver: &address1]; - - OTAssertEqual([sock receiveIntoBuffer: buffer - length: 5 - sender: &address2], 5); - OTAssertEqual(memcmp(buffer, "Hello", 5), 0); - OFSocketAddressGetIPXNode(&address1, node1); - OFSocketAddressGetIPXNode(&address2, node2); - OTAssertEqual(memcmp(node1, node2, IPX_NODE_LEN), 0); - OTAssertEqual(OFSocketAddressIPXPort(&address1), - OFSocketAddressIPXPort(&address2)); -} -@end DELETED new_tests/OFIRITests.m Index: new_tests/OFIRITests.m ================================================================== --- new_tests/OFIRITests.m +++ /dev/null @@ -1,539 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFIRITests: OTTestCase -{ - OFIRI *_IRI[11]; - OFMutableIRI *_mutableIRI; -} -@end - -static OFString *IRI0String = @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/" - @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment"; - -@implementation OFIRITests -- (void)setUp -{ - [super setUp]; - - _IRI[0] = [[OFIRI alloc] initWithString: IRI0String]; - _IRI[1] = [[OFIRI alloc] initWithString: @"http://foo:80"]; - _IRI[2] = [[OFIRI alloc] initWithString: @"http://bar/"]; - _IRI[3] = [[OFIRI alloc] initWithString: @"file:///etc/passwd"]; - _IRI[4] = [[OFIRI alloc] - initWithString: @"http://foo/bar/qux/foo%2fbar"]; - _IRI[5] = [[OFIRI alloc] initWithString: @"https://[12:34::56:abcd]/"]; - _IRI[6] = [[OFIRI alloc] - initWithString: @"https://[12:34::56:abcd]:234/"]; - _IRI[7] = [[OFIRI alloc] initWithString: @"urn:qux:foo"]; - _IRI[8] = [[OFIRI alloc] initWithString: @"file:/foo?query#frag"]; - _IRI[9] = [[OFIRI alloc] - initWithString: @"file:foo@bar/qux?query#frag"]; - _IRI[10] = [[OFIRI alloc] initWithString: @"http://ä/ö?ü"]; - - _mutableIRI = [[OFMutableIRI alloc] initWithScheme: @"dummy"]; -} - -- (void)dealloc -{ - for (uint_fast8_t i = 0; i < 11; i++) - [_IRI[i] release]; - - [_mutableIRI release]; - - [super dealloc]; -} - -- (void)testIRIWithStringFailsWithInvalidCharacters -{ - OTAssertThrowsSpecific([OFIRI IRIWithString: @"ht,tp://foo"], - OFInvalidFormatException); - - OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://f`oo"], - OFInvalidFormatException); - - OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://foo/`"], - OFInvalidFormatException); - - OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://foo/foo?`"], - OFInvalidFormatException); - - OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://foo/foo?foo#`"], - OFInvalidFormatException); - - OTAssertThrowsSpecific([OFIRI IRIWithString: @"https://[g]/"], - OFInvalidFormatException); - - OTAssertThrowsSpecific([OFIRI IRIWithString: @"https://[f]:/"], - OFInvalidFormatException); - - OTAssertThrowsSpecific([OFIRI IRIWithString: @"https://[f]:f/"], - OFInvalidFormatException); - - OTAssertThrowsSpecific([OFIRI IRIWithString: @"foo:"], - OFInvalidFormatException); -} - -- (void)testIRIWithStringRelativeToIRI -{ - OTAssertEqualObjects([[OFIRI IRIWithString: @"/foo" - relativeToIRI: _IRI[0]] string], - @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/foo"); - - OTAssertEqualObjects( - [[OFIRI IRIWithString: @"foo/bar?q" - relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/quux"]] - string], - @"http://h/qux/foo/bar?q"); - - OTAssertEqualObjects( - [[OFIRI IRIWithString: @"foo/bar" - relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/?x"]] - string], - @"http://h/qux/foo/bar"); - - OTAssertEqualObjects([[OFIRI IRIWithString: @"http://foo/?q" - relativeToIRI: _IRI[0]] string], - @"http://foo/?q"); - - OTAssertEqualObjects( - [[OFIRI IRIWithString: @"foo" - relativeToIRI: [OFIRI IRIWithString: @"http://foo/bar"]] - string], - @"http://foo/foo"); - - OTAssertEqualObjects( - [[OFIRI IRIWithString: @"foo" - relativeToIRI: [OFIRI IRIWithString: @"http://foo"]] - string], - @"http://foo/foo"); -} - -- (void)testIRIWithStringRelativeToIRIFailsWithInvalidCharacters -{ - OTAssertThrowsSpecific( - [OFIRI IRIWithString: @"`" relativeToIRI: _IRI[0]], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [OFIRI IRIWithString: @"/`" relativeToIRI: _IRI[0]], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [OFIRI IRIWithString: @"?`" relativeToIRI: _IRI[0]], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [OFIRI IRIWithString: @"#`" relativeToIRI: _IRI[0]], - OFInvalidFormatException); -} - -#ifdef OF_HAVE_FILES -- (void)testFileIRIWithPath -{ - OTAssertEqualObjects( - [[OFIRI fileIRIWithPath: @"testfile.txt"] fileSystemRepresentation], - [[OFFileManager defaultManager].currentDirectoryPath - stringByAppendingPathComponent: @"testfile.txt"]); -} - -# if defined(OF_WINDOWS) || defined(OF_MSDOS) -- (void)testFileIRWithPathC -{ - OFIRI *IRI = [OFIRI fileIRIWithPath: @"c:\\"]; - OTAssertEqualObjects(IRI.string, @"file:/c:/"); - OTAssertEqualObjects(IRI.fileSystemRepresentation, @"c:\\"); -} -# endif - -# ifdef OF_WINDOWS -- (void)testFileIRIWithPathUNC -{ - OFIRI *IRI; - - IRI = [OFIRI fileIRIWithPath: @"\\\\foo\\bar" isDirectory: false]; - OTAssertEqualObjects(IRI.host, @"foo"); - OTAssertEqualObjects(IRI.path, @"/bar"); - OTAssertEqualObjects(IRI.string, @"file://foo/bar"); - OTAssertEqualObjects(IRI.fileSystemRepresentation, @"\\\\foo\\bar"); - - IRI = [OFIRI fileIRIWithPath: @"\\\\test" isDirectory: true]; - OTAssertEqualObjects(IRI.host, @"test"); - OTAssertEqualObjects(IRI.path, @"/"); - OTAssertEqualObjects(IRI.string, @"file://test/"); - OTAssertEqualObjects(IRI.fileSystemRepresentation, @"\\\\test"); -} -# endif -#endif - -- (void)testString -{ - OTAssertEqualObjects(_IRI[0].string, IRI0String); - OTAssertEqualObjects(_IRI[1].string, @"http://foo:80"); - OTAssertEqualObjects(_IRI[2].string, @"http://bar/"); - OTAssertEqualObjects(_IRI[3].string, @"file:///etc/passwd"); - OTAssertEqualObjects(_IRI[4].string, @"http://foo/bar/qux/foo%2fbar"); - OTAssertEqualObjects(_IRI[5].string, @"https://[12:34::56:abcd]/"); - OTAssertEqualObjects(_IRI[6].string, @"https://[12:34::56:abcd]:234/"); - OTAssertEqualObjects(_IRI[7].string, @"urn:qux:foo"); - OTAssertEqualObjects(_IRI[8].string, @"file:/foo?query#frag"); - OTAssertEqualObjects(_IRI[9].string, @"file:foo@bar/qux?query#frag"); - OTAssertEqualObjects(_IRI[10].string, @"http://ä/ö?ü"); -} - -- (void)testScheme -{ - OTAssertEqualObjects(_IRI[0].scheme, @"ht+tp"); - OTAssertEqualObjects(_IRI[3].scheme, @"file"); - OTAssertEqualObjects(_IRI[8].scheme, @"file"); - OTAssertEqualObjects(_IRI[9].scheme, @"file"); - OTAssertEqualObjects(_IRI[10].scheme, @"http"); -} - -- (void)testUser -{ - OTAssertEqualObjects(_IRI[0].user, @"us:er"); - OTAssertNil(_IRI[3].user); - OTAssertNil(_IRI[9].user); - OTAssertNil(_IRI[10].user); -} - -- (void)testPassword -{ - OTAssertEqualObjects(_IRI[0].password, @"p@w"); - OTAssertNil(_IRI[3].password); - OTAssertNil(_IRI[9].password); - OTAssertNil(_IRI[10].password); -} - -- (void)testHost -{ - OTAssertEqualObjects(_IRI[0].host, @"ho:st"); - OTAssertEqualObjects(_IRI[5].host, @"12:34::56:abcd"); - OTAssertEqualObjects(_IRI[6].host, @"12:34::56:abcd"); - OTAssertNil(_IRI[7].host); - OTAssertNil(_IRI[8].host); - OTAssertNil(_IRI[9].host); - OTAssertEqualObjects(_IRI[10].host, @"ä"); -} - -- (void)testPort -{ - OTAssertEqual(_IRI[0].port.unsignedShortValue, 1234); - OTAssertNil(_IRI[3].port); - OTAssertEqual(_IRI[6].port.unsignedShortValue, 234); - OTAssertNil(_IRI[7].port); - OTAssertNil(_IRI[8].port); - OTAssertNil(_IRI[9].port); - OTAssertNil(_IRI[10].port); -} - -- (void)testPath -{ - OTAssertEqualObjects(_IRI[0].path, @"/pa?th"); - OTAssertEqualObjects(_IRI[3].path, @"/etc/passwd"); - OTAssertEqualObjects(_IRI[7].path, @"qux:foo"); - OTAssertEqualObjects(_IRI[8].path, @"/foo"); - OTAssertEqualObjects(_IRI[9].path, @"foo@bar/qux"); - OTAssertEqualObjects(_IRI[10].path, @"/ö"); -} - -- (void)testPathComponents -{ - OTAssertEqualObjects(_IRI[0].pathComponents, - ([OFArray arrayWithObjects: @"/", @"pa?th", nil])); - - OTAssertEqualObjects(_IRI[3].pathComponents, - ([OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil])); - - OTAssertEqualObjects(_IRI[4].pathComponents, - ([OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", - nil])); -} - -- (void)testLastPathComponent -{ - OTAssertEqualObjects([[OFIRI IRIWithString: @"http://host/foo//bar/baz"] - lastPathComponent], - @"baz"); - - OTAssertEqualObjects( - [[OFIRI IRIWithString: @"http://host/foo//bar/baz/"] - lastPathComponent], - @"baz"); - - OTAssertEqualObjects([[OFIRI IRIWithString: @"http://host/foo/"] - lastPathComponent], - @"foo"); - - OTAssertEqualObjects([[OFIRI IRIWithString: @"http://host/"] - lastPathComponent], - @"/"); - - OTAssertEqualObjects(_IRI[4].lastPathComponent, @"foo/bar"); -} - -- (void)testQuery -{ - OTAssertEqualObjects(_IRI[0].query, @"que#ry=1&f&oo=b=ar"); - OTAssertNil(_IRI[3].query); - OTAssertEqualObjects(_IRI[8].query, @"query"); - OTAssertEqualObjects(_IRI[9].query, @"query"); - OTAssertEqualObjects(_IRI[10].query, @"ü"); -} - -- (void)testQueryItems -{ - OTAssertEqualObjects(_IRI[0].queryItems, - ([OFArray arrayWithObjects: - [OFPair pairWithFirstObject: @"que#ry" secondObject: @"1"], - [OFPair pairWithFirstObject: @"f&oo" secondObject: @"b=ar"], nil])); -} - -- (void)testFragment -{ - OTAssertEqualObjects(_IRI[0].fragment, @"frag#ment"); - OTAssertNil(_IRI[3].fragment); - OTAssertEqualObjects(_IRI[8].fragment, @"frag"); - OTAssertEqualObjects(_IRI[9].fragment, @"frag"); -} - -- (void)testCopy -{ - OTAssertEqualObjects([[_IRI[0] copy] autorelease], _IRI[0]); -} - -- (void)testIsEqual -{ - OTAssertEqualObjects(_IRI[0], [OFIRI IRIWithString: IRI0String]); - OTAssertNotEqualObjects(_IRI[1], _IRI[2]); - OTAssertEqualObjects([OFIRI IRIWithString: @"HTTP://bar/"], _IRI[2]); -} - -- (void)testHash -{ - OTAssertEqual(_IRI[0].hash, [[OFIRI IRIWithString: IRI0String] hash]); - OTAssertNotEqual(_IRI[1].hash, _IRI[2].hash); -} - -- (void)testIRIWithStringFailsWithInvalidFormat -{ - OTAssertThrowsSpecific([OFIRI IRIWithString: @"http"], - OFInvalidFormatException); -} - -- (void)testIRIByAddingPercentEncodingForUnicodeCharacters -{ - OTAssertEqualObjects( - _IRI[10].IRIByAddingPercentEncodingForUnicodeCharacters, - [OFIRI IRIWithString: @"http://%C3%A4/%C3%B6?%C3%BC"]); -} - -- (void)testSetPercentEncodedSchemeFailsWithInvalidCharacters -{ - OTAssertThrowsSpecific(_mutableIRI.scheme = @"%20", - OFInvalidFormatException); -} - -- (void)testSetHost -{ - _mutableIRI.host = @"ho:st"; - OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"ho%3Ast"); - - _mutableIRI.host = @"12:34:ab"; - OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"[12:34:ab]"); - - _mutableIRI.host = @"12:34:aB"; - OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"[12:34:aB]"); - - _mutableIRI.host = @"12:34:g"; - OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"12%3A34%3Ag"); -} - -- (void)testSetPercentEncodedHost -{ - _mutableIRI.percentEncodedHost = @"ho%3Ast"; - OTAssertEqualObjects(_mutableIRI.host, @"ho:st"); - - _mutableIRI.percentEncodedHost = @"[12:34]"; - OTAssertEqualObjects(_mutableIRI.host, @"12:34"); - - _mutableIRI.percentEncodedHost = @"[12::ab]"; - OTAssertEqualObjects(_mutableIRI.host, @"12::ab"); -} - -- (void)testSetPercentEncodedHostFailsWithInvalidCharacters -{ - OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"/", - OFInvalidFormatException); - - OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"[12:34", - OFInvalidFormatException); - - OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"[a::g]", - OFInvalidFormatException); -} - -- (void)testSetUser -{ - _mutableIRI.user = @"us:er"; - OTAssertEqualObjects(_mutableIRI.percentEncodedUser, @"us%3Aer"); -} - -- (void)testSetPercentEncodedUser -{ - _mutableIRI.percentEncodedUser = @"us%3Aer"; - OTAssertEqualObjects(_mutableIRI.user, @"us:er"); -} - -- (void)testSetPercentEncodedUserFailsWithInvalidCharacters -{ - OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"/", - OFInvalidFormatException); -} - -- (void)testSetPassword -{ - _mutableIRI.password = @"pass:word"; - OTAssertEqualObjects(_mutableIRI.percentEncodedPassword, - @"pass%3Aword"); -} - -- (void)testSetPercentEncodedPassword -{ - _mutableIRI.percentEncodedPassword = @"pass%3Aword"; - OTAssertEqualObjects(_mutableIRI.password, @"pass:word"); -} - -- (void)testSetPercentEncodedPasswordFailsWithInvalidCharacters -{ - OTAssertThrowsSpecific(_mutableIRI.percentEncodedPassword = @"/", - OFInvalidFormatException); -} - -- (void)testSetPath -{ - _mutableIRI.path = @"pa/th@?"; - OTAssertEqualObjects(_mutableIRI.percentEncodedPath, @"pa/th@%3F"); -} - -- (void)testSetPercentEncodedPath -{ - _mutableIRI.percentEncodedPath = @"pa/th@%3F"; - OTAssertEqualObjects(_mutableIRI.path, @"pa/th@?"); -} - -- (void)testSetPercentEncodedPathFailsWithInvalidCharacters -{ - OTAssertThrowsSpecific(_mutableIRI.percentEncodedPath = @"?", - OFInvalidFormatException); -} - -- (void)testSetQuery -{ - _mutableIRI.query = @"que/ry?#"; - OTAssertEqualObjects(_mutableIRI.percentEncodedQuery, @"que/ry?%23"); -} - -- (void)testSetPercentEncodedQuery -{ - _mutableIRI.percentEncodedQuery = @"que/ry?%23"; - OTAssertEqualObjects(_mutableIRI.query, @"que/ry?#"); -} - -- (void)testSetPercentEncodedQueryFailsWithInvalidCharacters -{ - OTAssertThrowsSpecific(_mutableIRI.percentEncodedQuery = @"`", - OFInvalidFormatException); -} - -- (void)testSetQueryItems -{ - _mutableIRI.queryItems = [OFArray arrayWithObjects: - [OFPair pairWithFirstObject: @"foo&bar" secondObject: @"baz=qux"], - [OFPair pairWithFirstObject: @"f=oobar" secondObject: @"b&azqux"], - nil]; - OTAssertEqualObjects(_mutableIRI.percentEncodedQuery, - @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"); -} - -- (void)testSetFragment -{ - _mutableIRI.fragment = @"frag/ment?#"; - OTAssertEqualObjects(_mutableIRI.percentEncodedFragment, - @"frag/ment?%23"); -} - -- (void)testSetPercentEncodedFragment -{ - _mutableIRI.percentEncodedFragment = @"frag/ment?%23"; - OTAssertEqualObjects(_mutableIRI.fragment, @"frag/ment?#"); -} - -- (void)testSetPercentEncodedFragmentFailsWithInvalidCharacters -{ - OTAssertThrowsSpecific(_mutableIRI.percentEncodedFragment = @"`", - OFInvalidFormatException); -} - --(void)testIRIByAppendingPathComponentIsDirectory -{ - OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar"] - IRIByAppendingPathComponent: @"qux" - isDirectory: false], - [OFIRI IRIWithString: @"file:///foo/bar/qux"]); - - OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar/"] - IRIByAppendingPathComponent: @"qux" - isDirectory: false], - [OFIRI IRIWithString: @"file:///foo/bar/qux"]); - - OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar/"] - IRIByAppendingPathComponent: @"qu?x" - isDirectory: false], - [OFIRI IRIWithString: @"file:///foo/bar/qu%3Fx"]); - - OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar/"] - IRIByAppendingPathComponent: @"qu?x" - isDirectory: true], - [OFIRI IRIWithString: @"file:///foo/bar/qu%3Fx/"]); -} - -- (void)testIRIByStandardizingPath -{ - OTAssertEqualObjects([[OFIRI IRIWithString: @"http://foo/bar/.."] - IRIByStandardizingPath], - [OFIRI IRIWithString: @"http://foo/"]); - - OTAssertEqualObjects( - [[OFIRI IRIWithString: @"http://foo/bar/%2E%2E/../qux/"] - IRIByStandardizingPath], - [OFIRI IRIWithString: @"http://foo/bar/qux/"]); - - OTAssertEqualObjects( - [[OFIRI IRIWithString: @"http://foo/bar/./././qux/./"] - IRIByStandardizingPath], - [OFIRI IRIWithString: @"http://foo/bar/qux/"]); - - OTAssertEqualObjects([[OFIRI IRIWithString: @"http://foo/bar/../../qux"] - IRIByStandardizingPath], - [OFIRI IRIWithString: @"http://foo/../qux"]); -} -@end DELETED new_tests/OFInvocationTests.m Index: new_tests/OFInvocationTests.m ================================================================== --- new_tests/OFInvocationTests.m +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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" - -#include - -#if defined(HAVE_COMPLEX_H) && !defined(__STDC_NO_COMPLEX__) -# include -#endif - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFInvocationTests: OTTestCase -{ - OFInvocation *_invocation; -} -@end - -struct TestStruct { - unsigned char c; - unsigned int i; -}; - -@implementation OFInvocationTests -- (struct TestStruct)invocationTestMethod1: (unsigned char)c - : (unsigned int)i - : (struct TestStruct *)testStructPtr - : (struct TestStruct)testStruct -{ - return testStruct; -} - -- (void)setUp -{ - [super setUp]; - - SEL selector = @selector(invocationTestMethod1::::); - OFMethodSignature *signature = - [self methodSignatureForSelector: selector]; - - _invocation = [[OFInvocation alloc] initWithMethodSignature: signature]; -} - -- (void)dealloc -{ - [_invocation release]; - - [super dealloc]; -} - -- (void)testSetAndGetReturnValue -{ - struct TestStruct testStruct, testStruct2; - - memset(&testStruct, 0xFF, sizeof(testStruct)); - testStruct.c = 0x55; - testStruct.i = 0xAAAAAAAA; - - [_invocation setReturnValue: &testStruct]; - [_invocation getReturnValue: &testStruct2]; - OTAssertEqual(memcmp(&testStruct, &testStruct2, sizeof(testStruct)), 0); -} - -- (void)testSetAndGetArgumentAtIndex -{ - struct TestStruct testStruct, testStruct2; - struct TestStruct *testStructPtr = &testStruct, *testStructPtr2; - unsigned const char c = 0xAA; - unsigned char c2; - const unsigned int i = 0x55555555; - unsigned int i2; - - memset(&testStruct, 0xFF, sizeof(testStruct)); - testStruct.c = 0x55; - testStruct.i = 0xAAAAAAAA; - - memset(&testStruct2, 0, sizeof(testStruct2)); - - [_invocation setArgument: &c atIndex: 2]; - [_invocation setArgument: &i atIndex: 3]; - [_invocation setArgument: &testStructPtr atIndex: 4]; - [_invocation setArgument: &testStruct atIndex: 5]; - - [_invocation getArgument: &c2 atIndex: 2]; - OTAssertEqual(c, c2); - - [_invocation getArgument: &i2 atIndex: 3]; - OTAssertEqual(i, i2); - - [_invocation getArgument: &testStructPtr2 atIndex: 4]; - OTAssertEqual(testStructPtr, testStructPtr2); - - [_invocation getArgument: &testStruct2 atIndex: 5]; - OTAssertEqual(memcmp(&testStruct, &testStruct2, sizeof(testStruct)), 0); -} -@end DELETED new_tests/OFJSONTests.m Index: new_tests/OFJSONTests.m ================================================================== --- new_tests/OFJSONTests.m +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFJSONTests: OTTestCase -{ - OFDictionary *_dictionary; -} -@end - -static OFString *string = @"{\"foo\"\t:'b\\na\\r', \"x\":/*foo*/ [.5\r,0xF," - @"null//bar\n,\"foo\",false]}"; - -@implementation OFJSONTests -- (void)setUp -{ - [super setUp]; - - _dictionary = [[OTOrderedDictionary alloc] initWithKeysAndObjects: - @"foo", @"b\na\r", - @"x", [OFArray arrayWithObjects: - [OFNumber numberWithFloat: .5f], - [OFNumber numberWithInt: 0xF], - [OFNull null], - @"foo", - [OFNumber numberWithBool: false], - nil], - nil]; -} - -- (void)dealloc -{ - [_dictionary release]; - - [super dealloc]; -} - -- (void)testObjectByParsingJSON -{ - OTAssertEqualObjects(string.objectByParsingJSON, _dictionary); -} - -- (void)testJSONRepresentation -{ - OTAssert(_dictionary.JSONRepresentation, - @"{\"foo\":\"b\\na\\r\",\"x\":[0.5,15,null,\"foo\",false]}"); -} - -- (void)testPrettyJSONRepresentation -{ - OTAssertEqualObjects([_dictionary JSONRepresentationWithOptions: - OFJSONRepresentationOptionPretty], - @"{\n\t\"foo\": \"b\\na\\r\",\n\t\"x\": [\n\t\t0.5,\n\t\t15," - @"\n\t\tnull,\n\t\t\"foo\",\n\t\tfalse\n\t]\n}"); -} - -- (void)testJSON5Representation -{ - OTAssertEqualObjects([_dictionary JSONRepresentationWithOptions: - OFJSONRepresentationOptionJSON5], - @"{foo:\"b\\\na\\r\",x:[0.5,15,null,\"foo\",false]}"); -} - -- (void)testObjectByParsingJSONFailsWithInvalidJSON -{ - OTAssertThrowsSpecific([@"{" objectByParsingJSON], - OFInvalidJSONException); - - OTAssertThrowsSpecific([@"]" objectByParsingJSON], - OFInvalidJSONException); - - OTAssertThrowsSpecific([@"bar" objectByParsingJSON], - OFInvalidJSONException); - - OTAssertThrowsSpecific([@"[\"a\" \"b\"]" objectByParsingJSON], - OFInvalidJSONException); -} - -- (void)testObjectByParsingJSONWithDeepNesting -{ - OTAssertEqualObjects( - @"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" - .objectByParsingJSON, - [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: [OFArray arrayWithObject: - [OFArray arrayWithObject: - [OFDictionary dictionary]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]); -} - -- (void)testObjectByParsingJSONFailsWithTooDeepNesting -{ - OTAssertThrowsSpecific( - [@"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" - objectByParsingJSON], - OFInvalidJSONException); -} -@end DELETED new_tests/OFKernelEventObserverTests.m Index: new_tests/OFKernelEventObserverTests.m ================================================================== --- new_tests/OFKernelEventObserverTests.m +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -#ifdef HAVE_KQUEUE -# import "OFKqueueKernelEventObserver.h" -#endif -#ifdef HAVE_EPOLL -# import "OFEpollKernelEventObserver.h" -#endif -#ifdef HAVE_POLL -# import "OFPollKernelEventObserver.h" -#endif -#ifdef HAVE_SELECT -# import "OFSelectKernelEventObserver.h" -#endif - -@interface OFKernelEventObserverTests: OTTestCase - -{ - OFTCPSocket *_server, *_client, *_accepted; - OFKernelEventObserver *_observer; - size_t _events; -} -@end - -static const size_t numExpectedEvents = 3; - -@implementation OFKernelEventObserverTests -- (void)setUp -{ - OFSocketAddress address; - - [super setUp]; - - _server = [[OFTCPSocket alloc] init]; - address = [_server bindToHost: @"127.0.0.1" port: 0]; - [_server listen]; - - _client = [[OFTCPSocket alloc] init]; - [_client connectToHost: @"127.0.0.1" - port: OFSocketAddressIPPort(&address)]; - [_client writeBuffer: "0" length: 1]; -} - -- (void)dealloc -{ - [_client release]; - [_server release]; - [_accepted release]; - - [super dealloc]; -} - -- (void)testKernelEventObserverWithClass: (Class)class -{ - bool deadlineExceeded = false; - OFDate *deadline; - - _observer = [[class alloc] init]; - _observer.delegate = self; - [_observer addObjectForReading: _server]; - - deadline = [OFDate dateWithTimeIntervalSinceNow: 1]; - - while (_events < numExpectedEvents) { - if (deadline.timeIntervalSinceNow < 0) { - deadlineExceeded = true; - break; - } - - [_observer observeForTimeInterval: 0.01]; - } - - OTAssertFalse(deadlineExceeded); - OTAssertEqual(_events, numExpectedEvents); -} - -- (void)objectIsReadyForReading: (id)object -{ - char buffer; - - switch (_events++) { - case 0: - OTAssertEqual(object, _server); - - _accepted = [[object accept] retain]; - [_observer addObjectForReading: _accepted]; - break; - case 1: - OTAssert(object, _accepted); - - OTAssertEqual([object readIntoBuffer: &buffer length: 1], 1); - OTAssertEqual(buffer, '0'); - - [_client close]; - break; - case 2: - OTAssertEqual(object, _accepted); - - OTAssertEqual([object readIntoBuffer: &buffer length: 1], 0); - break; - default: - OTAssert(false); - } -} - -#ifdef HAVE_SELECT -- (void)testSelectKernelEventObserver -{ - [self testKernelEventObserverWithClass: - [OFSelectKernelEventObserver class]]; -} -#endif - -#ifdef HAVE_POLL -- (void)testPollKernelEventObserver -{ - [self testKernelEventObserverWithClass: - [OFPollKernelEventObserver class]]; -} -#endif - -#ifdef HAVE_EPOLL -- (void)testEpollKernelEventObserver -{ - [self testKernelEventObserverWithClass: - [OFEpollKernelEventObserver class]]; -} -#endif - -#ifdef HAVE_KQUEUE -- (void)testKqueueKernelEventObserver -{ - [self testKernelEventObserverWithClass: - [OFKqueueKernelEventObserver class]]; -} -#endif -@end DELETED new_tests/OFListTests.m Index: new_tests/OFListTests.m ================================================================== --- new_tests/OFListTests.m +++ /dev/null @@ -1,277 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFListTests: OTTestCase -{ - OFList *_list; -} -@end - -@implementation OFListTests -- (void)setUp -{ - [super setUp]; - - _list = [[OFList alloc] init]; - [_list appendObject: @"Foo"]; - [_list appendObject: @"Bar"]; - [_list appendObject: @"Baz"]; -} - -- (void)dealloc -{ - [_list release]; - - [super dealloc]; -} - -- (void)testCount -{ - OTAssertEqual(_list.count, 3); -} - -- (void)testAppendObject -{ - OFListItem item; - - [_list appendObject: @"Qux"]; - - item = _list.firstListItem; - OTAssertEqualObjects(OFListItemObject(item), @"Foo"); - - item = OFListItemNext(item); - OTAssertEqualObjects(OFListItemObject(item), @"Bar"); - - item = OFListItemNext(item); - OTAssertEqualObjects(OFListItemObject(item), @"Baz"); - - item = OFListItemNext(item); - OTAssertEqualObjects(OFListItemObject(item), @"Qux"); - - item = OFListItemNext(item); - OTAssertEqual(item, NULL); -} - -- (void)testFirstListItem -{ - OTAssertEqualObjects(OFListItemObject(_list.firstListItem), @"Foo"); -} - -- (void)testFirstObject -{ - OTAssertEqualObjects(_list.firstObject, @"Foo"); -} - -- (void)testLastListItem -{ - OTAssertEqualObjects(OFListItemObject(_list.lastListItem), @"Baz"); -} - -- (void)testLastObject -{ - OTAssertEqualObjects(_list.lastObject, @"Baz"); -} - -- (void)testListItemNext -{ - OTAssertEqualObjects( - OFListItemObject(OFListItemNext(_list.firstListItem)), @"Bar"); -} - -- (void)testListItemPrevious -{ - OTAssertEqualObjects( - OFListItemObject(OFListItemPrevious(_list.lastListItem)), @"Bar"); -} - -- (void)testRemoveListItem -{ - OFListItem item; - - [_list removeListItem: OFListItemNext(_list.firstListItem)]; - - item = _list.firstListItem; - OTAssertEqualObjects(OFListItemObject(item), @"Foo"); - - item = OFListItemNext(item); - OTAssertEqualObjects(OFListItemObject(item), @"Baz"); - - item = OFListItemNext(item); - OTAssertEqual(item, NULL); -} - -- (void)testInsertObjectBeforeListItem -{ - OFListItem item; - - [_list insertObject: @"Qux" beforeListItem: _list.lastListItem]; - - item = _list.firstListItem; - OTAssertEqualObjects(OFListItemObject(item), @"Foo"); - - item = OFListItemNext(item); - OTAssertEqualObjects(OFListItemObject(item), @"Bar"); - - item = OFListItemNext(item); - OTAssertEqualObjects(OFListItemObject(item), @"Qux"); - - item = OFListItemNext(item); - OTAssertEqualObjects(OFListItemObject(item), @"Baz"); - - item = OFListItemNext(item); - OTAssertEqual(item, NULL); -} - -- (void)testInsertObjectAfterListItem -{ - OFListItem item; - - [_list insertObject: @"Qux" afterListItem: _list.firstListItem]; - - item = _list.firstListItem; - OTAssertEqualObjects(OFListItemObject(item), @"Foo"); - - item = OFListItemNext(item); - OTAssertEqualObjects(OFListItemObject(item), @"Qux"); - - item = OFListItemNext(item); - OTAssertEqualObjects(OFListItemObject(item), @"Bar"); - - item = OFListItemNext(item); - OTAssertEqualObjects(OFListItemObject(item), @"Baz"); - - item = OFListItemNext(item); - OTAssertEqual(item, NULL); -} - -- (void)testContainsObject -{ - OTAssertTrue([_list containsObject: @"Foo"]); - OTAssertFalse([_list containsObject: @"Qux"]); -} - -- (void)testContainsObjectIdenticalTo -{ - OFString *foo = _list.firstObject; - - OTAssertTrue([_list containsObjectIdenticalTo: foo]); - OTAssertFalse( - [_list containsObjectIdenticalTo: [[foo mutableCopy] autorelease]]); -} - -- (void)testIsEqual -{ - OFList *list = [OFList list]; - - [list appendObject: @"Foo"]; - [list appendObject: @"Bar"]; - [list appendObject: @"Baz"]; - - OTAssertEqualObjects(list, _list); - - [list appendObject: @"Qux"]; - - OTAssertNotEqualObjects(list, _list); -} - -- (void)testHash -{ - OFList *list = [OFList list]; - - [list appendObject: @"Foo"]; - [list appendObject: @"Bar"]; - [list appendObject: @"Baz"]; - - OTAssertEqual(list.hash, _list.hash); - - [list appendObject: @"Qux"]; - - OTAssertNotEqual(list.hash, _list.hash); -} - -- (void)testCopy -{ - OTAssertEqualObjects([[_list copy] autorelease], _list); -} - -- (void)testDescription -{ - OTAssertEqualObjects(_list.description, @"[\n\tFoo,\n\tBar,\n\tBaz\n]"); -} - -- (void)testEnumerator -{ - OFEnumerator *enumerator = [_list objectEnumerator]; - - OTAssertEqualObjects([enumerator nextObject], @"Foo"); - OTAssertEqualObjects([enumerator nextObject], @"Bar"); - OTAssertEqualObjects([enumerator nextObject], @"Baz"); - OTAssertNil([enumerator nextObject]); -} - -- (void)testDetectMutationDuringEnumeration -{ - OFEnumerator *enumerator = [_list objectEnumerator]; - - [_list removeListItem: _list.firstListItem]; - - OTAssertThrowsSpecific([enumerator nextObject], - OFEnumerationMutationException); -} - -- (void)testFastEnumeration -{ - size_t i = 0; - - for (OFString *object in _list) { - OTAssertLessThan(i, 3); - - switch (i++) { - case 0: - OTAssertEqualObjects(object, @"Foo"); - break; - case 1: - OTAssertEqualObjects(object, @"Bar"); - break; - case 2: - OTAssertEqualObjects(object, @"Baz"); - break; - } - } - - OTAssertEqual(i, 3); -} - -- (void)testDetectMutationDuringFastEnumeration -{ - bool detected = false; - - @try { - for (OFString *object in _list) { - (void)object; - [_list removeListItem: _list.firstListItem]; - } - } @catch (OFEnumerationMutationException *e) { - detected = true; - } - - OTAssertTrue(detected); -} -@end DELETED new_tests/OFLocaleTests.m Index: new_tests/OFLocaleTests.m ================================================================== --- new_tests/OFLocaleTests.m +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFLocaleTests: OTTestCase -@end - -@implementation OFLocaleTests -+ (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, id) *) *)summary -{ - OFMutableArray *summary = [OFMutableArray array]; - -#define ADD(name, value) \ - [summary addObject: [OFPair pairWithFirstObject: name \ - secondObject: value]]; - - ADD(@"Language code", [OFLocale languageCode]) - ADD(@"Country code", [OFLocale countryCode]) - ADD(@"Encoding", OFStringEncodingName([OFLocale encoding])) - ADD(@"Decimal separator", [OFLocale decimalSeparator]) - -#undef ADD - - return summary; -} -@end DELETED new_tests/OFMatrix4x4Tests.m Index: new_tests/OFMatrix4x4Tests.m ================================================================== --- new_tests/OFMatrix4x4Tests.m +++ /dev/null @@ -1,165 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFMatrix4x4Tests: OTTestCase -{ - OFMatrix4x4 *_matrix; -} -@end - -@implementation OFMatrix4x4Tests -- (void)setUp -{ - [super setUp]; - - _matrix = [[OFMatrix4x4 alloc] initWithValues: (const float [4][4]){ - { 1, 2, 3, 4 }, - { 5, 6, 7, 8 }, - { 9, 10, 11, 12 }, - { 13, 14, 15, 16 } - }]; -} - -- (void)dealloc -{ - [_matrix release]; - - [super dealloc]; -} - -- (void)testIdentityMatrix -{ - OTAssertEqual(memcmp([[OFMatrix4x4 identityMatrix] values], - (const float [4][4]){ - { 1, 0, 0, 0 }, - { 0, 1, 0, 0 }, - { 0, 0, 1, 0 }, - { 0, 0, 0, 1 } - }, 16 * sizeof(float)), - 0); -} - -- (void)testDescription -{ - OTAssertEqualObjects(_matrix.description, - @""); -} - -- (void)testIsEqual -{ - OTAssertEqualObjects([OFMatrix4x4 identityMatrix], - ([OFMatrix4x4 matrixWithValues: (const float [4][4]){ - { 1, 0, 0, 0 }, - { 0, 1, 0, 0 }, - { 0, 0, 1, 0 }, - { 0, 0, 0, 1 } - }])); -} - -- (void)testHash -{ - OTAssertEqual([[OFMatrix4x4 identityMatrix] hash], - [([OFMatrix4x4 matrixWithValues: (const float [4][4]){ - { 1, 0, 0, 0 }, - { 0, 1, 0, 0 }, - { 0, 0, 1, 0 }, - { 0, 0, 0, 1 } - }]) hash]); -} - -- (void)testCopy -{ - OTAssertEqualObjects([[_matrix copy] autorelease], _matrix); -} - -- (void)testMultiplyWithMatrix -{ - OFMatrix4x4 *matrix; - - matrix = [[_matrix copy] autorelease]; - [matrix multiplyWithMatrix: [OFMatrix4x4 identityMatrix]]; - OTAssertEqualObjects(matrix, _matrix); - - matrix = [OFMatrix4x4 matrixWithValues: (const float [4][4]){ - { 100, 200, 300, 400 }, - { 500, 600, 700, 800 }, - { 900, 1000, 1100, 1200 }, - { 1300, 1400, 1500, 1600 } - }]; - [matrix multiplyWithMatrix: _matrix]; - OTAssertEqualObjects(matrix, - ([OFMatrix4x4 matrixWithValues: (const float [4][4]){ - { 9000, 10000, 11000, 12000 }, - { 20200, 22800, 25400, 28000 }, - { 31400, 35600, 39800, 44000 }, - { 42600, 48400, 54200, 60000 } - }])); -} - -- (void)testTranslateWithVector -{ - OFMatrix4x4 *matrix = [OFMatrix4x4 identityMatrix]; - OFVector4D point; - - [matrix translateWithVector: OFMakeVector3D(1, 2, 3)]; - - point = [matrix transformedVector: OFMakeVector4D(2, 3, 4, 1)]; - OTAssertEqual(point.x, 3); - OTAssertEqual(point.y, 5); - OTAssertEqual(point.z, 7); - OTAssertEqual(point.w, 1); -} - -- (void)testScaleWithVector -{ - OFMatrix4x4 *matrix = [OFMatrix4x4 identityMatrix]; - OFVector4D point; - - [matrix translateWithVector: OFMakeVector3D(1, 2, 3)]; - [matrix scaleWithVector: OFMakeVector3D(-1, 0.5f, 2)]; - - point = [matrix transformedVector: OFMakeVector4D(2, 3, 4, 1)]; - OTAssertEqual(point.x, -3); - OTAssertEqual(point.y, 2.5); - OTAssertEqual(point.z, 14); - OTAssertEqual(point.w, 1); -} - -- (void)testTransformVectorsCount -{ - OFVector4D points[2] = {{ 1, 2, 3, 1 }, { 7, 8, 9, 2 }}; - - [_matrix transformVectors: points count: 2]; - - OTAssertEqual(points[0].x, 18); - OTAssertEqual(points[0].y, 46); - OTAssertEqual(points[0].z, 74); - OTAssertEqual(points[0].w, 102); - OTAssertEqual(points[1].x, 58); - OTAssertEqual(points[1].y, 162); - OTAssertEqual(points[1].z, 266); - OTAssertEqual(points[1].w, 370); -} -@end DELETED new_tests/OFMemoryStreamTests.m Index: new_tests/OFMemoryStreamTests.m ================================================================== --- new_tests/OFMemoryStreamTests.m +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFMemoryStreamTests: OTTestCase -@end - -static const char string[] = "abcdefghijkl"; - -@implementation OFMemoryStreamTests -- (void)testReadOnlyMemoryStream -{ - OFMemoryStream *stream = [OFMemoryStream - streamWithMemoryAddress: (char *)string - size: sizeof(string) - writable: false]; - char buffer[10]; - - /* - * Test the lowlevel methods, as otherwise OFStream will do one big - * read and we will not test OFMemoryStream. - */ - - OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 5], 5); - OTAssertEqual(memcmp(buffer, "abcde", 5), 0); - OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 3], 3); - OTAssertEqual(memcmp(buffer, "fgh", 3), 0); - OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 10], 5); - OTAssertEqual(memcmp(buffer, "ijkl", 5), 0); - OTAssertTrue([stream lowlevelIsAtEndOfStream]); - - OTAssertEqual([stream lowlevelSeekToOffset: 0 whence: OFSeekCurrent], - sizeof(string)); - OTAssertTrue([stream lowlevelIsAtEndOfStream]); - - OTAssertEqual([stream lowlevelSeekToOffset: 4 whence: OFSeekSet], 4); - OTAssertFalse([stream lowlevelIsAtEndOfStream]); - OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 10], 9); - OTAssertEqual(memcmp(buffer, "efghijkl", 9), 0); - - OTAssertEqual([stream lowlevelSeekToOffset: -2 whence: OFSeekEnd], 11); - OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 10], 2); - OTAssertEqual(memcmp(buffer, "l", 2), 0); - OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 10], 0); - - OTAssertThrowsSpecific([stream lowlevelWriteBuffer: "" length: 1], - OFWriteFailedException); -} - -- (void)testReadWriteMemoryStream -{ - OFMutableData *data = [OFMutableData dataWithCapacity: 13]; - OFMemoryStream *stream; - - [data increaseCountBy: 13]; - stream = [OFMemoryStream streamWithMemoryAddress: data.mutableItems - size: data.count - writable: true]; - - OTAssertEqual([stream lowlevelWriteBuffer: "abcde" length: 5], 5); - OTAssertEqual([stream lowlevelWriteBuffer: "fgh" length: 3], 3); - OTAssertEqual([stream lowlevelWriteBuffer: "ijkl" length: 5], 5); - OTAssertEqual(memcmp(data.items, string, data.count), 0); - OTAssertEqual([stream lowlevelSeekToOffset: -3 whence: OFSeekEnd], 10); - - OTAssertThrowsSpecific([stream lowlevelWriteBuffer: "xyz" length: 4], - OFWriteFailedException); -} -@end DELETED new_tests/OFMethodSignatureTests.m Index: new_tests/OFMethodSignatureTests.m ================================================================== --- new_tests/OFMethodSignatureTests.m +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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" - -#include - -#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) -# include -#endif - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFMethodSignatureTests: OTTestCase -@end - -struct Test1Struct { - char c; - int i; - char d; -}; - -struct Test2Struct { - char c; - struct { - short s; - int i; - } st; - union { - char c; - int i; - } u; - double d; -}; - -#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) -struct Test3Struct { - char c; - complex double cd; -}; -#endif - -union Test3Union { - char c; - int i; - double d; -}; - -union Test4Union { - char c; - struct { - short x, y; - } st; - int i; - union { - float f; - double d; - } u; -}; - -@implementation OFMethodSignatureTests -- (void)testSignatureWithObjCTypes -{ - OFMethodSignature *methodSignature; - - methodSignature = - [OFMethodSignature signatureWithObjCTypes: "i28@0:8S16*20"]; - OTAssertEqual(methodSignature.numberOfArguments, 4); - OTAssertEqual(strcmp(methodSignature.methodReturnType, "i"), 0); - OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 0], "@"), 0); - OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 1], ":"), 0); - OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 2], "S"), 0); - OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 3], "*"), 0); - OTAssertEqual(methodSignature.frameLength, 28); - OTAssertEqual([methodSignature argumentOffsetAtIndex: 0], 0); - OTAssertEqual([methodSignature argumentOffsetAtIndex: 1], 8); - OTAssertEqual([methodSignature argumentOffsetAtIndex: 2], 16); - OTAssertEqual([methodSignature argumentOffsetAtIndex: 3], 20); - - methodSignature = [OFMethodSignature signatureWithObjCTypes: - "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}24@0:8" - "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}16"]; - OTAssertEqual(methodSignature.numberOfArguments, 3); - OTAssertEqual(strcmp(methodSignature.methodReturnType, - "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}"), 0); - OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 0], "@"), 0); - OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 1], ":"), 0); - OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 2], - "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}"), 0); - OTAssertEqual(methodSignature.frameLength, 24); - OTAssertEqual([methodSignature argumentOffsetAtIndex: 0], 0); - OTAssertEqual([methodSignature argumentOffsetAtIndex: 1], 8); - OTAssertEqual([methodSignature argumentOffsetAtIndex: 2], 16); -} - -- (void)testSignatureWithObjCTypesFailsWithInvalidFormat -{ - OTAssertThrowsSpecific( - [OFMethodSignature signatureWithObjCTypes: "{ii"], - OFInvalidFormatException); - - OTAssertThrowsSpecific([OFMethodSignature signatureWithObjCTypes: ""], - OFInvalidFormatException); - - OTAssertThrowsSpecific([OFMethodSignature signatureWithObjCTypes: "0"], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [OFMethodSignature signatureWithObjCTypes: "{{}0"], - OFInvalidFormatException); -} - -- (void)testSizeOfTypeEncoding -{ - OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test1Struct)), - sizeof(struct Test1Struct)); - - OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test2Struct)), - sizeof(struct Test2Struct)); - -#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \ - OF_GCC_VERSION >= 402 - OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test3Struct)), - sizeof(struct Test3Struct)); -#endif - - OTAssertEqual(OFSizeOfTypeEncoding(@encode(union Test3Union)), - sizeof(union Test3Union)); - - OTAssertEqual(OFSizeOfTypeEncoding(@encode(union Test4Union)), - sizeof(union Test4Union)); - - OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test1Struct [5])), - sizeof(struct Test1Struct [5])); -} - -- (void)testAlignmentOfTypeEncoding -{ - OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test1Struct)), - OF_ALIGNOF(struct Test1Struct)); - - OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test2Struct)), - OF_ALIGNOF(struct Test2Struct)); - -#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \ - OF_GCC_VERSION >= 402 - OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test3Struct)), - OF_ALIGNOF(struct Test3Struct)); -#endif - - OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(union Test3Union)), - OF_ALIGNOF(union Test3Union)); - - OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(union Test4Union)), - OF_ALIGNOF(union Test4Union)); - - OTAssertEqual( - OFAlignmentOfTypeEncoding(@encode(struct Test1Struct [5])), - OF_ALIGNOF(struct Test1Struct [5])); -} -@end DELETED new_tests/OFMutableArrayTests.h Index: new_tests/OFMutableArrayTests.h ================================================================== --- new_tests/OFMutableArrayTests.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 "OFArrayTests.h" - -@interface OFMutableArrayTests: OFArrayTests -{ - OFMutableArray *_mutableArray; -} -@end DELETED new_tests/OFMutableArrayTests.m Index: new_tests/OFMutableArrayTests.m ================================================================== --- new_tests/OFMutableArrayTests.m +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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 "OFMutableArrayTests.h" - -#import "OFArray+Private.h" - -@interface CustomMutableArray: OFMutableArray -{ - OFMutableArray *_array; -} -@end - -static OFString *const cArray[] = { - @"Foo", - @"Bar", - @"Baz" -}; - -@implementation OFMutableArrayTests -- (Class)arrayClass -{ - return [CustomMutableArray class]; -} - -- (void)setUp -{ - [super setUp]; - - _mutableArray = [[self.arrayClass alloc] - initWithObjects: cArray - count: sizeof(cArray) / sizeof(*cArray)]; -} - -- (void)dealloc -{ - [_mutableArray release]; - - [super dealloc]; -} - -- (void)testAddObject -{ - [_mutableArray addObject: cArray[0]]; - [_mutableArray addObject: cArray[2]]; - - OTAssertEqualObjects(_mutableArray, - ([OFArray arrayWithObjects: @"Foo", @"Bar", @"Baz", @"Foo", @"Baz", - nil])); -} - -- (void)testInsertObjectAtIndex -{ - [_mutableArray insertObject: cArray[1] atIndex: 1]; - - OTAssertEqualObjects(_mutableArray, - ([OFArray arrayWithObjects: @"Foo", @"Bar", @"Bar", @"Baz", nil])); -} - -- (void)testReplaceObjectWithObject -{ - [_mutableArray insertObject: cArray[1] atIndex: 1]; - [_mutableArray replaceObject: cArray[1] withObject: cArray[0]]; - - OTAssertEqualObjects(_mutableArray, - ([OFArray arrayWithObjects: @"Foo", @"Foo", @"Foo", @"Baz", nil])); -} - -- (void)testReplaceObjectIdenticalToWithObject -{ - [_mutableArray insertObject: [[cArray[1] mutableCopy] autorelease] - atIndex: 1]; - [_mutableArray replaceObjectIdenticalTo: cArray[1] - withObject: cArray[0]]; - - OTAssertEqualObjects(_mutableArray, - ([OFArray arrayWithObjects: @"Foo", @"Bar", @"Foo", @"Baz", nil])); -} - -- (void)testReplaceObjectAtIndexWithObject -{ - [_mutableArray replaceObjectAtIndex: 1 - withObject: cArray[0]]; - - OTAssertEqualObjects(_mutableArray, - ([OFArray arrayWithObjects: @"Foo", @"Foo", @"Baz", nil])); -} - -- (void)testRemoveObject -{ - [_mutableArray removeObject: cArray[1]]; - - OTAssertEqualObjects(_mutableArray, - ([OFArray arrayWithObjects: @"Foo", @"Baz", nil])); -} - -- (void)testRemoveObjectIdenticalTo -{ - [_mutableArray removeObjectIdenticalTo: cArray[1]]; - - OTAssertEqualObjects(_mutableArray, - ([OFArray arrayWithObjects: @"Foo", @"Baz", nil])); -} - -- (void)testRemoveObjectAtIndex -{ - [_mutableArray removeObjectAtIndex: 1]; - - OTAssertEqualObjects(_mutableArray, - ([OFArray arrayWithObjects: @"Foo", @"Baz", nil])); -} - -- (void)testRemoveObjectsInRange -{ - [_mutableArray removeObjectsInRange: OFMakeRange(1, 2)]; - - OTAssertEqualObjects(_mutableArray, [OFArray arrayWithObject: @"Foo"]); -} - -- (void)testRemoveObjectsInRangeFailsWhenOutOfRange -{ - OTAssertThrowsSpecific([_mutableArray removeObjectsInRange: - OFMakeRange(0, _mutableArray.count + 1)], OFOutOfRangeException); -} - -- (void)testReverse -{ - [_mutableArray reverse]; - - OTAssertEqualObjects(_mutableArray, - ([OFArray arrayWithObjects: @"Baz", @"Bar", @"Foo", nil])); -} - -#ifdef OF_HAVE_BLOCKS -- (void)testReplaceObjectsUsingBlock -{ - [_mutableArray replaceObjectsUsingBlock: ^ id (id object, size_t idx) { - return [object lowercaseString]; - }]; - - OTAssertEqualObjects(_mutableArray, - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); -} -#endif - -- (void)testSetValueForKey -{ - OFMutableArray *array = [self.arrayClass arrayWithObjects: - [OFMutableIRI IRIWithString: @"http://foo.bar/"], - [OFMutableIRI IRIWithString: @"http://bar.qux/"], - [OFMutableIRI IRIWithString: @"http://qux.quxqux/"], nil]; - - [array setValue: [OFNumber numberWithShort: 1234] - forKey: @"port"]; - OTAssertEqualObjects(array, ([OFArray arrayWithObjects: - [OFIRI IRIWithString: @"http://foo.bar:1234/"], - [OFIRI IRIWithString: @"http://bar.qux:1234/"], - [OFIRI IRIWithString: @"http://qux.quxqux:1234/"], nil])); -} -@end - -@implementation CustomMutableArray -- (instancetype)initWithObjects: (id const *)objects count: (size_t)count -{ - self = [super init]; - - @try { - _array = [[OFMutableArray alloc] initWithObjects: objects - count: count]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_array release]; - - [super dealloc]; -} - -- (id)objectAtIndex: (size_t)idx -{ - return [_array objectAtIndex: idx]; -} - -- (size_t)count -{ - return [_array count]; -} - -- (void)insertObject: (id)object atIndex: (size_t)idx -{ - [_array insertObject: object atIndex: idx]; -} - -- (void)replaceObjectAtIndex: (size_t)idx withObject: (id)object -{ - [_array replaceObjectAtIndex: idx withObject: object]; -} - -- (void)removeObjectAtIndex: (size_t)idx -{ - [_array removeObjectAtIndex: idx]; -} -@end DELETED new_tests/OFMutableDataTests.m Index: new_tests/OFMutableDataTests.m ================================================================== --- new_tests/OFMutableDataTests.m +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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" - -#include - -#import "OFDataTests.h" - -@interface OFMutableDataTests: OFDataTests -{ - OFMutableData *_mutableData; -} -@end - -@implementation OFMutableDataTests -- (Class)dataClass -{ - return [OFMutableData class]; -} - -- (void)setUp -{ - [super setUp]; - - _mutableData = [[OFMutableData alloc] initWithItems: "abcdef" count: 6]; -} - -- (void)dealloc -{ - [_mutableData release]; - - [super dealloc]; -} - -- (void)testMutableCopy -{ - OTAssertEqualObjects([[_data mutableCopy] autorelease], _data); - OTAssertNotEqual([[_data mutableCopy] autorelease], _data); -} - -- (void)testAddItem -{ - [_mutableData addItem: "g"]; - - OTAssertEqualObjects(_mutableData, - [OFData dataWithItems: "abcdefg" count: 7]); -} - -- (void)testAddItemsCount -{ - [_mutableData addItems: "gh" count: 2]; - - OTAssertEqualObjects(_mutableData, - [OFData dataWithItems: "abcdefgh" count: 8]); -} - -- (void)testAddItemsCountThrowsOnOutOfRange -{ - OTAssertThrowsSpecific([_mutableData addItems: "" count: SIZE_MAX], - OFOutOfRangeException); -} - -- (void)testRemoveLastItem -{ - [_mutableData removeLastItem]; - - OTAssertEqualObjects(_mutableData, - [OFData dataWithItems: "abcde" count: 5]); -} - -- (void)testRemoveItemsInRange -{ - [_mutableData removeItemsInRange: OFMakeRange(1, 2)]; - - OTAssertEqualObjects(_mutableData, - [OFData dataWithItems: "adef" count: 4]); -} - -- (void)testRemoveItemsInRangeThrowsOnOutOfRangeRange -{ - OTAssertThrowsSpecific( - [_mutableData removeItemsInRange: OFMakeRange(6, 1)], - OFOutOfRangeException); - - OTAssertThrowsSpecific( - [_mutableData removeItemsInRange: OFMakeRange(7, 0)], - OFOutOfRangeException); -} - -- (void)testInsertItemsAtIndexCount -{ - [_mutableData insertItems: "BC" atIndex: 1 count: 2]; - - OTAssertEqualObjects(_mutableData, - [OFData dataWithItems: "aBCbcdef" count: 8]); -} - -- (void)testInsertItemsAtIndexCountThrowsOnOutOfRangeIndex -{ - OTAssertThrowsSpecific( - [_mutableData insertItems: "a" atIndex: 7 count: 1], - OFOutOfRangeException); -} -@end DELETED new_tests/OFMutableDictionaryTests.h Index: new_tests/OFMutableDictionaryTests.h ================================================================== --- new_tests/OFMutableDictionaryTests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -#import "OFDictionaryTests.h" - -@interface OFMutableDictionaryTests: OFDictionaryTests -{ - OFMutableDictionary *_mutableDictionary; -} -@end DELETED new_tests/OFMutableDictionaryTests.m Index: new_tests/OFMutableDictionaryTests.m ================================================================== --- new_tests/OFMutableDictionaryTests.m +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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 "OFMutableDictionaryTests.h" - -@interface CustomMutableDictionary: OFMutableDictionary -{ - OFMutableDictionary *_dictionary; -} -@end - -@implementation OFMutableDictionaryTests -- (Class)dictionaryClass -{ - return [CustomMutableDictionary class]; -} - -- (void)setUp -{ - [super setUp]; - - _mutableDictionary = [[self.dictionaryClass alloc] init]; -} - -- (void)dealloc -{ - [_mutableDictionary release]; - - [super dealloc]; -} - -- (void)testSetObjectForKey -{ - [_mutableDictionary setObject: @"bar" forKey: @"foo"]; - OTAssertEqualObjects([_mutableDictionary objectForKey: @"foo"], @"bar"); - - [_mutableDictionary setObject: @"qux" forKey: @"baz"]; - OTAssertEqualObjects(_mutableDictionary, - ([OFDictionary dictionaryWithKeysAndObjects: - @"foo", @"bar", @"baz", @"qux", nil])); -} - -- (void)testSetValueForKey -{ - [_mutableDictionary setValue: @"bar" forKey: @"foo"]; - OTAssertEqualObjects([_mutableDictionary objectForKey: @"foo"], @"bar"); - - [_mutableDictionary setValue: @"qux" forKey: @"baz"]; - OTAssertEqualObjects(_mutableDictionary, - ([OFDictionary dictionaryWithKeysAndObjects: - @"foo", @"bar", @"baz", @"qux", nil])); -} - -- (void)testRemoveObjectForKey -{ - [_mutableDictionary addEntriesFromDictionary: _dictionary]; - OTAssertEqual(_mutableDictionary.count, 2); - - [_mutableDictionary removeObjectForKey: @"key2"]; - OTAssertEqual(_mutableDictionary.count, 1); - OTAssertEqualObjects(_mutableDictionary, - [OFDictionary dictionaryWithObject: @"value1" forKey: @"key1"]); -} - -- (void)testMutableCopy -{ - OFMutableDictionary *copy = [[_dictionary mutableCopy] autorelease]; - - OTAssertEqualObjects(copy, _dictionary); - OTAssertNotEqual(copy, _dictionary); -} - -#ifdef OF_HAVE_BLOCKS -- (void)testReplaceObjectsUsingBlock -{ - OFMutableDictionary *mutableDictionary = - [[_dictionary mutableCopy] autorelease]; - - [mutableDictionary replaceObjectsUsingBlock: ^ id (id key, id object) { - if ([key isEqual: @"key1"]) - return @"value_1"; - if ([key isEqual: @"key2"]) - return @"value_2"; - - return nil; - }]; - - OTAssertEqualObjects(mutableDictionary, - ([OFDictionary dictionaryWithKeysAndObjects: - @"key1", @"value_1", @"key2", @"value_2", nil])); -} -#endif -@end - -@implementation CustomMutableDictionary -- (instancetype)init -{ - self = [super init]; - - @try { - _dictionary = [[OFMutableDictionary alloc] init]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithObjects: (const id *)objects_ - forKeys: (const id *)keys_ - count: (size_t)count -{ - self = [super init]; - - @try { - _dictionary = [[OFMutableDictionary alloc] - initWithObjects: objects_ - forKeys: keys_ - count: count]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_dictionary release]; - - [super dealloc]; -} - -- (id)objectForKey: (id)key -{ - return [_dictionary objectForKey: key]; -} - -- (size_t)count -{ - return _dictionary.count; -} - -- (OFEnumerator *)keyEnumerator -{ - return [_dictionary keyEnumerator]; -} - -- (void)setObject: (id)object forKey: (id)key -{ - [_dictionary setObject: object forKey: key]; -} - -- (void)removeObjectForKey: (id)key -{ - [_dictionary removeObjectForKey: key]; -} -@end DELETED new_tests/OFMutableSetTests.h Index: new_tests/OFMutableSetTests.h ================================================================== --- new_tests/OFMutableSetTests.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 "OFSetTests.h" - -@interface OFMutableSetTests: OFSetTests -{ - OFMutableSet *_mutableSet; -} -@end DELETED new_tests/OFMutableSetTests.m Index: new_tests/OFMutableSetTests.m ================================================================== --- new_tests/OFMutableSetTests.m +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 "OFMutableSetTests.h" - -@interface CustomMutableSet: OFMutableSet -{ - OFMutableSet *_set; -} -@end - -@implementation OFMutableSetTests -- (Class)setClass -{ - return [CustomMutableSet class]; -} - -- (void)setUp -{ - [super setUp]; - - _mutableSet = [[OFMutableSet alloc] - initWithObjects: @"foo", @"bar", @"baz", nil]; -} - -- (void)dealloc -{ - [_mutableSet release]; - - [super dealloc]; -} - -- (void)testAddObject -{ - [_mutableSet addObject: @"x"]; - - OTAssertEqualObjects(_mutableSet, - ([OFSet setWithObjects: @"foo", @"bar", @"baz", @"x", nil])); -} - -- (void)testRemoveObject -{ - [_mutableSet removeObject: @"foo"]; - - OTAssertEqualObjects(_mutableSet, - ([OFSet setWithObjects: @"bar", @"baz", nil])); -} - -- (void)testMinusSet -{ - [_mutableSet minusSet: [OFSet setWithObjects: @"foo", @"bar", nil]]; - - OTAssertEqualObjects(_mutableSet, - ([OFSet setWithObjects: @"baz", nil])); -} - -- (void)testIntersectSet -{ - [_mutableSet intersectSet: [OFSet setWithObjects: @"foo", @"qux", nil]]; - - OTAssertEqualObjects(_mutableSet, - ([OFSet setWithObjects: @"foo", nil])); -} - -- (void)testUnionSet -{ - [_mutableSet unionSet: [OFSet setWithObjects: @"x", @"y", nil]]; - - OTAssertEqualObjects(_mutableSet, - ([OFSet setWithObjects: @"foo", @"bar", @"baz", @"x", @"y", nil])); -} - -- (void)testRemoveAllObjects -{ - [_mutableSet removeAllObjects]; - - OTAssertEqual(_mutableSet.count, 0); -} -@end - -@implementation CustomMutableSet -- (instancetype)initWithObjects: (id const *)objects count: (size_t)count -{ - self = [super init]; - - @try { - _set = [[OFMutableSet alloc] initWithObjects: objects - count: count]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_set release]; - - [super dealloc]; -} - -- (size_t)count -{ - return _set.count; -} - -- (bool)containsObject: (id)object -{ - return [_set containsObject: object]; -} - -- (OFEnumerator *)objectEnumerator -{ - return [_set objectEnumerator]; -} - -- (void)addObject: (id)object -{ - [_set addObject: object]; -} - -- (void)removeObject: (id)object -{ - [_set removeObject: object]; -} -@end DELETED new_tests/OFMutableStringTests.h Index: new_tests/OFMutableStringTests.h ================================================================== --- new_tests/OFMutableStringTests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -#import "OFStringTests.h" - -@interface OFMutableStringTests: OFStringTests -{ - OFMutableString *_mutableString; -} -@end DELETED new_tests/OFMutableStringTests.m Index: new_tests/OFMutableStringTests.m ================================================================== --- new_tests/OFMutableStringTests.m +++ /dev/null @@ -1,408 +0,0 @@ -/* - * 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" - -#include - -#import "OFMutableStringTests.h" - -@interface CustomMutableString: OFMutableString -{ - OFMutableString *_string; -} -@end - -static OFString *const whitespace[] = { - @" \r \t\n\t \tasd \t \t\t\r\n", - @" \t\t \t\t \t \t" -}; - -@implementation OFMutableStringTests -- (Class)stringClass -{ - return [CustomMutableString class]; -} - -- (void)setUp -{ - [super setUp]; - - _mutableString = [[self.stringClass alloc] initWithString: @"täṠ€🤔"]; -} - -- (void)dealloc -{ - [_mutableString release]; - - [super dealloc]; -} - -- (void)testAppendString -{ - [_mutableString appendString: @"ö"]; - - OTAssertEqualObjects(_mutableString, @"täṠ€🤔ö"); -} - -- (void)testAppendUTF8String -{ - [_mutableString appendUTF8String: "ö"]; - - OTAssertEqualObjects(_mutableString, @"täṠ€🤔ö"); -} - -- (void)testAppendUTF8StringLength -{ - [_mutableString appendUTF8String: "\xEF\xBB\xBF" "öÖ" length: 7]; - - OTAssertEqualObjects(_mutableString, @"täṠ€🤔öÖ"); -} - -- (void)testAppendFormat -{ - [_mutableString appendFormat: @"%02X", 15]; - - OTAssertEqualObjects(_mutableString, @"täṠ€🤔0F"); -} - -- (void)testAppendCharactersLength -{ - [_mutableString appendCharacters: (OFUnichar []){ 0xF6, 0xD6 } - length: 2]; - - OTAssertEqualObjects(_mutableString, @"täṠ€🤔öÖ"); -} - -- (void)testUppercase -{ - [_mutableString uppercase]; - -#ifdef OF_HAVE_UNICODE_TABLES - OTAssertEqualObjects(_mutableString, @"TÄṠ€🤔"); -#else - OTAssertEqualObjects(_mutableString, @"TäṠ€🤔"); -#endif -} - -- (void)testLowercase -{ - [_mutableString lowercase]; - -#ifdef OF_HAVE_UNICODE_TABLES - OTAssertEqualObjects(_mutableString, @"täṡ€🤔"); -#else - OTAssertEqualObjects(_mutableString, @"täṠ€🤔"); -#endif -} - -- (void)testCapitalize -{ - OFMutableString *string = - [self.stringClass stringWithString: @"täṠ€🤔täṠ€🤔 täṠ€🤔"]; - - [string capitalize]; - -#ifdef OF_HAVE_UNICODE_TABLES - OTAssertEqualObjects(string, @"Täṡ€🤔täṡ€🤔 Täṡ€🤔"); -#else - OTAssertEqualObjects(string, @"TäṠ€🤔täṠ€🤔 TäṠ€🤔"); -#endif -} - -- (void)testInsertStringAtIndex -{ - [_mutableString insertString: @"fööbär" atIndex: 2]; - - OTAssertEqualObjects(_mutableString, @"täfööbärṠ€🤔"); -} - -- (void)testSetCharacterAtIndex -{ - [_mutableString setCharacter: 0x1F600 atIndex: 2]; - - OTAssertEqualObjects(_mutableString, @"tä😀€🤔"); -} - -- (void)testDeleteCharactersInRange -{ - [_mutableString deleteCharactersInRange: OFMakeRange(2, 2)]; - - OTAssertEqualObjects(_mutableString, @"tä🤔"); -} - -- (void)testDeleteCharactersInRangeThrowsWithOutOfRangeRange -{ - OTAssertThrowsSpecific( - [_mutableString deleteCharactersInRange: OFMakeRange(4, 2)], - OFOutOfRangeException); - - OTAssertThrowsSpecific( - [_mutableString deleteCharactersInRange: OFMakeRange(5, 1)], - OFOutOfRangeException); - - OTAssertThrowsSpecific( - [_mutableString deleteCharactersInRange: OFMakeRange(6, 0)], - OFOutOfRangeException); -} - -- (void)testReplaceCharactersInRangeWithString -{ - OFMutableString *string = - [self.stringClass stringWithString: @"𝄞öööbä€"]; - - [string replaceCharactersInRange: OFMakeRange(1, 3) - withString: @"äöüß"]; - OTAssertEqualObjects(string, @"𝄞äöüßbä€"); - - [string replaceCharactersInRange: OFMakeRange(4, 2) withString: @"b"]; - OTAssertEqualObjects(string, @"𝄞äöübä€"); - - [string replaceCharactersInRange: OFMakeRange(0, 7) withString: @""]; - OTAssertEqualObjects(string, @""); -} - -- (void)testReplaceCharactersInRangeWithStringFailsWithOutOfRangeRange -{ - OTAssertThrowsSpecific( - [_mutableString replaceCharactersInRange: OFMakeRange(4, 2) - withString: @"abc"], - OFOutOfRangeException); - - OTAssertThrowsSpecific( - [_mutableString replaceCharactersInRange: OFMakeRange(5, 1) - withString: @"abc"], - OFOutOfRangeException); - - OTAssertThrowsSpecific( - [_mutableString replaceCharactersInRange: OFMakeRange(6, 0) - withString: @""], - OFOutOfRangeException); -} - -- (void)testReplaceOccurrencesOfStringWithString -{ - OFMutableString *string; - - string = [self.stringClass stringWithString: @"asd fo asd fofo asd"]; - [string replaceOccurrencesOfString: @"fo" withString: @"foo"]; - OTAssertEqualObjects(string, @"asd foo asd foofoo asd"); - - string = [self.stringClass stringWithString: @"XX"]; - [string replaceOccurrencesOfString: @"X" withString: @"XX"]; - OTAssertEqualObjects(string, @"XXXX"); -} - -- (void)testReplaceOccurrencesOfStringWithStringOptionsRange -{ - OFMutableString *string = - [self.stringClass stringWithString: @"foofoobarfoobarfoo"]; - - [string replaceOccurrencesOfString: @"oo" - withString: @"óò" - options: 0 - range: OFMakeRange(2, 15)]; - OTAssertEqualObjects(string, @"foofóòbarfóòbarfoo"); -} - -- (void) - testReplaceOccurrencesOfStringWithStringOptionsRangeThrowsWithOutOfRangeRange -{ - OTAssertThrowsSpecific( - [_mutableString replaceOccurrencesOfString: @"t" - withString: @"abc" - options: 0 - range: OFMakeRange(4, 2)], - OFOutOfRangeException); - - OTAssertThrowsSpecific( - [_mutableString replaceOccurrencesOfString: @"t" - withString: @"abc" - options: 0 - range: OFMakeRange(5, 1)], - OFOutOfRangeException); - - OTAssertThrowsSpecific( - [_mutableString replaceOccurrencesOfString: @"t" - withString: @"" - options: 0 - range: OFMakeRange(6, 0)], - OFOutOfRangeException); -} - -- (void)deleteLeadingWhitespaces -{ - OFMutableString *string; - - string = [self.stringClass stringWithString: whitespace[0]]; - [string deleteLeadingWhitespaces]; - OTAssertEqualObjects(string, @"asd \t \t\t\r\n"); - - string = [self.stringClass stringWithString: whitespace[1]]; - [string deleteLeadingWhitespaces]; - OTAssertEqualObjects(string, @""); -} - -- (void)deleteTrailingWhitespaces -{ - OFMutableString *string; - - string = [self.stringClass stringWithString: whitespace[0]]; - [string deleteTrailingWhitespaces]; - OTAssertEqualObjects(string, @" \r \t\n\t \tasd"); - - string = [self.stringClass stringWithString: whitespace[1]]; - [string deleteTrailingWhitespaces]; - OTAssertEqualObjects(string, @""); -} - -- (void)deleteEnclosingWhitespaces -{ - OFMutableString *string; - - string = [self.stringClass stringWithString: whitespace[0]]; - [string deleteEnclosingWhitespaces]; - OTAssertEqualObjects(string, @"asd"); - - string = [self.stringClass stringWithString: whitespace[1]]; - [string deleteEnclosingWhitespaces]; - OTAssertEqualObjects(string, @""); -} -@end - -@implementation CustomMutableString -- (instancetype)init -{ - self = [super init]; - - @try { - _string = [[OFMutableString alloc] init]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithString: (OFString *)string -{ - self = [super init]; - - @try { - _string = [string mutableCopy]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithCString: (const char *)cString - encoding: (OFStringEncoding)encoding - length: (size_t)length -{ - self = [super init]; - - @try { - _string = [[OFMutableString alloc] initWithCString: cString - encoding: encoding - length: length]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithUTF16String: (const OFChar16 *)UTF16String - length: (size_t)length - byteOrder: (OFByteOrder)byteOrder -{ - self = [super init]; - - @try { - _string = [[OFMutableString alloc] - initWithUTF16String: UTF16String - length: length - byteOrder: byteOrder]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithUTF32String: (const OFChar32 *)UTF32String - length: (size_t)length - byteOrder: (OFByteOrder)byteOrder -{ - self = [super init]; - - @try { - _string = [[OFMutableString alloc] - initWithUTF32String: UTF32String - length: length - byteOrder: byteOrder]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithFormat: (OFConstantString *)format - arguments: (va_list)arguments -{ - self = [super init]; - - @try { - _string = [[OFMutableString alloc] initWithFormat: format - arguments: arguments]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_string release]; - - [super dealloc]; -} - -- (OFUnichar)characterAtIndex: (size_t)idx -{ - return [_string characterAtIndex: idx]; -} - -- (size_t)length -{ - return _string.length; -} - -- (void)replaceCharactersInRange: (OFRange)range - withString: (OFString *)string -{ - [_string replaceCharactersInRange: range withString: string]; -} -@end DELETED new_tests/OFMutableUTF8StringTests.m Index: new_tests/OFMutableUTF8StringTests.m ================================================================== --- new_tests/OFMutableUTF8StringTests.m +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 "OFMutableStringTests.h" - -#import "OFMutableUTF8String.h" - -@interface OFMutableUTF8StringTests: OFMutableStringTests -@end - -@implementation OFMutableUTF8StringTests -- (Class)arrayClass -{ - return [OFMutableUTF8String class]; -} -@end DELETED new_tests/OFNotificationCenterTests.m Index: new_tests/OFNotificationCenterTests.m ================================================================== --- new_tests/OFNotificationCenterTests.m +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -static const OFNotificationName notificationName = - @"OFNotificationCenterTestName"; -static const OFNotificationName otherNotificationName = - @"OFNotificationCenterTestOtherName"; - -@interface OFNotificationCenterTests: OTTestCase -@end - -@interface OFNotificationCenterTestClass: OFObject -{ -@public - id _expectedObject; - int _received; -} - -- (void)handleNotification: (OFNotification *)notification; -@end - -@implementation OFNotificationCenterTestClass -- (void)handleNotification: (OFNotification *)notification -{ - OFEnsure([notification.name isEqual: notificationName]); - OFEnsure(_expectedObject == nil || - notification.object == _expectedObject); - - _received++; -} -@end - -@implementation OFNotificationCenterTests -- (void)testNotificationCenter -{ - OFNotificationCenter *center = [OFNotificationCenter defaultCenter]; - OFNotificationCenterTestClass *test1, *test2, *test3, *test4; - OFNotification *notification; - - test1 = [[[OFNotificationCenterTestClass alloc] init] autorelease]; - test1->_expectedObject = self; - test2 = [[[OFNotificationCenterTestClass alloc] init] autorelease]; - test3 = [[[OFNotificationCenterTestClass alloc] init] autorelease]; - test3->_expectedObject = self; - test4 = [[[OFNotificationCenterTestClass alloc] init] autorelease]; - - /* First one intentionally added twice to test deduplication. */ - [center addObserver: test1 - selector: @selector(handleNotification:) - name: notificationName - object: self]; - [center addObserver: test1 - selector: @selector(handleNotification:) - name: notificationName - object: self]; - [center addObserver: test2 - selector: @selector(handleNotification:) - name: notificationName - object: nil]; - [center addObserver: test3 - selector: @selector(handleNotification:) - name: otherNotificationName - object: self]; - [center addObserver: test4 - selector: @selector(handleNotification:) - name: otherNotificationName - object: nil]; - - notification = [OFNotification notificationWithName: notificationName - object: nil]; - [center postNotification: notification]; - OTAssertEqual(test1->_received, 0); - OTAssertEqual(test2->_received, 1); - OTAssertEqual(test3->_received, 0); - OTAssertEqual(test4->_received, 0); - - notification = [OFNotification notificationWithName: notificationName - object: self]; - [center postNotification: notification]; - OTAssertEqual(test1->_received, 1); - OTAssertEqual(test2->_received, 2); - OTAssertEqual(test3->_received, 0); - OTAssertEqual(test4->_received, 0); - - notification = [OFNotification notificationWithName: notificationName - object: @"foo"]; - [center postNotification: notification]; - OTAssertEqual(test1->_received, 1); - OTAssertEqual(test2->_received, 3); - OTAssertEqual(test3->_received, 0); - OTAssertEqual(test4->_received, 0); - -#ifdef OF_HAVE_BLOCKS - __block bool received = false; - id handle; - - notification = [OFNotification notificationWithName: notificationName - object: self]; - handle = [center addObserverForName: notificationName - object: self - usingBlock: ^ (OFNotification *notification_) { - OTAssertEqual(notification_, notification); - OTAssertFalse(received); - received = true; - }]; - [center postNotification: notification]; - OTAssertTrue(received); - OTAssertEqual(test1->_received, 2); - OTAssertEqual(test2->_received, 4); - OTAssertEqual(test3->_received, 0); - OTAssertEqual(test4->_received, 0); - - /* Act like the block test didn't happen. */ - [center removeObserver: handle]; - test1->_received--; - test2->_received--; -#endif - - [center removeObserver: test1 - selector: @selector(handleNotification:) - name: notificationName - object: self]; - [center removeObserver: test2 - selector: @selector(handleNotification:) - name: notificationName - object: nil]; - [center removeObserver: test3 - selector: @selector(handleNotification:) - name: otherNotificationName - object: self]; - [center removeObserver: test4 - selector: @selector(handleNotification:) - name: otherNotificationName - object: nil]; - - notification = [OFNotification notificationWithName: notificationName - object: self]; - [center postNotification: notification]; - OTAssertEqual(test1->_received, 1); - OTAssertEqual(test2->_received, 3); - OTAssertEqual(test3->_received, 0); - OTAssertEqual(test4->_received, 0); -} -@end DELETED new_tests/OFNumberTests.m Index: new_tests/OFNumberTests.m ================================================================== --- new_tests/OFNumberTests.m +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFNumberTests: OTTestCase -{ - OFNumber *_number; -} -@end - -@implementation OFNumberTests -- (void)setUp -{ - [super setUp]; - - _number = [[OFNumber alloc] initWithLongLong: 123456789]; -} - -- (void)dealloc -{ - [_number release]; - - [super dealloc]; -} - -- (void)testIsEqual -{ - OTAssertEqualObjects(_number, [OFNumber numberWithLong: 123456789]); -} - -- (void)testHash -{ - OTAssertEqual(_number.hash, - [[OFNumber numberWithLong: 123456789] hash]); -} - -- (void)testCharValue -{ - OTAssertEqual(_number.charValue, 21); -} - -- (void)testDoubleValue -{ - OTAssertEqual(_number.doubleValue, 123456789.L); -} - -- (void)testSignedCharMinAndMaxUnmodified -{ - OTAssertEqual([[OFNumber numberWithChar: SCHAR_MIN] charValue], - SCHAR_MIN); - OTAssertEqual([[OFNumber numberWithChar: SCHAR_MAX] charValue], - SCHAR_MAX); -} - -- (void)testShortMinAndMaxUnmodified -{ - OTAssertEqual([[OFNumber numberWithShort: SHRT_MIN] shortValue], - SHRT_MIN); - OTAssertEqual([[OFNumber numberWithShort: SHRT_MAX] shortValue], - SHRT_MAX); -} - -- (void)testIntMinAndMaxUnmodified -{ - OTAssertEqual([[OFNumber numberWithInt: INT_MIN] intValue], INT_MIN); - OTAssertEqual([[OFNumber numberWithInt: INT_MAX] intValue], INT_MAX); -} - -- (void)testLongMinAndMaxUnmodified -{ - OTAssertEqual([[OFNumber numberWithLong: LONG_MIN] longValue], - LONG_MIN); - OTAssertEqual([[OFNumber numberWithLong: LONG_MAX] longValue], - LONG_MAX);; -} - -- (void)testLongLongMinAndMaxUnmodified -{ - OTAssertEqual([[OFNumber numberWithLongLong: LLONG_MIN] longLongValue], - LLONG_MIN); - OTAssertEqual([[OFNumber numberWithLongLong: LLONG_MAX] longLongValue], - LLONG_MAX); -} - -- (void)testUnsignedCharMaxUnmodified -{ - OTAssertEqual([[OFNumber numberWithUnsignedChar: UCHAR_MAX] - unsignedCharValue], UCHAR_MAX); -} - -- (void)testUnsignedShortMaxUnmodified -{ - OTAssertEqual([[OFNumber numberWithUnsignedShort: USHRT_MAX] - unsignedShortValue], USHRT_MAX); -} - -- (void)testUnsignedIntMaxUnmodified -{ - OTAssertEqual([[OFNumber numberWithUnsignedInt: UINT_MAX] - unsignedIntValue], UINT_MAX); -} - -- (void)testUnsignedLongMaxUnmodified -{ - OTAssertEqual([[OFNumber numberWithUnsignedLong: ULONG_MAX] - unsignedLongValue], ULONG_MAX); -} - -- (void)testUnsignedLongLongMaxUnmodified -{ - OTAssertEqual([[OFNumber numberWithUnsignedLongLong: ULLONG_MAX] - unsignedLongLongValue], ULLONG_MAX); -} -@end DELETED new_tests/OFObjectTests.m Index: new_tests/OFObjectTests.m ================================================================== --- new_tests/OFObjectTests.m +++ /dev/null @@ -1,261 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface MyObject: 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 - -@interface OFObjectTests: OTTestCase -{ - MyObject *_myObject; -} -@end - -@implementation OFObjectTests -- (void)setUp -{ - [super setUp]; - - _myObject = [[MyObject alloc] init]; -} - -- (void)dealloc -{ - [_myObject release]; - - [super dealloc]; -} - -- (void)testClassDescription -{ - OTAssertEqualObjects([OFObject description], @"OFObject"); - OTAssertEqualObjects([MyObject description], @"MyObject"); -} - -- (void)testInstanceDescription -{ - OFObject *object = [[[OFObject alloc] init] autorelease]; - - OTAssertEqualObjects(object.description, @""); - OTAssertEqualObjects(_myObject.description, @""); -} - -- (void)testValueForKey -{ - _myObject.objectValue = @"Hello"; - _myObject.classValue = _myObject.class; - - OTAssertEqualObjects([_myObject valueForKey: @"objectValue"], @"Hello"); - OTAssertEqualObjects([_myObject valueForKey: @"classValue"], - _myObject.class); - OTAssertEqualObjects([_myObject valueForKey: @"class"], - _myObject.class); -} - -- (void)testValueForKeyWithUndefinedKeyThrows -{ - OTAssertThrowsSpecific([_myObject valueForKey: @"undefined"], - OFUndefinedKeyException); -} - -- (void)testSetValueForKey -{ - [_myObject setValue: @"World" forKey: @"objectValue"]; - [_myObject setValue: [OFObject class] forKey: @"classValue"]; - - OTAssertEqualObjects(_myObject.objectValue, @"World"); - OTAssertEqualObjects(_myObject.classValue, [OFObject class]); -} - -- (void)testSetValueWithUndefinedKeyThrows -{ - OTAssertThrowsSpecific([_myObject setValue: @"x" forKey: @"undefined"], - OFUndefinedKeyException); -} - -- (void)testAutoWrappingOfValueForKey -{ - _myObject.boolValue = 1; - _myObject.charValue = 2; - _myObject.shortValue = 3; - _myObject.intValue = 4; - _myObject.longValue = 5; - _myObject.longLongValue = 6; - _myObject.unsignedCharValue = 7; - _myObject.unsignedShortValue = 8; - _myObject.unsignedIntValue = 9; - _myObject.unsignedLongValue = 10; - _myObject.unsignedLongLongValue = 11; - _myObject.floatValue = 12; - _myObject.doubleValue = 13; - - OTAssertEqualObjects([_myObject valueForKey: @"boolValue"], - [OFNumber numberWithBool: 1]); - OTAssertEqualObjects([_myObject valueForKey: @"charValue"], - [OFNumber numberWithChar: 2]); - OTAssertEqualObjects([_myObject valueForKey: @"shortValue"], - [OFNumber numberWithShort: 3]); - OTAssertEqualObjects([_myObject valueForKey: @"intValue"], - [OFNumber numberWithInt: 4]); - OTAssertEqualObjects([_myObject valueForKey: @"longValue"], - [OFNumber numberWithLong: 5]); - OTAssertEqualObjects([_myObject valueForKey: @"longLongValue"], - [OFNumber numberWithLongLong: 6]); - OTAssertEqualObjects([_myObject valueForKey: @"unsignedCharValue"], - [OFNumber numberWithUnsignedChar: 7]); - OTAssertEqualObjects([_myObject valueForKey: @"unsignedShortValue"], - [OFNumber numberWithUnsignedShort: 8]); - OTAssertEqualObjects([_myObject valueForKey: @"unsignedIntValue"], - [OFNumber numberWithUnsignedInt: 9]); - OTAssertEqualObjects([_myObject valueForKey: @"unsignedLongValue"], - [OFNumber numberWithUnsignedLong: 10]); - OTAssertEqualObjects([_myObject valueForKey: @"unsignedLongLongValue"], - [OFNumber numberWithUnsignedLongLong: 11]); - OTAssertEqualObjects([_myObject valueForKey: @"floatValue"], - [OFNumber numberWithFloat: 12]); - OTAssertEqualObjects([_myObject valueForKey: @"doubleValue"], - [OFNumber numberWithDouble: 13]); -} - -- (void)testAutoWrappingOfSetValueForKey -{ - [_myObject setValue: [OFNumber numberWithBool: 0] - forKey: @"boolValue"]; - [_myObject setValue: [OFNumber numberWithChar: 10] - forKey: @"charValue"]; - [_myObject setValue: [OFNumber numberWithShort: 20] - forKey: @"shortValue"]; - [_myObject setValue: [OFNumber numberWithInt: 30] - forKey: @"intValue"]; - [_myObject setValue: [OFNumber numberWithLong: 40] - forKey: @"longValue"]; - [_myObject setValue: [OFNumber numberWithLongLong: 50] - forKey: @"longLongValue"]; - [_myObject setValue: [OFNumber numberWithUnsignedChar: 60] - forKey: @"unsignedCharValue"]; - [_myObject setValue: [OFNumber numberWithUnsignedShort: 70] - forKey: @"unsignedShortValue"]; - [_myObject setValue: [OFNumber numberWithUnsignedInt: 80] - forKey: @"unsignedIntValue"]; - [_myObject setValue: [OFNumber numberWithUnsignedLong: 90] - forKey: @"unsignedLongValue"]; - [_myObject setValue: [OFNumber numberWithUnsignedLongLong: 100] - forKey: @"unsignedLongLongValue"]; - [_myObject setValue: [OFNumber numberWithFloat: 110] - forKey: @"floatValue"]; - [_myObject setValue: [OFNumber numberWithDouble: 120] - forKey: @"doubleValue"]; - - OTAssertEqual(_myObject.isBoolValue, 0); - OTAssertEqual(_myObject.charValue, 10); - OTAssertEqual(_myObject.shortValue, 20); - OTAssertEqual(_myObject.intValue, 30); - OTAssertEqual(_myObject.longValue, 40); - OTAssertEqual(_myObject.longLongValue, 50); - OTAssertEqual(_myObject.unsignedCharValue, 60); - OTAssertEqual(_myObject.unsignedShortValue, 70); - OTAssertEqual(_myObject.unsignedIntValue, 80); - OTAssertEqual(_myObject.unsignedLongValue, 90); - OTAssertEqual(_myObject.unsignedLongLongValue, 100); - OTAssertEqual(_myObject.floatValue, 110); - OTAssertEqual(_myObject.doubleValue, 120); -} - -- (void)testSetValueForKeyWithNilThrows -{ - OTAssertThrowsSpecific( - [_myObject setValue: (id _Nonnull)nil forKey: @"intValue"], - OFInvalidArgumentException); -} - -- (void)testValueForKeyPath -{ - _myObject.objectValue = [[[MyObject alloc] init] autorelease]; - [_myObject.objectValue setObjectValue: - [[[MyObject alloc] init] autorelease]]; - [[_myObject.objectValue objectValue] setDoubleValue: 0.5]; - - OTAssertEqual([[_myObject valueForKeyPath: - @"objectValue.objectValue.doubleValue"] doubleValue], 0.5); -} - -- (void)testSetValueForKeyPath -{ - _myObject.objectValue = [[[MyObject alloc] init] autorelease]; - [_myObject.objectValue setObjectValue: - [[[MyObject alloc] init] autorelease]]; - [_myObject setValue: [OFNumber numberWithDouble: 0.75] - forKeyPath: @"objectValue.objectValue.doubleValue"]; - - OTAssertEqual([[_myObject.objectValue objectValue] doubleValue], 0.75); -} -@end - -@implementation MyObject -@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 DELETED new_tests/OFPBKDF2Tests.m Index: new_tests/OFPBKDF2Tests.m ================================================================== --- new_tests/OFPBKDF2Tests.m +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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" - -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFPBKDF2Tests: OTTestCase -{ - OFHMAC *_HMAC; -} -@end - -@implementation OFPBKDF2Tests -- (void)setUp -{ - [super setUp]; - - _HMAC = [[OFHMAC alloc] initWithHashClass: [OFSHA1Hash class] - allowsSwappableMemory: true]; -} - -- (void)dealloc -{ - [_HMAC release]; - - [super dealloc]; -} - -/* Test vectors from RFC 6070 */ - -- (void)testRFC6070TestVector1 -{ - unsigned char key[25]; - - OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = _HMAC, - .iterations = 1, - .salt = (unsigned char *)"salt", - .saltLength = 4, - .password = "password", - .passwordLength = 8, - .key = key, - .keyLength = 20, - .allowsSwappableMemory = true - }); - - OTAssertEqual(memcmp(key, "\x0C\x60\xC8\x0F\x96\x1F\x0E\x71\xF3\xA9\xB5" - "\x24\xAF\x60\x12\x06\x2F\xE0\x37\xA6", 20), 0); -} - -- (void)testRFC6070TestVector2 -{ - unsigned char key[25]; - - OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = _HMAC, - .iterations = 2, - .salt = (unsigned char *)"salt", - .saltLength = 4, - .password = "password", - .passwordLength = 8, - .key = key, - .keyLength = 20, - .allowsSwappableMemory = true - }); - - OTAssertEqual(memcmp(key, "\xEA\x6C\x01\x4D\xC7\x2D\x6F\x8C\xCD\x1E\xD9" - "\x2A\xCE\x1D\x41\xF0\xD8\xDE\x89\x57", 20), 0); -} - -- (void)testRFC6070TestVector3 -{ - unsigned char key[25]; - - OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = _HMAC, - .iterations = 4096, - .salt = (unsigned char *)"salt", - .saltLength = 4, - .password = "password", - .passwordLength = 8, - .key = key, - .keyLength = 20, - .allowsSwappableMemory = true - }); - - OTAssertEqual(memcmp(key, "\x4B\x00\x79\x01\xB7\x65\x48\x9A\xBE\xAD\x49" - "\xD9\x26\xF7\x21\xD0\x65\xA4\x29\xC1", 20), 0); -} - -#if 0 -/* This test takes too long, even on a fast machine. */ -- (void)testRFC6070TestVector4 -{ - unsigned char key[25]; - - OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = _HMAC, - .iterations = 16777216, - .salt = (unsigned char *)"salt", - .saltLength = 4, - .password = "password", - .passwordLength = 8, - .key = key, - .keyLength = 20, - .allowsSwappableMemory = true - }); - - OTAssertEqual(memcmp(key, "\xEE\xFE\x3D\x61\xCD\x4D\xA4\xE4\xE9\x94\x5B" - "\x3D\x6B\xA2\x15\x8C\x26\x34\xE9\x84", 20), 0); -} -#endif - -- (void)testRFC6070TestVector5 -{ - unsigned char key[25]; - - OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = _HMAC, - .iterations = 4096, - .salt = (unsigned char *)"saltSALTsaltSALTsalt" - "SALTsaltSALTsalt", - .saltLength = 36, - .password = "passwordPASSWORDpassword", - .passwordLength = 24, - .key = key, - .keyLength = 25, - .allowsSwappableMemory = true - }); - - OTAssertEqual(memcmp(key, "\x3D\x2E\xEC\x4F\xE4\x1C\x84\x9B\x80\xC8\xD8" - "\x36\x62\xC0\xE4\x4A\x8B\x29\x1A\x96\x4C\xF2\xF0\x70\x38", 25), 0); -} - -- (void)testRFC6070TestVector6 -{ - unsigned char key[25]; - - OFPBKDF2((OFPBKDF2Parameters){ - .HMAC = _HMAC, - .iterations = 4096, - .salt = (unsigned char *)"sa\0lt", - .saltLength = 5, - .password = "pass\0word", - .passwordLength = 9, - .key = key, - .keyLength = 16, - .allowsSwappableMemory = true - }); - - OTAssertEqual(memcmp(key, "\x56\xFA\x6A\xA7\x55\x48\x09\x9D\xCC\x37\xD7" - "\xF0\x34\x25\xE0\xC3", 16), 0); -} -@end DELETED new_tests/OFPluginTests.m Index: new_tests/OFPluginTests.m ================================================================== --- new_tests/OFPluginTests.m +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -#import "plugin/TestPlugin.h" - -@interface OFPluginTests: OTTestCase -@end - -@implementation OFPluginTests -- (void)testPlugin -{ - TestPlugin *test = nil; - OFString *path; - OFPlugin *plugin; - Class (*class)(void); - -#ifndef OF_IOS - path = [OFPlugin pathForName: @"plugin/TestPlugin"]; -#else - path = [OFPlugin pathForName: @"PlugIns/TestPlugin"]; -#endif - OTAssertNotNil(path); - - plugin = [OFPlugin pluginWithPath: path]; - OTAssertNotNil(plugin); - - class = (Class (*)(void))(uintptr_t)[plugin addressForSymbol: @"class"]; - OTAssert(class != NULL); - - @try { - test = [[class() alloc] init]; - OTAssertEqual([test test: 1234], 2468); - } @finally { - [test release]; - } -} -@end DELETED new_tests/OFPropertyListTests.m Index: new_tests/OFPropertyListTests.m ================================================================== --- new_tests/OFPropertyListTests.m +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFPropertyListTests: OTTestCase -@end - -#define PLIST(x) \ - @"" \ - @"" \ - @"\n" \ - x @"\n" \ - @"" - -@implementation OFPropertyListTests -- (void)testObjectByParsingPropertyList -{ - OFArray *array = [OFArray arrayWithObjects: - @"Hello", - [OFData dataWithItems: "World!" count: 6], - [OFDate dateWithTimeIntervalSince1970: 1521030896], - [OFNumber numberWithBool: true], - [OFNumber numberWithBool: false], - [OFNumber numberWithFloat: 12.25f], - [OFNumber numberWithInt: -10], - nil]; - - OTAssertEqualObjects([PLIST( - @"Hello") objectByParsingPropertyList], - @"Hello"); - OTAssertEqualObjects([PLIST( - @"" - @" Hello" - @" V29ybGQh" - @" 2018-03-14T12:34:56Z" - @" " - @" " - @" 12.25" - @" -10" - @"") objectByParsingPropertyList], - array); - OTAssertEqualObjects([PLIST( - @"" - @" array" - @" " - @" Hello" - @" V29ybGQh" - @" 2018-03-14T12:34:56Z" - @" " - @" " - @" 12.25" - @" -10" - @" " - @" foo" - @" bar" - @"") objectByParsingPropertyList], - ([OFDictionary dictionaryWithKeysAndObjects: - @"array", array, - @"foo", @"bar", - nil])); -} - -- (void)testDetectUnsupportedVersion -{ - OTAssertThrowsSpecific( - [[PLIST(@"") - stringByReplacingOccurrencesOfString: @"1.0" - withString: @"1.1"] - objectByParsingPropertyList], - OFUnsupportedVersionException); -} - -- (void)testDetectInvalidFormat -{ - OTAssertThrowsSpecific( - [PLIST(@"") objectByParsingPropertyList], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [PLIST(@"") objectByParsingPropertyList], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [PLIST(@"") objectByParsingPropertyList], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [PLIST(@"") - objectByParsingPropertyList], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [PLIST(@"") - objectByParsingPropertyList], - OFInvalidFormatException); -} -@end DELETED new_tests/OFSPXSocketTests.m Index: new_tests/OFSPXSocketTests.m ================================================================== --- new_tests/OFSPXSocketTests.m +++ /dev/null @@ -1,233 +0,0 @@ -/* - * 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" - -#include -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFSPXSocketTests: OTTestCase -{ - OFSPXSocket *_sockServer; - OFSocketAddress _addrServer; -} -@end - -@interface SPXSocketDelegate: OFObject -{ -@public - OFSequencedPacketSocket *_expectedServerSocket; - OFSPXSocket *_expectedClientSocket; - unsigned char _expectedNode[IPX_NODE_LEN]; - uint32_t _expectedNetwork; - uint16_t _expectedPort; - bool _accepted; - bool _connected; -} -@end - -@implementation OFSPXSocketTests -- (void)setUp -{ - const unsigned char zeroNode[IPX_NODE_LEN] = { 0 }; - - _sockServer = [[OFSPXSocket alloc] init]; - - @try { - _addrServer = [_sockServer bindToNetwork: 0 - node: zeroNode - port: 0]; - } @catch (OFBindSocketFailedException *e) { - switch (e.errNo) { - case EAFNOSUPPORT: - OTSkip(@"IPX unsupported"); - case ESOCKTNOSUPPORT: - OTSkip(@"SPX unsupported"); - case EADDRNOTAVAIL: - OTSkip(@"IPX not configured"); - default: - @throw e; - } - } -} - -- (void)dealloc -{ - [_sockServer release]; - - [super dealloc]; -} - -- (void)testSPXSocket -{ - OFSPXSocket *sockClient, *sockAccepted; - const OFSocketAddress *addrAccepted; - uint32_t network; - unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN]; - uint16_t port; - OFDictionary *networkInterfaces; - char buffer[5]; - - sockClient = [OFSPXSocket socket]; - - network = OFSocketAddressIPXNetwork(&_addrServer); - OFSocketAddressGetIPXNode(&_addrServer, node); - port = OFSocketAddressIPXPort(&_addrServer); - - [_sockServer listen]; - - /* - * Find any network interface with IPX and send to it. Any should be - * fine since we bound to 0.0. - */ - networkInterfaces = [OFSystemInfo networkInterfaces]; - for (OFString *name in networkInterfaces) { - OFNetworkInterface interface = [networkInterfaces - objectForKey: name]; - OFData *addresses = [interface - objectForKey: OFNetworkInterfaceIPXAddresses]; - - if (addresses.count == 0) - continue; - - network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]); - OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); - } - - [sockClient connectToNetwork: network node: node port: port]; - - sockAccepted = [_sockServer accept]; - [sockAccepted sendBuffer: "Hello" length: 5]; - - OTAssertEqual([sockClient receiveIntoBuffer: buffer length: 5], 5); - OTAssertEqual(memcmp(buffer, "Hello", 5), 0); - - addrAccepted = sockAccepted.remoteAddress; - OFSocketAddressGetIPXNode(addrAccepted, node2); - OTAssertEqual(memcmp(node, node2, IPX_NODE_LEN), 0); -} - -- (void)testAsyncSPXSocket -{ - SPXSocketDelegate *delegate = - [[[SPXSocketDelegate alloc] init] autorelease]; - uint32_t network; - unsigned char node[IPX_NODE_LEN]; - uint16_t port; - OFDictionary *networkInterfaces; - OFSPXSocket *sockClient; - - delegate->_expectedServerSocket = _sockServer; - _sockServer.delegate = delegate; - - sockClient = [OFSPXSocket socket]; - delegate->_expectedClientSocket = sockClient; - sockClient.delegate = delegate; - - [_sockServer listen]; - [_sockServer asyncAccept]; - - network = OFSocketAddressIPXNetwork(&_addrServer); - OFSocketAddressGetIPXNode(&_addrServer, node); - port = OFSocketAddressIPXPort(&_addrServer); - - /* - * Find any network interface with IPX and send to it. Any should be - * fine since we bound to 0.0. - */ - networkInterfaces = [OFSystemInfo networkInterfaces]; - for (OFString *name in networkInterfaces) { - OFNetworkInterface interface = [networkInterfaces - objectForKey: name]; - OFData *addresses = [interface - objectForKey: OFNetworkInterfaceIPXAddresses]; - - if (addresses.count == 0) - continue; - - network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]); - OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); - } - - delegate->_expectedNetwork = network = - OFSocketAddressIPXNetwork(&_addrServer); - OFSocketAddressGetIPXNode(&_addrServer, node); - memcpy(delegate->_expectedNode, node, IPX_NODE_LEN); - delegate->_expectedPort = port = OFSocketAddressIPXPort(&_addrServer); - - @try { - [sockClient asyncConnectToNetwork: network - node: node - port: port]; - - [[OFRunLoop mainRunLoop] runUntilDate: - [OFDate dateWithTimeIntervalSinceNow: 2]]; - - OTAssertTrue(delegate->_accepted); - OTAssertTrue(delegate->_connected); - } @catch (OFObserveKernelEventsFailedException *e) { - /* - * Make sure it doesn't stay in the run loop and throws again - * next time we run the run loop. - */ - [sockClient cancelAsyncRequests]; - [_sockServer cancelAsyncRequests]; - - switch (e.errNo) { - case ENOTSOCK: - OTSkip(@"select() not supported for SPX"); - default: - @throw e; - } - } -} -@end - -@implementation SPXSocketDelegate -- (bool)socket: (OFSequencedPacketSocket *)sock - didAcceptSocket: (OFSequencedPacketSocket *)accepted - exception: (id)exception -{ - OFEnsure(!_accepted); - - _accepted = (sock == _expectedServerSocket && accepted != nil && - exception == nil); - - if (_accepted && _connected) - [[OFRunLoop mainRunLoop] stop]; - - return false; -} - -- (void)socket: (OFSPXSocket *)sock - didConnectToNetwork: (uint32_t)network - node: (const unsigned char [IPX_NODE_LEN])node - port: (uint16_t)port - exception: (id)exception -{ - OFEnsure(!_connected); - - _connected = (sock == _expectedClientSocket && - network == _expectedNetwork && - memcmp(node, _expectedNode, IPX_NODE_LEN) == 0 && - port == _expectedPort && exception == nil); - - if (_accepted && _connected) - [[OFRunLoop mainRunLoop] stop]; -} -@end DELETED new_tests/OFSPXStreamSocketTests.m Index: new_tests/OFSPXStreamSocketTests.m ================================================================== --- new_tests/OFSPXStreamSocketTests.m +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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" - -#include -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFSPXStreamSocketTests: OTTestCase -{ - OFSPXStreamSocket *_sockServer; - OFSocketAddress _addrServer; -} -@end - -@interface SPXStreamSocketDelegate: OFObject -{ -@public - OFStreamSocket *_expectedServerSocket; - OFSPXStreamSocket *_expectedClientSocket; - uint32_t _expectedNetwork; - unsigned char _expectedNode[IPX_NODE_LEN]; - uint16_t _expectedPort; - bool _accepted; - bool _connected; -} -@end - -@implementation OFSPXStreamSocketTests -- (void)setUp -{ - const unsigned char zeroNode[IPX_NODE_LEN] = { 0 }; - - _sockServer = [[OFSPXStreamSocket alloc] init]; - - @try { - _addrServer = [_sockServer bindToNetwork: 0 - node: zeroNode - port: 0]; - } @catch (OFBindSocketFailedException *e) { - switch (e.errNo) { - case EAFNOSUPPORT: - OTSkip(@"IPX unsupported"); - case ESOCKTNOSUPPORT: - case EPROTONOSUPPORT: - OTSkip(@"SPX unsupported"); - case EADDRNOTAVAIL: - OTSkip(@"IPX not configured"); - default: - @throw e; - } - } -} - -- (void)dealloc -{ - [_sockServer release]; - - [super dealloc]; -} - -- (void)testSPXStreamSocket -{ - OFSPXStreamSocket *sockClient, *sockAccepted; - const OFSocketAddress *addrAccepted; - uint32_t network; - unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN]; - uint16_t port; - OFDictionary *networkInterfaces; - char buffer[5]; - - sockClient = [OFSPXStreamSocket socket]; - - network = OFSocketAddressIPXNetwork(&_addrServer); - OFSocketAddressGetIPXNode(&_addrServer, node); - port = OFSocketAddressIPXPort(&_addrServer); - - [_sockServer listen]; - - /* - * Find any network interface with IPX and send to it. Any should be - * fine since we bound to 0.0. - */ - networkInterfaces = [OFSystemInfo networkInterfaces]; - for (OFString *name in networkInterfaces) { - OFNetworkInterface interface = [networkInterfaces - objectForKey: name]; - OFData *addresses = [interface - objectForKey: OFNetworkInterfaceIPXAddresses]; - - if (addresses.count == 0) - continue; - - network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]); - OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); - } - - [sockClient connectToNetwork: network node: node port: port]; - - sockAccepted = [_sockServer accept]; - [sockAccepted writeBuffer: "Hello" length: 5]; - - /* Test reassembly (this would not work with OFSPXSocket) */ - OTAssertEqual([sockClient readIntoBuffer: buffer length: 2], 2); - OTAssertEqual([sockClient readIntoBuffer: buffer + 2 length: 3], 3); - OTAssertEqual(memcmp(buffer, "Hello", 5), 0); - - addrAccepted = sockAccepted.remoteAddress; - OFSocketAddressGetIPXNode(addrAccepted, node2); - OTAssertEqual(memcmp(node, node2, IPX_NODE_LEN), 0); -} - -- (void)testAsyncSPXStreamSocket -{ - SPXStreamSocketDelegate *delegate = - [[[SPXStreamSocketDelegate alloc] init] autorelease]; - uint32_t network; - unsigned char node[IPX_NODE_LEN]; - uint16_t port; - OFDictionary *networkInterfaces; - OFSPXStreamSocket *sockClient; - - delegate->_expectedServerSocket = _sockServer; - _sockServer.delegate = delegate; - - sockClient = [OFSPXStreamSocket socket]; - delegate->_expectedClientSocket = sockClient; - sockClient.delegate = delegate; - - [_sockServer listen]; - [_sockServer asyncAccept]; - - network = OFSocketAddressIPXNetwork(&_addrServer); - OFSocketAddressGetIPXNode(&_addrServer, node); - port = OFSocketAddressIPXPort(&_addrServer); - - /* - * Find any network interface with IPX and send to it. Any should be - * fine since we bound to 0.0. - */ - networkInterfaces = [OFSystemInfo networkInterfaces]; - for (OFString *name in networkInterfaces) { - OFNetworkInterface interface = [networkInterfaces - objectForKey: name]; - OFData *addresses = [interface - objectForKey: OFNetworkInterfaceIPXAddresses]; - - if (addresses.count == 0) - continue; - - network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]); - OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); - } - - delegate->_expectedNetwork = network = - OFSocketAddressIPXNetwork(&_addrServer); - OFSocketAddressGetIPXNode(&_addrServer, node); - memcpy(delegate->_expectedNode, node, IPX_NODE_LEN); - delegate->_expectedPort = port = OFSocketAddressIPXPort(&_addrServer); - - @try { - [sockClient asyncConnectToNetwork: network - node: node - port: port]; - - [[OFRunLoop mainRunLoop] runUntilDate: - [OFDate dateWithTimeIntervalSinceNow: 2]]; - - OTAssertTrue(delegate->_accepted); - OTAssertTrue(delegate->_connected); - } @catch (OFObserveKernelEventsFailedException *e) { - /* - * Make sure it doesn't stay in the run loop and throws again - * next time we run the run loop. - */ - [sockClient cancelAsyncRequests]; - [_sockServer cancelAsyncRequests]; - - switch (e.errNo) { - case ENOTSOCK: - OTSkip(@"select() not supported for SPX"); - default: - @throw e; - } - } -} -@end - -@implementation SPXStreamSocketDelegate -- (bool)socket: (OFStreamSocket *)sock - didAcceptSocket: (OFStreamSocket *)accepted - exception: (id)exception -{ - OFEnsure(!_accepted); - - _accepted = (sock == _expectedServerSocket && accepted != nil && - exception == nil); - - if (_accepted && _connected) - [[OFRunLoop mainRunLoop] stop]; - - return false; -} - -- (void)socket: (OFSPXStreamSocket *)sock - didConnectToNetwork: (uint32_t)network - node: (const unsigned char [IPX_NODE_LEN])node - port: (uint16_t)port - exception: (id)exception -{ - OFEnsure(!_connected); - - _connected = (sock == _expectedClientSocket && - network == _expectedNetwork && - memcmp(node, _expectedNode, IPX_NODE_LEN) == 0 && - port == _expectedPort && exception == nil); - - if (_accepted && _connected) - [[OFRunLoop mainRunLoop] stop]; -} -@end DELETED new_tests/OFScryptTests.m Index: new_tests/OFScryptTests.m ================================================================== --- new_tests/OFScryptTests.m +++ /dev/null @@ -1,263 +0,0 @@ -/* - * 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" - -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFScryptTests: OTTestCase -@end - -/* Test vectors form RFC 7914 */ -static const unsigned char salsa20Input[64] = { - 0x7E, 0x87, 0x9A, 0x21, 0x4F, 0x3E, 0xC9, 0x86, 0x7C, 0xA9, 0x40, 0xE6, - 0x41, 0x71, 0x8F, 0x26, 0xBA, 0xEE, 0x55, 0x5B, 0x8C, 0x61, 0xC1, 0xB5, - 0x0D, 0xF8, 0x46, 0x11, 0x6D, 0xCD, 0x3B, 0x1D, 0xEE, 0x24, 0xF3, 0x19, - 0xDF, 0x9B, 0x3D, 0x85, 0x14, 0x12, 0x1E, 0x4B, 0x5A, 0xC5, 0xAA, 0x32, - 0x76, 0x02, 0x1D, 0x29, 0x09, 0xC7, 0x48, 0x29, 0xED, 0xEB, 0xC6, 0x8D, - 0xB8, 0xB8, 0xC2, 0x5E -}; -static const unsigned char salsa20Output[64] = { - 0xA4, 0x1F, 0x85, 0x9C, 0x66, 0x08, 0xCC, 0x99, 0x3B, 0x81, 0xCA, 0xCB, - 0x02, 0x0C, 0xEF, 0x05, 0x04, 0x4B, 0x21, 0x81, 0xA2, 0xFD, 0x33, 0x7D, - 0xFD, 0x7B, 0x1C, 0x63, 0x96, 0x68, 0x2F, 0x29, 0xB4, 0x39, 0x31, 0x68, - 0xE3, 0xC9, 0xE6, 0xBC, 0xFE, 0x6B, 0xC5, 0xB7, 0xA0, 0x6D, 0x96, 0xBA, - 0xE4, 0x24, 0xCC, 0x10, 0x2C, 0x91, 0x74, 0x5C, 0x24, 0xAD, 0x67, 0x3D, - 0xC7, 0x61, 0x8F, 0x81 -}; -static const union { - unsigned char uc[128]; - uint32_t u32[32]; -} blockMixInput = { .uc = { - 0xF7, 0xCE, 0x0B, 0x65, 0x3D, 0x2D, 0x72, 0xA4, 0x10, 0x8C, 0xF5, 0xAB, - 0xE9, 0x12, 0xFF, 0xDD, 0x77, 0x76, 0x16, 0xDB, 0xBB, 0x27, 0xA7, 0x0E, - 0x82, 0x04, 0xF3, 0xAE, 0x2D, 0x0F, 0x6F, 0xAD, 0x89, 0xF6, 0x8F, 0x48, - 0x11, 0xD1, 0xE8, 0x7B, 0xCC, 0x3B, 0xD7, 0x40, 0x0A, 0x9F, 0xFD, 0x29, - 0x09, 0x4F, 0x01, 0x84, 0x63, 0x95, 0x74, 0xF3, 0x9A, 0xE5, 0xA1, 0x31, - 0x52, 0x17, 0xBC, 0xD7, - 0x89, 0x49, 0x91, 0x44, 0x72, 0x13, 0xBB, 0x22, 0x6C, 0x25, 0xB5, 0x4D, - 0xA8, 0x63, 0x70, 0xFB, 0xCD, 0x98, 0x43, 0x80, 0x37, 0x46, 0x66, 0xBB, - 0x8F, 0xFC, 0xB5, 0xBF, 0x40, 0xC2, 0x54, 0xB0, 0x67, 0xD2, 0x7C, 0x51, - 0xCE, 0x4A, 0xD5, 0xFE, 0xD8, 0x29, 0xC9, 0x0B, 0x50, 0x5A, 0x57, 0x1B, - 0x7F, 0x4D, 0x1C, 0xAD, 0x6A, 0x52, 0x3C, 0xDA, 0x77, 0x0E, 0x67, 0xBC, - 0xEA, 0xAF, 0x7E, 0x89 -}}; -static const unsigned char blockMixOutput[128] = { - 0xA4, 0x1F, 0x85, 0x9C, 0x66, 0x08, 0xCC, 0x99, 0x3B, 0x81, 0xCA, 0xCB, - 0x02, 0x0C, 0xEF, 0x05, 0x04, 0x4B, 0x21, 0x81, 0xA2, 0xFD, 0x33, 0x7D, - 0xFD, 0x7B, 0x1C, 0x63, 0x96, 0x68, 0x2F, 0x29, 0xB4, 0x39, 0x31, 0x68, - 0xE3, 0xC9, 0xE6, 0xBC, 0xFE, 0x6B, 0xC5, 0xB7, 0xA0, 0x6D, 0x96, 0xBA, - 0xE4, 0x24, 0xCC, 0x10, 0x2C, 0x91, 0x74, 0x5C, 0x24, 0xAD, 0x67, 0x3D, - 0xC7, 0x61, 0x8F, 0x81, - 0x20, 0xED, 0xC9, 0x75, 0x32, 0x38, 0x81, 0xA8, 0x05, 0x40, 0xF6, 0x4C, - 0x16, 0x2D, 0xCD, 0x3C, 0x21, 0x07, 0x7C, 0xFE, 0x5F, 0x8D, 0x5F, 0xE2, - 0xB1, 0xA4, 0x16, 0x8F, 0x95, 0x36, 0x78, 0xB7, 0x7D, 0x3B, 0x3D, 0x80, - 0x3B, 0x60, 0xE4, 0xAB, 0x92, 0x09, 0x96, 0xE5, 0x9B, 0x4D, 0x53, 0xB6, - 0x5D, 0x2A, 0x22, 0x58, 0x77, 0xD5, 0xED, 0xF5, 0x84, 0x2C, 0xB9, 0xF1, - 0x4E, 0xEF, 0xE4, 0x25 -}; -static const unsigned char ROMixInput[128] = { - 0xF7, 0xCE, 0x0B, 0x65, 0x3D, 0x2D, 0x72, 0xA4, 0x10, 0x8C, 0xF5, 0xAB, - 0xE9, 0x12, 0xFF, 0xDD, 0x77, 0x76, 0x16, 0xDB, 0xBB, 0x27, 0xA7, 0x0E, - 0x82, 0x04, 0xF3, 0xAE, 0x2D, 0x0F, 0x6F, 0xAD, 0x89, 0xF6, 0x8F, 0x48, - 0x11, 0xD1, 0xE8, 0x7B, 0xCC, 0x3B, 0xD7, 0x40, 0x0A, 0x9F, 0xFD, 0x29, - 0x09, 0x4F, 0x01, 0x84, 0x63, 0x95, 0x74, 0xF3, 0x9A, 0xE5, 0xA1, 0x31, - 0x52, 0x17, 0xBC, 0xD7, 0x89, 0x49, 0x91, 0x44, 0x72, 0x13, 0xBB, 0x22, - 0x6C, 0x25, 0xB5, 0x4D, 0xA8, 0x63, 0x70, 0xFB, 0xCD, 0x98, 0x43, 0x80, - 0x37, 0x46, 0x66, 0xBB, 0x8F, 0xFC, 0xB5, 0xBF, 0x40, 0xC2, 0x54, 0xB0, - 0x67, 0xD2, 0x7C, 0x51, 0xCE, 0x4A, 0xD5, 0xFE, 0xD8, 0x29, 0xC9, 0x0B, - 0x50, 0x5A, 0x57, 0x1B, 0x7F, 0x4D, 0x1C, 0xAD, 0x6A, 0x52, 0x3C, 0xDA, - 0x77, 0x0E, 0x67, 0xBC, 0xEA, 0xAF, 0x7E, 0x89 -}; -static const unsigned char ROMixOutput[128] = { - 0x79, 0xCC, 0xC1, 0x93, 0x62, 0x9D, 0xEB, 0xCA, 0x04, 0x7F, 0x0B, 0x70, - 0x60, 0x4B, 0xF6, 0xB6, 0x2C, 0xE3, 0xDD, 0x4A, 0x96, 0x26, 0xE3, 0x55, - 0xFA, 0xFC, 0x61, 0x98, 0xE6, 0xEA, 0x2B, 0x46, 0xD5, 0x84, 0x13, 0x67, - 0x3B, 0x99, 0xB0, 0x29, 0xD6, 0x65, 0xC3, 0x57, 0x60, 0x1F, 0xB4, 0x26, - 0xA0, 0xB2, 0xF4, 0xBB, 0xA2, 0x00, 0xEE, 0x9F, 0x0A, 0x43, 0xD1, 0x9B, - 0x57, 0x1A, 0x9C, 0x71, 0xEF, 0x11, 0x42, 0xE6, 0x5D, 0x5A, 0x26, 0x6F, - 0xDD, 0xCA, 0x83, 0x2C, 0xE5, 0x9F, 0xAA, 0x7C, 0xAC, 0x0B, 0x9C, 0xF1, - 0xBE, 0x2B, 0xFF, 0xCA, 0x30, 0x0D, 0x01, 0xEE, 0x38, 0x76, 0x19, 0xC4, - 0xAE, 0x12, 0xFD, 0x44, 0x38, 0xF2, 0x03, 0xA0, 0xE4, 0xE1, 0xC4, 0x7E, - 0xC3, 0x14, 0x86, 0x1F, 0x4E, 0x90, 0x87, 0xCB, 0x33, 0x39, 0x6A, 0x68, - 0x73, 0xE8, 0xF9, 0xD2, 0x53, 0x9A, 0x4B, 0x8E -}; -static const unsigned char testVector1[64] = { - 0x77, 0xD6, 0x57, 0x62, 0x38, 0x65, 0x7B, 0x20, 0x3B, 0x19, 0xCA, 0x42, - 0xC1, 0x8A, 0x04, 0x97, 0xF1, 0x6B, 0x48, 0x44, 0xE3, 0x07, 0x4A, 0xE8, - 0xDF, 0xDF, 0xFA, 0x3F, 0xED, 0xE2, 0x14, 0x42, 0xFC, 0xD0, 0x06, 0x9D, - 0xED, 0x09, 0x48, 0xF8, 0x32, 0x6A, 0x75, 0x3A, 0x0F, 0xC8, 0x1F, 0x17, - 0xE8, 0xD3, 0xE0, 0xFB, 0x2E, 0x0D, 0x36, 0x28, 0xCF, 0x35, 0xE2, 0x0C, - 0x38, 0xD1, 0x89, 0x06 -}; -/* Nintendo DS does not have enough RAM for the second test vector. */ -#ifndef OF_NINTENDO_DS -static const unsigned char testVector2[64] = { - 0xFD, 0xBA, 0xBE, 0x1C, 0x9D, 0x34, 0x72, 0x00, 0x78, 0x56, 0xE7, 0x19, - 0x0D, 0x01, 0xE9, 0xFE, 0x7C, 0x6A, 0xD7, 0xCB, 0xC8, 0x23, 0x78, 0x30, - 0xE7, 0x73, 0x76, 0x63, 0x4B, 0x37, 0x31, 0x62, 0x2E, 0xAF, 0x30, 0xD9, - 0x2E, 0x22, 0xA3, 0x88, 0x6F, 0xF1, 0x09, 0x27, 0x9D, 0x98, 0x30, 0xDA, - 0xC7, 0x27, 0xAF, 0xB9, 0x4A, 0x83, 0xEE, 0x6D, 0x83, 0x60, 0xCB, 0xDF, - 0xA2, 0xCC, 0x06, 0x40 -}; -#endif -/* - * The third test vector is too expensive for m68k. - * Nintendo DS does not have enough RAM for the third test vector. - */ -#if !defined(OF_M68K) && !defined(OF_NINTENDO_DS) -static const unsigned char testVector3[64] = { - 0x70, 0x23, 0xBD, 0xCB, 0x3A, 0xFD, 0x73, 0x48, 0x46, 0x1C, 0x06, 0xCD, - 0x81, 0xFD, 0x38, 0xEB, 0xFD, 0xA8, 0xFB, 0xBA, 0x90, 0x4F, 0x8E, 0x3E, - 0xA9, 0xB5, 0x43, 0xF6, 0x54, 0x5D, 0xA1, 0xF2, 0xD5, 0x43, 0x29, 0x55, - 0x61, 0x3F, 0x0F, 0xCF, 0x62, 0xD4, 0x97, 0x05, 0x24, 0x2A, 0x9A, 0xF9, - 0xE6, 0x1E, 0x85, 0xDC, 0x0D, 0x65, 0x1E, 0x40, 0xDF, 0xCF, 0x01, 0x7B, - 0x45, 0x57, 0x58, 0x87 -}; -#endif -/* The forth test vector is too expensive to include it in the tests. */ -#if 0 -static const unsigned char testVector4[64] = { - 0x21, 0x01, 0xCB, 0x9B, 0x6A, 0x51, 0x1A, 0xAE, 0xAD, 0xDB, 0xBE, 0x09, - 0xCF, 0x70, 0xF8, 0x81, 0xEC, 0x56, 0x8D, 0x57, 0x4A, 0x2F, 0xFD, 0x4D, - 0xAB, 0xE5, 0xEE, 0x98, 0x20, 0xAD, 0xAA, 0x47, 0x8E, 0x56, 0xFD, 0x8F, - 0x4B, 0xA5, 0xD0, 0x9F, 0xFA, 0x1C, 0x6D, 0x92, 0x7C, 0x40, 0xF4, 0xC3, - 0x37, 0x30, 0x40, 0x49, 0xE8, 0xA9, 0x52, 0xFB, 0xCB, 0xF4, 0x5C, 0x6F, - 0xA7, 0x7A, 0x41, 0xA4 -}; -#endif - -@implementation OFScryptTests -- (void)testSalsa20_8Core -{ - uint32_t salsa20Buffer[16]; - - memcpy(salsa20Buffer, salsa20Input, 64); - OFSalsa20_8Core(salsa20Buffer); - OTAssertEqual(memcmp(salsa20Buffer, salsa20Output, 64), 0); -} - -- (void)testBlockMix -{ - uint32_t blockMixBuffer[32]; - - OFScryptBlockMix(blockMixBuffer, blockMixInput.u32, 1); - OTAssertEqual(memcmp(blockMixBuffer, blockMixOutput, 128), 0); -} - -- (void)testROMix -{ - uint32_t ROMixBuffer[32], ROMixTmp[17 * 32]; - - memcpy(ROMixBuffer, ROMixInput, 128); - OFScryptROMix(ROMixBuffer, 1, 16, ROMixTmp); - OTAssertEqual(memcmp(ROMixBuffer, ROMixOutput, 128), 0); -} - -- (void)testRFC7941TestVector1 -{ - unsigned char output[64]; - - OFScrypt((OFScryptParameters){ - .blockSize = 1, - .costFactor = 16, - .parallelization = 1, - .salt = (unsigned char *)"", - .saltLength = 0, - .password = "", - .passwordLength = 0, - .key = output, - .keyLength = 64, - .allowsSwappableMemory = true - }); - - OTAssertEqual(memcmp(output, testVector1, 64), 0); -} - -/* Nintendo DS does not have enough RAM for the second test vector. */ -#ifndef OF_NINTENDO_DS -- (void)testRFC7941TestVector2 -{ - unsigned char output[64]; - - OFScrypt((OFScryptParameters){ - .blockSize = 8, - .costFactor = 1024, - .parallelization = 16, - .salt = (unsigned char *)"NaCl", - .saltLength = 4, - .password = "password", - .passwordLength = 8, - .key = output, - .keyLength = 64, - .allowsSwappableMemory = true - }); - - OTAssertEqual(memcmp(output, testVector2, 64), 0); -} -#endif - -/* - * The third test vector is too expensive for m68k. - * Nintendo DS does not have enough RAM for the third test vector. - */ -#if !defined(OF_M68K) && !defined(OF_NINTENDO_DS) -- (void)testRFC7941TestVector3 -{ - unsigned char output[64]; - - OFScrypt((OFScryptParameters){ - .blockSize = 8, - .costFactor = 16384, - .parallelization = 1, - .salt = (unsigned char *)"SodiumChloride", - .saltLength = 14, - .password = "pleaseletmein", - .passwordLength = 13, - .key = output, - .keyLength = 64, - .allowsSwappableMemory = true - }); - - OTAssertEqual(memcmp(output, testVector3, 64), 0); -} -#endif - -/* The forth test vector is too expensive to include it in the tests. */ -#if 0 -- (void)testRFC7941TestVector4 -{ - unsigned char output[64]; - - OFScrypt((OFScryptParameters){ - .blockSize = 8, - .costFactor = 1048576, - .parallelization = 1, - .salt = (unsigned char *)"SodiumChloride", - .saltLength = 14, - .password = "pleaseletmein", - .passwordLength = 13, - .key = output, - .keyLength = 64, - .allowsSwappableMemory = true - }); - - OTAssertEqual(memcmp(output, testVector4, 64), 0); -} -#endif -@end DELETED new_tests/OFSetTests.h Index: new_tests/OFSetTests.h ================================================================== --- new_tests/OFSetTests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFSetTests: OTTestCase -{ - OFSet *_set; -} - -@property (readonly, nonatomic) Class setClass; -@end DELETED new_tests/OFSetTests.m Index: new_tests/OFSetTests.m ================================================================== --- new_tests/OFSetTests.m +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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 "OFSetTests.h" - -@interface CustomSet: OFSet -{ - OFSet *_set; -} -@end - -@implementation OFSetTests -- (Class)setClass -{ - return [CustomSet class]; -} - -- (void)setUp -{ - [super setUp]; - - _set = [[OFSet alloc] initWithObjects: @"foo", @"bar", @"baz", nil]; -} - -- (void)dealloc -{ - [_set release]; - - [super dealloc]; -} - -- (void)testSetWithArray -{ - OTAssertEqualObjects([self.setClass setWithArray: - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", @"foo", nil])], - _set); -} - -- (void)testIsEqual -{ - OTAssertEqualObjects(_set, - ([OFSet setWithObjects: @"foo", @"bar", @"baz", nil])); -} - -- (void)testHash -{ - OTAssertEqual(_set.hash, - [([OFSet setWithObjects: @"foo", @"bar", @"baz", nil]) hash]); -} - -- (void)testDescription -{ - OFString *description = _set.description; - - OTAssert( - [description isEqual: @"{(\n\tfoo,\n\tbar,\n\tbaz\n)}"] || - [description isEqual: @"{(\n\tfoo,\n\tbaz,\n\tbar\n)}"] || - [description isEqual: @"{(\n\tbar,\n\tfoo,\n\tbaz\n)}"] || - [description isEqual: @"{(\n\tbar,\n\tbaz,\n\tfoo\n)}"] || - [description isEqual: @"{(\n\tbaz,\n\tfoo,\n\tbar\n)}"] || - [description isEqual: @"{(\n\tbaz,\n\tbar,\n\tfoo\n)}"]); -} - -- (void)testCopy -{ - OTAssertEqualObjects([[_set copy] autorelease], _set); -} - -- (void)testIsSubsetOfSet -{ - OTAssertTrue([([OFSet setWithObjects: @"foo", nil]) - isSubsetOfSet: _set]); - OTAssertFalse([([OFSet setWithObjects: @"foo", @"Foo", nil]) - isSubsetOfSet: _set]); -} - -- (void)testIntersectsSet -{ - OTAssertTrue([([OFSet setWithObjects: @"foo", @"Foo", nil]) - intersectsSet: _set]); - OTAssertFalse([([OFSet setWithObjects: @"Foo", nil]) - intersectsSet: _set]); -} - -- (void)testEnumerator -{ - OFEnumerator *enumerator = [_set objectEnumerator]; - bool seenFoo = false, seenBar = false, seenBaz = false; - OFString *object; - - while ((object = [enumerator nextObject]) != nil) { - if ([object isEqual: @"foo"]) { - OTAssertFalse(seenFoo); - seenFoo = true; - } else if ([object isEqual: @"bar"]) { - OTAssertFalse(seenBar); - seenBar = true; - } else if ([object isEqual: @"baz"]) { - OTAssertFalse(seenBaz); - seenBaz = true; - } else - OTAssert(false, @"Unexpected object seen: %@", object); - } - - OTAssert(seenFoo && seenBar && seenBaz); -} - -- (void)testFastEnumeration -{ - bool seenFoo = false, seenBar = false, seenBaz = false; - - for (OFString *object in _set) { - if ([object isEqual: @"foo"]) { - OTAssertFalse(seenFoo); - seenFoo = true; - } else if ([object isEqual: @"bar"]) { - OTAssertFalse(seenBar); - seenBar = true; - } else if ([object isEqual: @"baz"]) { - OTAssertFalse(seenBaz); - seenBaz = true; - } else - OTAssert(false, @"Unexpected object seen: %@", object); - } - - OTAssert(seenFoo && seenBar && seenBaz); -} - -#ifdef OF_HAVE_BLOCKS -- (void)testEnumerateObjectsUsingBlock -{ - __block bool seenFoo = false, seenBar = false, seenBaz = false; - - [_set enumerateObjectsUsingBlock: ^ (id object, bool *stop) { - if ([object isEqual: @"foo"]) { - OTAssertFalse(seenFoo); - seenFoo = true; - } else if ([object isEqual: @"bar"]) { - OTAssertFalse(seenBar); - seenBar = true; - } else if ([object isEqual: @"baz"]) { - OTAssertFalse(seenBaz); - seenBaz = true; - } else - OTAssert(false, @"Unexpected object seen: %@", object); - }]; - - OTAssert(seenFoo && seenBar && seenBaz); -} - -- (void)testFilteredSetUsingBlock -{ - OFSet *filteredSet = [_set filteredSetUsingBlock: ^ (id object) { - return [object hasPrefix: @"ba"]; - }]; - - OTAssertEqualObjects(filteredSet, - ([OFSet setWithObjects: @"bar", @"baz", nil])); -} -#endif - -- (void)testValueForKey -{ - OFSet *set = [[self.setClass setWithObjects: - @"a", @"ab", @"abc", @"b", nil] valueForKey: @"length"]; - - OTAssertEqualObjects(set, ([OFSet setWithObjects: - [OFNumber numberWithInt: 1], [OFNumber numberWithInt: 2], - [OFNumber numberWithInt: 3], nil])); - - OTAssertEqualObjects([set valueForKey: @"@count"], - [OFNumber numberWithInt: 3]); -} -@end - -@implementation CustomSet -- (instancetype)initWithObjects: (id const *)objects count: (size_t)count -{ - self = [super init]; - - @try { - _set = [[OFSet alloc] initWithObjects: objects count: count]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_set release]; - - [super dealloc]; -} - -- (size_t)count -{ - return _set.count; -} - -- (bool)containsObject: (id)object -{ - return [_set containsObject: object]; -} - -- (OFEnumerator *)objectEnumerator -{ - return [_set objectEnumerator]; -} -@end DELETED new_tests/OFSocketTests.m Index: new_tests/OFSocketTests.m ================================================================== --- new_tests/OFSocketTests.m +++ /dev/null @@ -1,252 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFSocketTests: OTTestCase -@end - -#define COMPARE_V6(a, a0, a1, a2, a3, a4, a5, a6, a7) \ - (a.sockaddr.in6.sin6_addr.s6_addr[0] == (a0 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[1] == (a0 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[2] == (a1 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[3] == (a1 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[4] == (a2 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[5] == (a2 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[6] == (a3 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[7] == (a3 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[8] == (a4 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[9] == (a4 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[10] == (a5 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[11] == (a5 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[12] == (a6 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[13] == (a6 & 0xFF) && \ - a.sockaddr.in6.sin6_addr.s6_addr[14] == (a7 >> 8) && \ - a.sockaddr.in6.sin6_addr.s6_addr[15] == (a7 & 0xFF)) -#define SET_V6(a, a0, a1, a2, a3, a4, a5, a6, a7) \ - a.sockaddr.in6.sin6_addr.s6_addr[0] = a0 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[1] = a0 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[2] = a1 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[3] = a1 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[4] = a2 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[5] = a2 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[6] = a3 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[7] = a3 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[8] = a4 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[9] = a4 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF; \ - a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8; \ - a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF; - -@implementation OFSocketTests -- (void)testParseIPv4 -{ - OFSocketAddress address = OFSocketAddressParseIP(@"127.0.0.1", 1234); - - OTAssertEqual(OFFromBigEndian32(address.sockaddr.in.sin_addr.s_addr), - 0x7F000001); - OTAssertEqual(OFFromBigEndian16(address.sockaddr.in.sin_port), 1234); -} - -- (void)testParseRejectsInvalidIPv4 -{ - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.0.0.1", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.0.256", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.0. 1", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@" 127.0.0.1", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.a.1", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0..1", 1234), - OFInvalidFormatException); -} - -- (void)testPortForIPv4 -{ - OFSocketAddress address = OFSocketAddressParseIP(@"127.0.0.1", 1234); - - OTAssertEqual(OFSocketAddressIPPort(&address), 1234); -} - -- (void)testStringForIPv4 -{ - OFSocketAddress address = OFSocketAddressParseIP(@"127.0.0.1", 1234); - - OTAssertEqualObjects(OFSocketAddressString(&address), @"127.0.0.1"); -} - -- (void)testParseIPv6 -{ - OFSocketAddress address; - - address = OFSocketAddressParseIP( - @"1122:3344:5566:7788:99aa:bbCc:ddee:ff00", 1234); - OTAssert(COMPARE_V6(address, - 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00)); - OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); - - address = OFSocketAddressParseIP(@"::", 1234); - OTAssert(COMPARE_V6(address, 0, 0, 0, 0, 0, 0, 0, 0)); - OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); - - address = OFSocketAddressParseIP(@"aaAa::bBbb", 1234); - OTAssert(COMPARE_V6(address, 0xAAAA, 0, 0, 0, 0, 0, 0, 0xBBBB)); - OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); - - address = OFSocketAddressParseIP(@"aaAa::", 1234); - OTAssert(COMPARE_V6(address, 0xAAAA, 0, 0, 0, 0, 0, 0, 0)); - OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); - - address = OFSocketAddressParseIP(@"::aaAa", 1234); - OTAssert(COMPARE_V6(address, 0, 0, 0, 0, 0, 0, 0, 0xAAAA)); - OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); - - address = OFSocketAddressParseIP(@"fd00::1%123", 1234); - OTAssert(COMPARE_V6(address, 0xFD00, 0, 0, 0, 0, 0, 0, 1)); - OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); - OTAssertEqual(address.sockaddr.in6.sin6_scope_id, 123); - - address = OFSocketAddressParseIP(@"::ffff:127.0.0.1", 1234); - OTAssert(COMPARE_V6(address, 0, 0, 0, 0, 0, 0xFFFF, 0x7F00, 1)); - OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); - - address = OFSocketAddressParseIP(@"64:ff9b::127.0.0.1", 1234); - OTAssert(COMPARE_V6(address, 0x64, 0xFF9B, 0, 0, 0, 0, 0x7F00, 1)); - OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); -} - -- (void)testParseRejectsInvalidIPv6 -{ - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:::2", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1: ::2", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:: :2", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1::2::3", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"10000::1", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"::10000", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"::1::", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:2:3:4:5:6:7:", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:2:3:4:5:6:7::", 1234), - OFInvalidFormatException); - - OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:2", 1234), - OFInvalidFormatException); -} - -- (void)testPortForIPv6 -{ - OFSocketAddress address = OFSocketAddressParseIP(@"::", 1234); - - OTAssertEqual(OFSocketAddressIPPort(&address), 1234); -} - -- (void)testStringForIPv6 -{ - OFSocketAddress address = OFSocketAddressParseIP(@"::", 1234); - - OTAssertEqualObjects(OFSocketAddressString(&address), @"::"); - - SET_V6(address, 0, 0, 0, 0, 0, 0, 0, 1) - OTAssertEqualObjects(OFSocketAddressString(&address), @"::1"); - - SET_V6(address, 1, 0, 0, 0, 0, 0, 0, 0) - OTAssertEqualObjects(OFSocketAddressString(&address), @"1::"); - - SET_V6(address, - 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) - OTAssertEqualObjects(OFSocketAddressString(&address), - @"1122:3344:5566:7788:99aa:bbcc:ddee:ff00"); - - SET_V6(address, - 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0) - OTAssertEqualObjects(OFSocketAddressString(&address), - @"1122:3344:5566:7788:99aa:bbcc:ddee:0"); - - SET_V6(address, 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0) - OTAssertEqualObjects(OFSocketAddressString(&address), - @"1122:3344:5566:7788:99aa:bbcc::"); - - SET_V6(address, - 0, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) - OTAssertEqualObjects(OFSocketAddressString(&address), - @"0:3344:5566:7788:99aa:bbcc:ddee:ff00"); - - SET_V6(address, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) - OTAssertEqualObjects(OFSocketAddressString(&address), - @"::5566:7788:99aa:bbcc:ddee:ff00"); - - SET_V6(address, 0, 0, 0x5566, 0, 0, 0, 0xDDEE, 0xFF00) - OTAssertEqualObjects(OFSocketAddressString(&address), - @"0:0:5566::ddee:ff00"); - - SET_V6(address, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0) - OTAssertEqualObjects(OFSocketAddressString(&address), - @"::5566:7788:99aa:bbcc:0:0"); - - address.sockaddr.in6.sin6_scope_id = 123; - OTAssertEqualObjects(OFSocketAddressString(&address), - @"::5566:7788:99aa:bbcc:0:0%123"); -} - -- (void)testAddressEqual -{ - OFSocketAddress addr1 = OFSocketAddressParseIP(@"127.0.0.1", 1234); - OFSocketAddress addr2 = OFSocketAddressParseIP(@"127.0.0.1", 1234); - OFSocketAddress addr3 = OFSocketAddressParseIP(@"127.0.0.1", 1235); - - OTAssertTrue(OFSocketAddressEqual(&addr1, &addr2)); - OTAssertFalse(OFSocketAddressEqual(&addr1, &addr3)); -} - -- (void)testAddressHash -{ - OFSocketAddress addr1 = OFSocketAddressParseIP(@"127.0.0.1", 1234); - OFSocketAddress addr2 = OFSocketAddressParseIP(@"127.0.0.1", 1234); - OFSocketAddress addr3 = OFSocketAddressParseIP(@"127.0.0.1", 1235); - - OTAssertEqual(OFSocketAddressHash(&addr1), OFSocketAddressHash(&addr2)); - OTAssertNotEqual(OFSocketAddressHash(&addr1), - OFSocketAddressHash(&addr3)); -} -@end DELETED new_tests/OFStreamTests.m Index: new_tests/OFStreamTests.m ================================================================== --- new_tests/OFStreamTests.m +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFStreamTests: OTTestCase -@end - -@interface OFTestStream: OFStream -{ - int _state; -} -@end - -@implementation OFStreamTests -- (void)testStream -{ - size_t pageSize = [OFSystemInfo pageSize]; - OFTestStream *stream = [[[OFTestStream alloc] init] autorelease]; - char *cString = OFAllocMemory(pageSize - 2, 1); - - @try { - OFString *string; - - memset(cString, 'X', pageSize - 3); - cString[pageSize - 3] = '\0'; - - OTAssertEqualObjects([stream readLine], @"foo"); - - string = [stream readLine]; - OTAssertNotNil(string); - OTAssertEqual(string.length, pageSize - 3); - OTAssertEqual(strcmp(string.UTF8String, cString), 0); - } @finally { - OFFreeMemory(cString); - } -} -@end - -@implementation OFTestStream -- (bool)lowlevelIsAtEndOfStream -{ - return (_state > 1); -} - -- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)size -{ - size_t pageSize = [OFSystemInfo pageSize]; - - switch (_state) { - case 0: - if (size < 1) - return 0; - - memcpy(buffer, "f", 1); - - _state++; - return 1; - case 1: - if (size < pageSize) - return 0; - - memcpy(buffer, "oo\n", 3); - memset((char *)buffer + 3, 'X', pageSize - 3); - - _state++; - return pageSize; - } - - return 0; -} -@end DELETED new_tests/OFStringTests.h Index: new_tests/OFStringTests.h ================================================================== --- new_tests/OFStringTests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFStringTests: OTTestCase -{ - OFString *_string; -} - -@property (readonly, nonatomic) Class stringClass; -@end DELETED new_tests/OFStringTests.m Index: new_tests/OFStringTests.m ================================================================== --- new_tests/OFStringTests.m +++ /dev/null @@ -1,1661 +0,0 @@ -/* - * 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" - -#include -#include -#include - -#import "OFStringTests.h" - -#ifndef INFINITY -# define INFINITY __builtin_inf() -#endif - -static const OFUnichar unicharString[] = { - 0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0x1F03A, 0 -}; -static const OFUnichar swappedUnicharString[] = { - 0xFFFE0000, 0x66000000, 0xF6000000, 0xF6000000, 0x62000000, 0xE4000000, - 0x72000000, 0x3AF00100, 0 -}; -static const OFChar16 char16String[] = { - 0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0xD83C, 0xDC3A, 0 -}; -static const OFChar16 swappedChar16String[] = { - 0xFFFE, 0x6600, 0xF600, 0xF600, 0x6200, 0xE400, 0x7200, 0x3CD8, 0x3ADC, - 0 -}; - -@interface CustomString: OFString -{ - OFMutableString *_string; -} -@end - -@interface CustomMutableString: OFMutableString -{ - OFMutableString *_string; -} -@end - -@interface EntityHandler: OFObject -@end - -@implementation OFStringTests -- (Class)stringClass -{ - return [CustomString class]; -} - -- (void)setUp -{ - [super setUp]; - - _string = [[self.stringClass alloc] initWithString: @"täṠ€🤔"]; -} - -- (void)dealloc -{ - [_string release]; - - [super dealloc]; -} - -- (void)testIsEqual -{ - OTAssertEqualObjects(_string, @"täṠ€🤔"); - OTAssertEqualObjects(@"täṠ€🤔", _string); - OTAssertNotEqualObjects([self.stringClass stringWithString: @"test"], - @"täṠ€🤔"); - OTAssertNotEqualObjects(@"täṠ€🤔", - [self.stringClass stringWithString: @"test"]); -} - -- (void)testHash -{ - OTAssertEqual(_string.hash, @"täṠ€🤔".hash); - OTAssertNotEqual([[self.stringClass stringWithString: @"test"] hash], - @"täṠ€".hash); -} - -- (void)testCompare -{ - OTAssertEqual([_string compare: @"täṠ€🤔"], OFOrderedSame); - OTAssertEqual([[self.stringClass stringWithString: @""] - compare: @"a"], OFOrderedAscending); - OTAssertEqual([[self.stringClass stringWithString: @"a"] - compare: @"b"], OFOrderedAscending); - OTAssertEqual([[self.stringClass stringWithString: @"cd"] - compare: @"bc"], OFOrderedDescending); - OTAssertEqual([[self.stringClass stringWithString: @"ä"] - compare: @"ö"], OFOrderedAscending); - OTAssertEqual([[self.stringClass stringWithString: @"€"] - compare: @"ß"], OFOrderedDescending); - OTAssertEqual([[self.stringClass stringWithString: @"aa"] - compare: @"z"], OFOrderedAscending); - OTAssertEqual([@"aa" compare: - [self.stringClass stringWithString: @"z"]], OFOrderedAscending); -} - -- (void)testCaseInsensitiveCompare -{ -#ifdef OF_HAVE_UNICODE_TABLES - OTAssertEqual([[self.stringClass stringWithString: @"a"] - caseInsensitiveCompare: @"A"], OFOrderedSame); - OTAssertEqual([[self.stringClass stringWithString: @"Ä"] - caseInsensitiveCompare: @"ä"], OFOrderedSame); - OTAssertEqual([[self.stringClass stringWithString: @"я"] - caseInsensitiveCompare: @"Я"], OFOrderedSame); - OTAssertEqual([[self.stringClass stringWithString: @"€"] - caseInsensitiveCompare: @"ß"], OFOrderedDescending); - OTAssertEqual([[self.stringClass stringWithString: @"ß"] - caseInsensitiveCompare: @"→"], OFOrderedAscending); - OTAssertEqual([[self.stringClass stringWithString: @"AA"] - caseInsensitiveCompare: @"z"], OFOrderedAscending); - OTAssertEqual([[self.stringClass stringWithString: @"ABC"] - caseInsensitiveCompare: @"AbD"], OFOrderedAscending); -#else - OTAssertEqual([[self.stringClass stringWithString: @"a"] - caseInsensitiveCompare: @"A"], OFOrderedSame); - OTAssertEqual([[self.stringClass stringWithString: @"AA"] - caseInsensitiveCompare: @"z"], OFOrderedAscending); - OTAssertEqual([[self.stringClass stringWithString: @"ABC"] - caseInsensitiveCompare: @"AbD"], OFOrderedAscending); -#endif -} - -- (void)testDescription -{ - OTAssertEqualObjects(_string.description, @"täṠ€🤔"); -} - -- (void)testLength -{ - OTAssertEqual(_string.length, 5); -} - -- (void)testUTF8StringLength -{ - OTAssertEqual(_string.UTF8StringLength, 13); -} - -- (void)testCharacterAtIndex -{ - OTAssertEqual([_string characterAtIndex: 0], 't'); - OTAssertEqual([_string characterAtIndex: 1], 0xE4); - OTAssertEqual([_string characterAtIndex: 2], 0x1E60); - OTAssertEqual([_string characterAtIndex: 3], 0x20AC); - OTAssertEqual([_string characterAtIndex: 4], 0x1F914); -} - -- (void)testCharacterAtIndexFailsWithOutOfRangeIndex -{ - OTAssertThrowsSpecific([_string characterAtIndex: 5], - OFOutOfRangeException); -} - -- (void)testUppercaseString -{ -#ifdef OF_HAVE_UNICODE_TABLES - OTAssertEqualObjects(_string.uppercaseString, @"TÄṠ€🤔"); -#else - OTAssertEqualObjects(_string.uppercaseString, @"TäṠ€🤔"); -#endif -} - -- (void)testLowercaseString -{ -#ifdef OF_HAVE_UNICODE_TABLES - OTAssertEqualObjects(_string.lowercaseString, @"täṡ€🤔"); -#else - OTAssertEqualObjects(_string.lowercaseString, @"täṠ€🤔"); -#endif -} - -- (void)testCapitalizedString -{ -#ifdef OF_HAVE_UNICODE_TABLES - OTAssertEqualObjects([[self.stringClass stringWithString: - @"täṠ€🤔täṠ€🤔 täṠ€🤔"] capitalizedString], @"Täṡ€🤔täṡ€🤔 Täṡ€🤔"); -#else - OTAssertEqualObjects([[self.stringClass stringWithString: - @"täṠ€🤔täṠ€🤔 täṠ€🤔"] capitalizedString], @"TäṠ€🤔täṠ€🤔 TäṠ€🤔"); -#endif -} - -- (void)testStringWithUTF8StringLength -{ - OTAssertEqualObjects([self.stringClass - stringWithUTF8String: "\xEF\xBB\xBF" "foobar" - length: 6], @"foo"); -} - -- (void)testStringWithUTF16String -{ - OTAssertEqualObjects([self.stringClass - stringWithUTF16String: char16String], @"fööbär🀺"); - OTAssertEqualObjects([self.stringClass - stringWithUTF16String: swappedChar16String], @"fööbär🀺"); -} - -- (void)testStringWithUTF32String -{ - OTAssertEqualObjects([self.stringClass - stringWithUTF32String: unicharString], @"fööbär🀺"); - OTAssertEqualObjects([self.stringClass - stringWithUTF32String: swappedUnicharString], @"fööbär🀺"); -} - -- (void)testStringWithUTF8StringFailsWithInvalidUTF8 -{ - OTAssertThrowsSpecific( - [self.stringClass stringWithUTF8String: "\xE0\x80"], - OFInvalidEncodingException); - - OTAssertThrowsSpecific( - [self.stringClass stringWithUTF8String: "\xF0\x80\x80\xC0"], - OFInvalidEncodingException); -} - -- (void)testStringWithCStringEncodingISO8859_1 -{ - OTAssertEqualObjects([self.stringClass - stringWithCString: "\xE4\xF6\xFC" - encoding: OFStringEncodingISO8859_1], @"äöü"); -} - -#ifdef HAVE_ISO_8859_15 -- (void)testStringWithCStringEncodingISO8859_15 -{ - OTAssertEqualObjects([self.stringClass - stringWithCString: "\xA4\xA6\xA8\xB4\xB8\xBC\xBD\xBE" - encoding: OFStringEncodingISO8859_15], @"€ŠšŽžŒœŸ"); -} -#endif - -#ifdef HAVE_WINDOWS_1252 -- (void)testStringWithCStringEncodingWindows1252 -{ - OTAssertEqualObjects([self.stringClass - stringWithCString: "\x80\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B" - "\x8C\x8E\x91\x92\x93\x94\x95\x96\x97\x98\x99" - "\x9A\x9B\x9C\x9E\x9F" - encoding: OFStringEncodingWindows1252], - @"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ"); -} -#endif - -#ifdef HAVE_CODEPAGE_437 -- (void)testStringWithCStringEncodingCodepage437 -{ - OTAssertEqualObjects([self.stringClass - stringWithCString: "\xB0\xB1\xB2\xDB" - encoding: OFStringEncodingCodepage437], @"░▒▓█"); -} -#endif - -#ifdef OF_HAVE_FILES -- (void)testStringWithContentsOfFileEncoding -{ - OTAssertEqualObjects([self.stringClass - stringWithContentsOfFile: @"testfile.txt" - encoding: OFStringEncodingISO8859_1], @"testäöü"); -} - -- (void)testStringWithContentsOfIRIEncoding -{ - OTAssertEqualObjects([self.stringClass - stringWithContentsOfIRI: [OFIRI fileIRIWithPath: @"testfile.txt"] - encoding: OFStringEncodingISO8859_1], @"testäöü"); -} -#endif - -- (void)testCStringWithEncodingASCII -{ - OTAssertEqual(strcmp([[self.stringClass stringWithString: - @"This is a test"] cStringWithEncoding: OFStringEncodingASCII], - "This is a test"), 0); - - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"This is a tést"] cStringWithEncoding: OFStringEncodingASCII], - OFInvalidEncodingException); -} - -- (void)testCStringWithEncodingISO8859_1 -{ - OTAssertEqual(strcmp([[self.stringClass stringWithString: - @"This is ä test"] cStringWithEncoding: OFStringEncodingISO8859_1], - "This is \xE4 test"), 0); - - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"This is ä t€st"] cStringWithEncoding: OFStringEncodingISO8859_1], - OFInvalidEncodingException); -} - -#ifdef HAVE_ISO_8859_15 -- (void)testCStringWithEncodingISO8859_15 -{ - OTAssertEqual(strcmp([[self.stringClass stringWithString: - @"This is ä t€st"] cStringWithEncoding: OFStringEncodingISO8859_15], - "This is \xE4 t\xA4st"), 0); - - OTAssertThrowsSpecific( - [[self.stringClass stringWithString: @"This is ä t€st…"] - cStringWithEncoding: OFStringEncodingISO8859_15], - OFInvalidEncodingException); -} -#endif - -#ifdef HAVE_WINDOWS_1252 -- (void)testCStringWithEncodingWindows1252 -{ - OTAssertEqual( - strcmp([[self.stringClass stringWithString: @"This is ä t€st…"] - cStringWithEncoding: OFStringEncodingWindows1252], - "This is \xE4 t\x80st\x85"), 0); - - OTAssertThrowsSpecific( - [[self.stringClass stringWithString: @"This is ä t€st…‼"] - cStringWithEncoding: OFStringEncodingWindows1252], - OFInvalidEncodingException); -} -#endif - -#ifdef HAVE_CODEPAGE_437 -- (void)testCStringWithEncodingCodepage437 -{ - OTAssertEqual( - strcmp([[self.stringClass stringWithString: @"Tést strîng ░▒▓"] - cStringWithEncoding: OFStringEncodingCodepage437], - "T\x82st str\x8Cng \xB0\xB1\xB2"), 0); - - OTAssertThrowsSpecific( - [[self.stringClass stringWithString: @"T€st strîng ░▒▓"] - cStringWithEncoding: OFStringEncodingCodepage437], - OFInvalidEncodingException); -} -#endif - -- (void)testLossyCStringWithEncodingASCII -{ - OTAssertEqual(strcmp([[self.stringClass stringWithString: - @"This is a tést"] lossyCStringWithEncoding: OFStringEncodingASCII], - "This is a t?st"), 0); -} - -- (void)testLossyCStringWithEncodingISO8859_1 -{ - OTAssertEqual( - strcmp([[self.stringClass stringWithString: @"This is ä t€st"] - lossyCStringWithEncoding: OFStringEncodingISO8859_1], - "This is \xE4 t?st"), 0); -} - -#ifdef HAVE_ISO_8859_15 -- (void)testLossyCStringWithEncodingISO8859_15 -{ - OTAssertEqual( - strcmp([[self.stringClass stringWithString: @"This is ä t€st…"] - lossyCStringWithEncoding: OFStringEncodingISO8859_15], - "This is \xE4 t\xA4st?"), 0); -} -#endif - -#ifdef HAVE_WINDOWS_1252 -- (void)testLossyCStringWithEncodingWindows1252 -{ - OTAssertEqual( - strcmp([[self.stringClass stringWithString: @"This is ä t€st…‼"] - lossyCStringWithEncoding: OFStringEncodingWindows1252], - "This is \xE4 t\x80st\x85?"), 0); -} -#endif - -#ifdef HAVE_CODEPAGE_437 -- (void)testLossyCStringWithEncodingCodepage437 -{ - OTAssertEqual( - strcmp([[self.stringClass stringWithString: @"T€st strîng ░▒▓"] - lossyCStringWithEncoding: OFStringEncodingCodepage437], - "T?st str\x8Cng \xB0\xB1\xB2"), 0); -} -#endif - -- (void)testStringWithFormat -{ - OTAssertEqualObjects( - ([self.stringClass stringWithFormat: @"%@:%d", @"test", 123]), - @"test:123"); -} - -- (void)testRangeOfString -{ - OFString *string = [self.stringClass stringWithString: @"𝄞öö"]; - - OTAssertEqual([string rangeOfString: @"öö"].location, 1); - OTAssertEqual([string rangeOfString: @"ö"].location, 1); - OTAssertEqual([string rangeOfString: @"𝄞"].location, 0); - OTAssertEqual([string rangeOfString: @"x"].location, OFNotFound); - - OTAssertEqual([string - rangeOfString: @"öö" - options: OFStringSearchBackwards].location, 1); - - OTAssertEqual([string - rangeOfString: @"ö" - options: OFStringSearchBackwards].location, 2); - - OTAssertEqual([string - rangeOfString: @"𝄞" - options: OFStringSearchBackwards].location, 0); - - OTAssertEqual([string - rangeOfString: @"x" - options: OFStringSearchBackwards].location, OFNotFound); -} - -- (void)testRangeOfStringFailsWithOutOfRangeRange -{ - OTAssertThrowsSpecific( - [_string rangeOfString: @"t" options: 0 range: OFMakeRange(6, 1)], - OFOutOfRangeException); -} - -- (void)testIndexOfCharacterFromSet -{ - OFCharacterSet *characterSet = - [OFCharacterSet characterSetWithCharactersInString: @"cđ"]; - - OTAssertEqual([[self.stringClass stringWithString: @"abcđabcđe"] - indexOfCharacterFromSet: characterSet], 2); - - OTAssertEqual([[self.stringClass stringWithString: @"abcđabcđë"] - indexOfCharacterFromSet: characterSet - options: OFStringSearchBackwards], 7); - - OTAssertEqual([[self.stringClass stringWithString: @"abcđabcđë"] - indexOfCharacterFromSet: characterSet - options: 0 - range: OFMakeRange(4, 4)], 6); - - OTAssertEqual([[self.stringClass stringWithString: @"abcđabcđëf"] - indexOfCharacterFromSet: characterSet - options: 0 - range: OFMakeRange(8, 2)], OFNotFound); -} - -- (void)testIndexOfCharacterFromSetFailsWithOutOfRangeRange -{ - OFCharacterSet *characterSet = - [OFCharacterSet characterSetWithCharactersInString: @"cđ"]; - - OTAssertThrowsSpecific([[self.stringClass stringWithString: @"𝄞öö"] - indexOfCharacterFromSet: characterSet - options: 0 - range: OFMakeRange(3, 1)], - OFOutOfRangeException); -} - -- (void)testSubstringWithRange -{ - OTAssertEqualObjects([_string substringWithRange: OFMakeRange(1, 2)], - @"äṠ"); - - OTAssertEqualObjects([_string substringWithRange: OFMakeRange(3, 0)], - @""); -} - -- (void)testSubstringWithRangeFailsWithOutOfRangeRange -{ - OTAssertThrowsSpecific([_string substringWithRange: OFMakeRange(4, 2)], - OFOutOfRangeException); - - OTAssertThrowsSpecific([_string substringWithRange: OFMakeRange(6, 0)], - OFOutOfRangeException); -} - -- (void)testStringByAppendingString -{ - OTAssertEqualObjects([_string stringByAppendingString: @"äöü"], - @"täṠ€🤔äöü"); -} - -- (void)testHasPrefix -{ - OTAssertTrue([_string hasPrefix: @"täṠ"]); - OTAssertFalse([_string hasPrefix: @"🤔"]); -} - -- (void)testHasSuffix -{ - OTAssertTrue([_string hasSuffix: @"🤔"]); - OTAssertFalse([_string hasSuffix: @"täṠ"]); -} - -- (void)testComponentsSeparatedByString -{ - OTAssertEqualObjects([[self.stringClass stringWithString: - @"fooXXbarXXXXbazXXXX"] componentsSeparatedByString: @"XX"], - ([OFArray arrayWithObjects: @"foo", @"bar", @"", @"baz", @"", @"", - nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] componentsSeparatedByString: @""], - [OFArray arrayWithObject: @"foo"]); -} - -- (void)testComponentsSeparatedByStringOptions -{ - OTAssertEqualObjects([[self.stringClass stringWithString: - @"fooXXbarXXXXbazXXXX"] - componentsSeparatedByString: @"XX" - options: OFStringSkipEmptyComponents], - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); -} - -- (void)testComponentsSeparatedByCharactersInSet -{ - OFCharacterSet *characterSet = - [OFCharacterSet characterSetWithCharactersInString: @"XYZ"]; - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"fooXYbarXYZXbazXYXZx"] - componentsSeparatedByCharactersInSet: characterSet], - ([OFArray arrayWithObjects: @"foo", @"", @"bar", @"", @"", @"", - @"baz", @"", @"", @"", @"x", nil])); -} - -- (void)testComponentsSeparatedByCharactersInSetOptions -{ - OFCharacterSet *characterSet = - [OFCharacterSet characterSetWithCharactersInString: @"XYZ"]; - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"fooXYbarXYZXbazXYXZ"] - componentsSeparatedByCharactersInSet: characterSet - options: OFStringSkipEmptyComponents], - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); -} - -- (void)testLongLongValue -{ - OTAssertEqual([[self.stringClass stringWithString: - @"1234"] longLongValue], 1234); - - OTAssertEqual([[self.stringClass stringWithString: - @"\r\n+123 "] longLongValue], 123); - - OTAssertEqual([[self.stringClass stringWithString: - @"-500\t"] longLongValue], -500); - - OTAssertEqual([[self.stringClass stringWithString: - @"-0x10\t"] longLongValueWithBase: 0], -0x10); - - OTAssertEqual([[self.stringClass stringWithString: - @"\t\t\r\n"] longLongValue], 0); - - OTAssertEqual([[self.stringClass stringWithString: - @"123f"] longLongValueWithBase: 16], 0x123f); - - OTAssertEqual([[self.stringClass stringWithString: - @"-1234"] longLongValueWithBase: 0], -1234); - - OTAssertEqual([[self.stringClass stringWithString: - @"\t\n0xABcd\r"] longLongValueWithBase: 0], 0xABCD); - - OTAssertEqual([[self.stringClass stringWithString: - @"1234567"] longLongValueWithBase: 8], 01234567); - - OTAssertEqual([[self.stringClass stringWithString: - @"\r\n0123"] longLongValueWithBase: 0], 0123); - - OTAssertEqual([[self.stringClass stringWithString: - @"765\t"] longLongValueWithBase: 8], 0765); - - OTAssertEqual([[self.stringClass stringWithString: - @"\t\t\r\n"] longLongValueWithBase: 8], 0); -} - -- (void)testLongLongValueThrowsOnInvalidFormat -{ - OTAssertThrowsSpecific( - [[self.stringClass stringWithString: @"abc"] longLongValue], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [[self.stringClass stringWithString: @"0a"] longLongValue], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [[self.stringClass stringWithString: @"0 1"] longLongValue], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [[self.stringClass stringWithString: @"0xABCDEFG"] - longLongValueWithBase: 0], - OFInvalidFormatException); - - OTAssertThrowsSpecific( - [[self.stringClass stringWithString: @"0x"] - longLongValueWithBase: 0], - OFInvalidFormatException); -} - -- (void)testLongLongValueThrowsOnOutOfRange -{ - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"-12345678901234567890123456789012345678901234567890" - @"12345678901234567890123456789012345678901234567890"] - longLongValueWithBase: 16], OFOutOfRangeException) -} - -- (void)testUnsignedLongLongValue -{ - OTAssertEqual([[self.stringClass stringWithString: - @"1234"] unsignedLongLongValue], 1234); - - OTAssertEqual([[self.stringClass stringWithString: - @"\r\n+123 "] unsignedLongLongValue], 123); - - OTAssertEqual([[self.stringClass stringWithString: - @"\t\t\r\n"] unsignedLongLongValue], 0); - - OTAssertEqual([[self.stringClass stringWithString: - @"123f"] unsignedLongLongValueWithBase: 16], 0x123f); - - OTAssertEqual([[self.stringClass stringWithString: - @"1234"] unsignedLongLongValueWithBase: 0], 1234); - - OTAssertEqual([[self.stringClass stringWithString: - @"\t\n0xABcd\r"] unsignedLongLongValueWithBase: 0], 0xABCD); - - OTAssertEqual([[self.stringClass stringWithString: - @"1234567"] unsignedLongLongValueWithBase: 8], 01234567); - - OTAssertEqual([[self.stringClass stringWithString: - @"\r\n0123"] unsignedLongLongValueWithBase: 0], 0123); - - OTAssertEqual([[self.stringClass stringWithString: @"765\t"] - unsignedLongLongValueWithBase: 8], 0765); - - OTAssertEqual([[self.stringClass stringWithString: @"\t\t\r\n"] - unsignedLongLongValueWithBase: 8], 0); -} - -- (void)testUnsignedLongLongValueThrowsOnOutOfRange -{ - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" - @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"] - unsignedLongLongValueWithBase: 16], OFOutOfRangeException); -} - -- (void)testFloatValue -{ - /* - * These test numbers can be generated without rounding if we have IEEE - * floating point numbers, thus we can use OTAssertEqual on them. - */ - - OTAssertEqual([[self.stringClass stringWithString: - @"\t-0.25 "] floatValue], -0.25); - - OTAssertEqual([[self.stringClass stringWithString: - @"\r\n\tINF\t\n"] floatValue], INFINITY); - OTAssertEqual([[self.stringClass stringWithString: - @"\r -INFINITY\n"] floatValue], -INFINITY); - - OTAssertTrue(isnan([[self.stringClass stringWithString: - @" NAN\t\t"] floatValue])); - OTAssertTrue(isnan([[self.stringClass stringWithString: - @" -NaN\t\t"] floatValue])); -} - -- (void)testFloatValueThrowsOnInvalidFormat -{ - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"0.0a"] floatValue], OFInvalidFormatException); - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"0 0"] floatValue], OFInvalidFormatException); - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"0,0"] floatValue], OFInvalidFormatException); -} - -- (void)testDoubleValue -{ -#if (defined(OF_SOLARIS) && defined(OF_X86)) || defined(OF_AMIGAOS_M68K) - /* - * Solaris' strtod() has weird rounding on x86, but not on AMD64. - * AmigaOS 3 with libnix has weird rounding as well. - */ - OTAssertEqual([[self.stringClass stringWithString: - @"\t-0.125 "] doubleValue], -0.125); -#elif defined(OF_ANDROID) || defined(OF_SOLARIS) || defined(OF_HPUX) || \ - defined(OF_DJGPP) || defined(OF_AMIGAOS_M68K) - /* - * Android, Solaris, HP-UX, DJGPP and AmigaOS 3 do not accept 0x for - * strtod(). - */ - OTAssertEqual([[self.stringClass stringWithString: - @"\t-0.123456789 "] doubleValue], -0.123456789); -#else - OTAssertEqual([[self.stringClass stringWithString: - @"\t-0x1.FFFFFFFFFFFFFP-1020 "] doubleValue], - -0x1.FFFFFFFFFFFFFP-1020); -#endif - - OTAssertEqual([[self.stringClass stringWithString: - @"\r\n\tINF\t\n"] doubleValue], INFINITY); - OTAssertEqual([[self.stringClass stringWithString: - @"\r -INFINITY\n"] doubleValue], -INFINITY); - - OTAssert(isnan([[self.stringClass stringWithString: - @" NAN\t\t"] doubleValue])); - OTAssert(isnan([[self.stringClass stringWithString: - @" -NaN\t\t"] doubleValue])); -} - -- (void)testDoubleValueThrowsOnInvalidFormat -{ - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"0.0a"] doubleValue], OFInvalidFormatException); - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"0 0"] doubleValue], OFInvalidFormatException); - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"0,0"] doubleValue], OFInvalidFormatException); -} - -- (void)testCharacters -{ - OTAssertEqual(memcmp([[self.stringClass stringWithString: @"fööbär🀺"] - characters], unicharString + 1, sizeof(unicharString) - 8), 0); -} - -- (void)testUTF16String -{ - OFString *string = [self.stringClass stringWithString: @"fööbär🀺"]; - - OTAssertEqual(memcmp(string.UTF16String, char16String + 1, - OFUTF16StringLength(char16String) * 2), 0); - -#ifdef OF_BIG_ENDIAN - OTAssertEqual(memcmp([string UTF16StringWithByteOrder: - OFByteOrderLittleEndian], swappedChar16String + 1, - OFUTF16StringLength(swappedChar16String) * 2), 0); -#else - OTAssertEqual(memcmp([string UTF16StringWithByteOrder: - OFByteOrderBigEndian], swappedChar16String + 1, - OFUTF16StringLength(swappedChar16String) * 2), 0); -#endif -} - -- (void)testUTF16StringLength -{ - OTAssertEqual(_string.UTF16StringLength, 6); -} - -- (void)testUTF32String -{ - OFString *string = [self.stringClass stringWithString: @"fööbär🀺"]; - - OTAssertEqual(memcmp(string.UTF32String, unicharString + 1, - OFUTF32StringLength(unicharString) * 4), 0); - -#ifdef OF_BIG_ENDIAN - OTAssertEqual(memcmp([string UTF32StringWithByteOrder: - OFByteOrderLittleEndian], swappedUnicharString + 1, - OFUTF32StringLength(swappedUnicharString) * 4), 0); -#else - OTAssertEqual(memcmp([string UTF32StringWithByteOrder: - OFByteOrderBigEndian], swappedUnicharString + 1, - OFUTF32StringLength(swappedUnicharString) * 4), 0); -#endif -} - -- (void)testStringByMD5Hashing -{ - OTAssertEqualObjects(_string.stringByMD5Hashing, - @"7e6bef5fe100d93e808d15b1c6e6145a"); -} - -- (void)testStringByRIPEMD160Hashing -{ - OTAssertEqualObjects(_string.stringByRIPEMD160Hashing, - @"2fd0ec899c55cf2821a2f844b9d80887fc351103"); -} - -- (void)testStringBySHA1Hashing -{ - OTAssertEqualObjects(_string.stringBySHA1Hashing, - @"3f76f9358b372b7147344b7a3ba6d309e4466b3a"); -} - -- (void)testStringBySHA224Hashing -{ - OTAssertEqualObjects(_string.stringBySHA224Hashing, - @"6e57ec72e4da55c46d88a15ce7ce4d8db83d0493a263134a3734259d"); -} - -- (void)testStringBySHA256Hashing -{ - OTAssertEqualObjects(_string.stringBySHA256Hashing, - @"6eac4d3d0b4152c82ff88599482696ca" - @"d6dca0b533e8a2e6963d995b19b0a683"); -} - -- (void)testStringBySHA384Hashing -{ - OTAssertEqualObjects(_string.stringBySHA384Hashing, - @"d9bd6a671407d01cee4022888677040d" - @"108dd0270c38e0ce755d6dcadb4bf9c1" - @"89204dd2a51f954be55ea5d5fe00667b"); -} - -- (void)testStringBySHA512Hashing -{ - OTAssertEqualObjects(_string.stringBySHA512Hashing, - @"64bec66b3633c585da6d32760fa3617a" - @"47ca4c247472bdbbfb452b2dbf5a3612" - @"5629053394a16ecd08f8a21d461537c5" - @"f1224cbb379589e73dcd6763ec4f886c"); -} - -- (void)testStringByAddingPercentEncodingWithAllowedCharacters -{ - OFCharacterSet *characterSet = - [OFCharacterSet characterSetWithCharactersInString: @"abfo'_~$🍏"]; - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo\"ba'_~$]🍏🍌"] - stringByAddingPercentEncodingWithAllowedCharacters: characterSet], - @"foo%22ba'_~$%5D🍏%F0%9F%8D%8C"); -} - -- (void)testStringByRemovingPercentEncoding -{ - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo%20bar%22+%24%F0%9F%8D%8C"] stringByRemovingPercentEncoding], - @"foo bar\"+$🍌"); -} - -- (void)testStringByRemovingPercentEncodingThrowsOnInvalidFormat -{ - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"foo%xbar"] stringByRemovingPercentEncoding], - OFInvalidFormatException); -} - -- (void)testStringByRemovingPercentEncodingThrowsOnInvalidEncoding -{ - OTAssertThrowsSpecific([[self.stringClass stringWithString: - @"foo%FFbar"] stringByRemovingPercentEncoding], - OFInvalidEncodingException); -} - -- (void)testStringByXMLEscaping -{ - OTAssertEqualObjects([[self.stringClass stringWithString: - @" &world'\"!&"] stringByXMLEscaping], - @"<hello> &world'"!&"); -} - -- (void)testStringByXMLUnescaping -{ - OTAssertEqualObjects([[self.stringClass stringWithString: - @"<hello> &world'"!&"] - stringByXMLUnescaping], - @" &world'\"!&"); - - OTAssertEqualObjects([[self.stringClass stringWithString: @"y"] - stringByXMLUnescaping], @"y"); - OTAssertEqualObjects([[self.stringClass stringWithString: @"ä"] - stringByXMLUnescaping], @"ä"); - OTAssertEqualObjects([[self.stringClass stringWithString: @"€"] - stringByXMLUnescaping], @"€"); - OTAssertEqualObjects([[self.stringClass stringWithString: @"𝄞"] - stringByXMLUnescaping], @"𝄞"); -} - -- (void)testStringByXMLUnescapingThrowsOnUnknownEntities -{ - OTAssertThrowsSpecific([[self.stringClass stringWithString: @"&foo;"] - stringByXMLUnescaping], OFUnknownXMLEntityException); -} - -- (void)testStringByXMLUnescapingThrowsOnInvalidFormat -{ - OTAssertThrowsSpecific([[self.stringClass stringWithString: @"x&"] - stringByXMLUnescaping], OFInvalidFormatException); - OTAssertThrowsSpecific([[self.stringClass stringWithString: @"&#;"] - stringByXMLUnescaping], OFInvalidFormatException); - OTAssertThrowsSpecific([[self.stringClass stringWithString: @"&#x;"] - stringByXMLUnescaping], OFInvalidFormatException); - OTAssertThrowsSpecific([[self.stringClass stringWithString: @"&#g;"] - stringByXMLUnescaping], OFInvalidFormatException); - OTAssertThrowsSpecific([[self.stringClass stringWithString: @"&#xg;"] - stringByXMLUnescaping], OFInvalidFormatException); -} - -- (void)testStringByXMLUnescapingWithDelegate -{ - EntityHandler *entityHandler = - [[[EntityHandler alloc] init] autorelease]; - - OTAssertEqualObjects([[self.stringClass stringWithString: @"x&foo;y"] - stringByXMLUnescapingWithDelegate: entityHandler], - @"xbary"); -} - -#ifdef OF_HAVE_BLOCKS -- (void)testStringByXMLUnescapingWithBlock -{ - OTAssertEqualObjects([[self.stringClass stringWithString: @"x&foo;y"] - stringByXMLUnescapingWithBlock: ^ OFString * (OFString *string, - OFString *entity) { - if ([entity isEqual: @"foo"]) - return @"bar"; - - return nil; - }], @"xbary"); -} - -- (void)testEnumerateLinesUsingBlock -{ - __block size_t count = 0; - - [[self.stringClass stringWithString: @"foo\nbar\nbaz"] - enumerateLinesUsingBlock: ^ (OFString *line, bool *stop) { - switch (count++) { - case 0: - OTAssertEqualObjects(line, @"foo"); - break; - case 1: - OTAssertEqualObjects(line, @"bar"); - break; - case 2: - OTAssertEqualObjects(line, @"baz"); - break; - default: - OTAssert(false); - } - }]; - - OTAssertEqual(count, 3); -} -#endif - -#ifdef OF_HAVE_FILES -- (void)testIsAbsolutePath -{ -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - OTAssertTrue( - [[self.stringClass stringWithString: @"C:\\foo"] isAbsolutePath]); - OTAssertTrue( - [[self.stringClass stringWithString: @"a:/foo"] isAbsolutePath]); - OTAssertFalse( - [[self.stringClass stringWithString: @"foo"] isAbsolutePath]); - OTAssertFalse( - [[self.stringClass stringWithString: @"b:foo"] isAbsolutePath]); -# ifdef OF_WINDOWS - OTAssertTrue( - [[self.stringClass stringWithString: @"\\\\foo"] isAbsolutePath]); -# endif -# elif defined(OF_AMIGAOS) - OTAssertTrue( - [[self.stringClass stringWithString: @"dh0:foo"] isAbsolutePath]); - OTAssertTrue( - [[self.stringClass stringWithString: @"dh0:a/b"] isAbsolutePath]); - OTAssertFalse( - [[self.stringClass stringWithString: @"foo/bar"] isAbsolutePath]); - OTAssertFalse( - [[self.stringClass stringWithString: @"foo"] isAbsolutePath]); -# elif defined(OF_NINTENDO_DS) || defined(OF_NINTENDO_3DS) || \ - defined(OF_WII) || defined(OF_NINTENDO_SWITCH) - OTAssertTrue( - [[self.stringClass stringWithString: @"sdmc:/foo"] isAbsolutePath]); - OTAssertFalse( - [[self.stringClass stringWithString: @"sdmc:foo"] isAbsolutePath]); - OTAssertFalse( - [[self.stringClass stringWithString: @"foo/bar"] isAbsolutePath]); - OTAssertFalse( - [[self.stringClass stringWithString: @"foo"] isAbsolutePath]); -# else - OTAssertTrue( - [[self.stringClass stringWithString: @"/foo"] isAbsolutePath]); - OTAssertTrue( - [[self.stringClass stringWithString: @"/foo/bar"] isAbsolutePath]); - OTAssertFalse( - [[self.stringClass stringWithString: @"foo/bar"] isAbsolutePath]); - OTAssertFalse( - [[self.stringClass stringWithString: @"foo"] isAbsolutePath]); -# endif -} - -- (void)testStringByAppendingPathComponent -{ -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - OTAssertEqualObjects([[self.stringClass stringWithString: @"foo\\bar"] - stringByAppendingPathComponent: @"baz"], - @"foo\\bar\\baz"); - - OTAssertEqualObjects([[self.stringClass stringWithString: @"foo\\bar\\"] - stringByAppendingPathComponent: @"baz"], - @"foo\\bar\\baz"); -# else - OTAssertEqualObjects([[self.stringClass stringWithString: @"foo/bar"] - stringByAppendingPathComponent: @"baz"], - @"foo/bar/baz"); - - OTAssertEqualObjects([[self.stringClass stringWithString: @"foo/bar/"] - stringByAppendingPathComponent: @"baz"], - @"foo/bar/baz"); -# endif -} - -- (void)testStringByAppendingPathExtension -{ -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] stringByAppendingPathExtension: @"bar"], - @"foo.bar"); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:\\tmp\\foo"] stringByAppendingPathExtension: @"bar"], - @"c:\\tmp\\foo.bar"); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:\\tmp\\/\\"] stringByAppendingPathExtension: @"bar"], - @"c:\\tmp.bar"); -# elif defined(OF_AMIGAOS) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] stringByAppendingPathExtension: @"bar"], - @"foo.bar"); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] stringByAppendingPathExtension: @"baz"], - @"foo/bar.baz"); -# else - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] stringByAppendingPathExtension: @"bar"], - @"foo.bar"); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] stringByAppendingPathExtension: @"baz"], - @"foo/bar.baz"); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo///"] stringByAppendingPathExtension: @"bar"], - @"foo.bar"); -# endif -} - -- (void)testPathWithComponents -{ -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])], - @"foo\\bar\\baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"c:\\", @"foo", @"bar", @"baz", nil])], - @"c:\\foo\\bar\\baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"c:", @"foo", @"bar", @"baz", nil])], - @"c:foo\\bar\\baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"c:", @"\\", @"foo", @"bar", @"baz", - nil])], @"c:\\foo\\bar\\baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"c:", @"/", @"foo", @"bar", @"baz", - nil])], @"c:/foo\\bar\\baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"foo/", @"bar\\", @"", @"baz", @"\\", - nil])], @"foo/bar\\baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - [OFArray arrayWithObject: @"foo"]], @"foo"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - [OFArray arrayWithObject: @"c:"]], @"c:"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - [OFArray arrayWithObject: @"c:\\"]], @"c:\\"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - [OFArray arrayWithObject: @"\\"]], @"\\"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - [OFArray arrayWithObject: @"/"]], @"/"); - -# ifdef OF_WINDOWS - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"\\\\", @"foo", @"bar", nil])], - @"\\\\foo\\bar"); -# endif -# elif defined(OF_AMIGAOS) - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"dh0:", @"foo", @"bar", @"baz", nil])], - @"dh0:foo/bar/baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])], - @"foo/bar/baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"foo/", @"bar", @"", @"baz", @"/", - nil])], @"foo//bar/baz//"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - [OFArray arrayWithObject: @"foo"]], @"foo"); -# elif defined(OF_WII) || defined(OF_NINTENDO_DS) || \ - defined(OF_NINTENDO_3DS) || defined(OF_NINTENDO_SWITCH) - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])], - @"foo/bar/baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"sdmc:", @"foo", @"bar", @"baz", - nil])], @"sdmc:/foo/bar/baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"foo/", @"bar/", @"", @"baz", @"/", - nil])], @"foo/bar/baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - [OFArray arrayWithObject: @"foo"]], @"foo"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - [OFArray arrayWithObject: @"sdmc:"]], @"sdmc:/"); -# else - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"/", @"foo", @"bar", @"baz", nil])], - @"/foo/bar/baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])], - @"foo/bar/baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - ([OFArray arrayWithObjects: @"foo/", @"bar", @"", @"baz", @"/", - nil])], @"foo/bar/baz"); - - OTAssertEqualObjects([self.stringClass pathWithComponents: - [OFArray arrayWithObject: @"foo"]], @"foo"); -# endif -} - -- (void)testPathComponents -{ -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:/tmp"] pathComponents], - ([OFArray arrayWithObjects: @"c:/", @"tmp", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:\\tmp\\"] pathComponents], - ([OFArray arrayWithObjects: @"c:\\", @"tmp", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:\\"] pathComponents], [OFArray arrayWithObject: @"c:\\"]); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:/"] pathComponents], [OFArray arrayWithObject: @"c:/"]); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:"] pathComponents], [OFArray arrayWithObject: @"c:"]); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo\\bar"] pathComponents], - ([OFArray arrayWithObjects: @"foo", @"bar", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo\\bar/baz/"] pathComponents], - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo\\/"] pathComponents], [OFArray arrayWithObject: @"foo"]); - -# ifdef OF_WINDOWS - OTAssertEqualObjects([[self.stringClass stringWithString: - @"\\\\foo\\bar"] pathComponents], - ([OFArray arrayWithObjects: @"\\\\", @"foo", @"bar", nil])); -# endif - - OTAssertEqualObjects([[self.stringClass stringWithString: @""] - pathComponents], [OFArray array]); -# elif defined(OF_AMIGAOS) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:tmp"] pathComponents], - ([OFArray arrayWithObjects: @"dh0:", @"tmp", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:tmp/"] pathComponents], - ([OFArray arrayWithObjects: @"dh0:", @"tmp", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:/"] pathComponents], - ([OFArray arrayWithObjects: @"dh0:", @"/", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] pathComponents], - ([OFArray arrayWithObjects: @"foo", @"bar", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar/baz/"] pathComponents], - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo//"] pathComponents], - ([OFArray arrayWithObjects: @"foo", @"/", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: @""] - pathComponents], [OFArray array]); -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ - defined(OF_NINTENDO_SWITCH) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"sdmc:/tmp"] pathComponents], - ([OFArray arrayWithObjects: @"sdmc:", @"tmp", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"sdmc:/"] pathComponents], [OFArray arrayWithObject: @"sdmc:"]); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] pathComponents], - ([OFArray arrayWithObjects: @"foo", @"bar", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar/baz/"] pathComponents], - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo//"] pathComponents], [OFArray arrayWithObject: @"foo"]); - - OTAssertEqualObjects([[self.stringClass stringWithString: @""] - pathComponents], [OFArray array]); -# else - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/tmp"] pathComponents], - ([OFArray arrayWithObjects: @"/", @"tmp", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/tmp/"] pathComponents], - ([OFArray arrayWithObjects: @"/", @"tmp", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/"] pathComponents], [OFArray arrayWithObject: @"/"]); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] pathComponents], - ([OFArray arrayWithObjects: @"foo", @"bar", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar/baz/"] pathComponents], - ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo//"] pathComponents], [OFArray arrayWithObject: @"foo"]); - - OTAssertEqualObjects([[self.stringClass stringWithString: @""] - pathComponents], [OFArray array]); -# endif -} - -- (void)testLastPathComponent -{ -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:/tmp"] lastPathComponent], @"tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:\\tmp\\"] lastPathComponent], @"tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:\\"] lastPathComponent], @"c:\\"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:/"] lastPathComponent], @"c:/"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"\\"] lastPathComponent], @"\\"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] lastPathComponent], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo\\bar"] lastPathComponent], @"bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar/baz/"] lastPathComponent], @"baz"); -# ifdef OF_WINDOWS - OTAssertEqualObjects([[self.stringClass stringWithString: - @"\\\\foo\\bar"] lastPathComponent], @"bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"\\\\"] lastPathComponent], @"\\\\"); -# endif -# elif defined(OF_AMIGAOS) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:tmp"] lastPathComponent], @"tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:tmp/"] lastPathComponent], @"tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:/"] lastPathComponent], @"/"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:"] lastPathComponent], @"dh0:"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] lastPathComponent], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] lastPathComponent], @"bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar/baz/"] lastPathComponent], @"baz"); -# elif defined(OF_WII) || defined(OF_NINTENDO_DS) || \ - defined(OF_NINTENDO_3DS) || defined(OF_NINTENDO_SWITCH) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"sdmc:/tmp"] lastPathComponent], @"tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"sdmc:/tmp/"] lastPathComponent], @"tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"sdmc:/"] lastPathComponent], @"sdmc:/"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"sdmc:"] lastPathComponent], @"sdmc:"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] lastPathComponent], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] lastPathComponent], @"bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar/baz/"] lastPathComponent], @"baz"); -# else - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/tmp"] lastPathComponent], @"tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/tmp/"] lastPathComponent], @"tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/"] lastPathComponent], @"/"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] lastPathComponent], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] lastPathComponent], @"bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar/baz/"] lastPathComponent], @"baz"); -# endif -} - -- (void)testPathExtension -{ - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo.bar"] pathExtension], @"bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/.bar"] pathExtension], @""); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/.bar.baz"] pathExtension], @"baz"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar.baz/"] pathExtension], @"baz"); -} - -- (void)testStringByDeletingLastPathComponent -{ -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"\\tmp"] stringByDeletingLastPathComponent], @"\\"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/tmp/"] stringByDeletingLastPathComponent], @"/"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:\\"] stringByDeletingLastPathComponent], @"c:\\"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:/"] stringByDeletingLastPathComponent], @"c:/"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:\\tmp/foo/"] stringByDeletingLastPathComponent], @"c:\\tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo\\bar"] stringByDeletingLastPathComponent], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"\\"] stringByDeletingLastPathComponent], @"\\"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] stringByDeletingLastPathComponent], @"."); -# ifdef OF_WINDOWS - OTAssertEqualObjects([[self.stringClass stringWithString: - @"\\\\foo\\bar"] stringByDeletingLastPathComponent], @"\\\\foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"\\\\foo"] stringByDeletingLastPathComponent], @"\\\\"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"\\\\"] stringByDeletingLastPathComponent], @"\\\\"); -# endif -# elif defined(OF_AMIGAOS) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:"] stringByDeletingLastPathComponent], @"dh0:"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:tmp"] stringByDeletingLastPathComponent], @"dh0:"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:tmp/"] stringByDeletingLastPathComponent], @"dh0:"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:/"] stringByDeletingLastPathComponent], @"dh0:"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:tmp/foo/"] stringByDeletingLastPathComponent], @"dh0:tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] stringByDeletingLastPathComponent], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] stringByDeletingLastPathComponent], @""); -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ - defined(OF_NINTENDO_SWITCH) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/tmp/"] stringByDeletingLastPathComponent], @""); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"sdmc:/tmp/foo/"] stringByDeletingLastPathComponent], - @"sdmc:/tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"sdmc:/"] stringByDeletingLastPathComponent], @"sdmc:/"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] stringByDeletingLastPathComponent], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/"] stringByDeletingLastPathComponent], @""); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] stringByDeletingLastPathComponent], @"."); -# else - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/tmp"] stringByDeletingLastPathComponent], @"/"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/tmp/"] stringByDeletingLastPathComponent], @"/"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/tmp/foo/"] stringByDeletingLastPathComponent], @"/tmp"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo/bar"] stringByDeletingLastPathComponent], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/"] stringByDeletingLastPathComponent], @"/"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo"] stringByDeletingLastPathComponent], @"."); -# endif -} - -- (void)testStringByDeletingPathExtension -{ -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo.bar"] stringByDeletingPathExtension], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo..bar"] stringByDeletingPathExtension], @"foo."); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:/foo.\\bar"] stringByDeletingPathExtension], @"c:/foo.\\bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:\\foo./bar.baz"] stringByDeletingPathExtension], - @"c:\\foo.\\bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo.bar/"] stringByDeletingPathExtension], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @".foo"] stringByDeletingPathExtension], @".foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @".foo.bar"] stringByDeletingPathExtension], @".foo"); -# elif defined(OF_AMIGAOS) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo.bar"] stringByDeletingPathExtension], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo..bar"] stringByDeletingPathExtension], @"foo."); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:foo.bar"] stringByDeletingPathExtension], @"dh0:foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:foo./bar"] stringByDeletingPathExtension], @"dh0:foo./bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"dh0:foo./bar.baz"] stringByDeletingPathExtension], - @"dh0:foo./bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo.bar/"] stringByDeletingPathExtension], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @".foo"] stringByDeletingPathExtension], @".foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @".foo\\bar"] stringByDeletingPathExtension], @".foo\\bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @".foo.bar"] stringByDeletingPathExtension], @".foo"); -# elif defined(OF_WII) || defined(OF_NINTENDO_DS) || \ - defined(OF_NINTENDO_3DS) || defined(OF_NINTENDO_SWITCH) - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo.bar"] stringByDeletingPathExtension], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo..bar"] stringByDeletingPathExtension], @"foo."); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"sdmc:/foo./bar"] stringByDeletingPathExtension], - @"sdmc:/foo./bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"sdmc:/foo./bar.baz"] stringByDeletingPathExtension], - @"sdmc:/foo./bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo.bar/"] stringByDeletingPathExtension], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @".foo"] stringByDeletingPathExtension], @".foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @".foo.bar"] stringByDeletingPathExtension], @".foo"); -# else - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo.bar"] stringByDeletingPathExtension], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo..bar"] stringByDeletingPathExtension], @"foo."); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/foo./bar"] stringByDeletingPathExtension], @"/foo./bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"/foo./bar.baz"] stringByDeletingPathExtension], @"/foo./bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @"foo.bar/"] stringByDeletingPathExtension], @"foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @".foo"] stringByDeletingPathExtension], @".foo"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @".foo\\bar"] stringByDeletingPathExtension], @".foo\\bar"); - OTAssertEqualObjects([[self.stringClass stringWithString: - @".foo.bar"] stringByDeletingPathExtension], @".foo"); -# endif -} - -# if defined(OF_WINDOWS) || defined(OF_MSDOS) -- (void)testStringByStandardizingPath -{ - /* TODO: Add more tests */ - - OTAssertEqualObjects([[self.stringClass stringWithString: - @"c:\\..\\asd"] stringByStandardizingPath], - @"c:\\..\\asd"); - -# ifndef OF_MSDOS - OTAssertEqualObjects([[self.stringClass stringWithString: - @"\\\\foo\\..\\bar\\qux"] stringByStandardizingPath], - @"\\\\bar\\qux"); -# endif -} -# endif -#endif -@end - -@implementation CustomString -- (instancetype)init -{ - self = [super init]; - - @try { - _string = [[OFMutableString alloc] init]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithString: (OFString *)string -{ - self = [super init]; - - @try { - _string = [string mutableCopy]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithCString: (const char *)cString - encoding: (OFStringEncoding)encoding - length: (size_t)length -{ - self = [super init]; - - @try { - _string = [[OFMutableString alloc] initWithCString: cString - encoding: encoding - length: length]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithUTF16String: (const OFChar16 *)UTF16String - length: (size_t)length - byteOrder: (OFByteOrder)byteOrder -{ - self = [super init]; - - @try { - _string = [[OFMutableString alloc] - initWithUTF16String: UTF16String - length: length - byteOrder: byteOrder]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithUTF32String: (const OFChar32 *)UTF32String - length: (size_t)length - byteOrder: (OFByteOrder)byteOrder -{ - self = [super init]; - - @try { - _string = [[OFMutableString alloc] - initWithUTF32String: UTF32String - length: length - byteOrder: byteOrder]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithFormat: (OFConstantString *)format - arguments: (va_list)arguments -{ - self = [super init]; - - @try { - _string = [[OFMutableString alloc] initWithFormat: format - arguments: arguments]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_string release]; - - [super dealloc]; -} - -- (OFUnichar)characterAtIndex: (size_t)idx -{ - return [_string characterAtIndex: idx]; -} - -- (size_t)length -{ - return _string.length; -} -@end - -@implementation EntityHandler -- (OFString *)string: (OFString *)string - containsUnknownEntityNamed: (OFString *)entity -{ - if ([entity isEqual: @"foo"]) - return @"bar"; - - return nil; -} -@end DELETED new_tests/OFSubprocessTests.m Index: new_tests/OFSubprocessTests.m ================================================================== --- new_tests/OFSubprocessTests.m +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFSubprocessTests: OTTestCase -@end - -@implementation OFSubprocessTests -- (void)testSubprocess -{ -#ifdef OF_HAVE_FILES - OFString *program = [@"subprocess" stringByAppendingPathComponent: - @"subprocess" @PROG_SUFFIX]; -#else - OFString *program = @"subprocess/subprocess" @PROG_SUFFIX; -#endif - OFArray *arguments = [OFArray arrayWithObjects: @"tést", @"123", nil]; - OFMutableDictionary *environment = - [[[OFApplication environment] mutableCopy] autorelease]; - OFSubprocess *subprocess; - - [environment setObject: @"yés" forKey: @"tëst"]; - - subprocess = [OFSubprocess subprocessWithProgram: program - programName: program - arguments: arguments - environment: environment]; - - [subprocess writeLine: @"Hellö world!"]; -#ifdef OF_HAVE_UNICODE_TABLES - OTAssertEqualObjects([subprocess readLine], @"HELLÖ WORLD!"); -#else - OTAssertEqualObjects([subprocess readLine], @"HELLö WORLD!"); -#endif - - [subprocess closeForWriting]; - - OTAssertEqual([subprocess waitForTermination], 0); -} -@end DELETED new_tests/OFSystemInfoTests.m Index: new_tests/OFSystemInfoTests.m ================================================================== --- new_tests/OFSystemInfoTests.m +++ /dev/null @@ -1,201 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFSystemInfoTests: OTTestCase -@end - -#ifdef OF_HAVE_SOCKETS -static void -appendAddresses(OFMutableString *string, OFData *addresses, bool *firstAddress) -{ - size_t count = addresses.count; - - for (size_t i = 0; i < count; i++) { - const OFSocketAddress *address = [addresses itemAtIndex: i]; - - if (!*firstAddress) - [string appendString: @", "]; - - *firstAddress = false; - - [string appendString: OFSocketAddressString(address)]; - } -} -#endif - -@implementation OFSystemInfoTests -+ (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, id) *) *)summary -{ - OFMutableArray *summary = [OFMutableArray array]; -#ifdef OF_HAVE_SOCKETS - OFDictionary *networkInterfaces; - OFMutableString *networkInterfacesString; - bool firstInterface = true; -#endif - -#define ADD(name, value) \ - [summary addObject: [OFPair pairWithFirstObject: name \ - secondObject: value]]; -#define ADD_UINT(name, value) \ - ADD(name, [OFNumber numberWithUnsignedInt: value]); -#define ADD_ULONGLONG(name, value) \ - ADD(name, [OFNumber numberWithUnsignedLongLong: value]); -#define ADD_BOOL(name, value) \ - ADD(name, [OFNumber numberWithBool: value]); - - ADD(@"ObjFW version", [OFSystemInfo ObjFWVersion]) - ADD_UINT(@"ObjFW version major", [OFSystemInfo ObjFWVersionMajor]) - ADD_UINT(@"ObjFW version minor", [OFSystemInfo ObjFWVersionMinor]) - ADD(@"Operating system name", [OFSystemInfo operatingSystemName]); - ADD(@"Operating system version", [OFSystemInfo operatingSystemVersion]); - ADD_ULONGLONG(@"Page size", [OFSystemInfo pageSize]); - ADD_ULONGLONG(@"Number of CPUs", [OFSystemInfo numberOfCPUs]); - ADD(@"User config IRI", [OFSystemInfo userConfigIRI].string); - ADD(@"User data IRI", [OFSystemInfo userDataIRI].string); - ADD(@"Temporary directory IRI", - [OFSystemInfo temporaryDirectoryIRI].string); - ADD(@"CPU vendor", [OFSystemInfo CPUVendor]); - ADD(@"CPU model", [OFSystemInfo CPUModel]); - -#if defined(OF_AMD64) || defined(OF_X86) - ADD_BOOL(@"Supports MMX", [OFSystemInfo supportsMMX]); - ADD_BOOL(@"Supports 3DNow!", [OFSystemInfo supports3DNow]); - ADD_BOOL(@"Supports enhanced 3DNow!", - [OFSystemInfo supportsEnhanced3DNow]); - ADD_BOOL(@"Supports SSE", [OFSystemInfo supportsSSE]); - ADD_BOOL(@"Supports SSE2", [OFSystemInfo supportsSSE2]); - ADD_BOOL(@"Supports SSE3", [OFSystemInfo supportsSSE3]); - ADD_BOOL(@"Supports SSSE3", [OFSystemInfo supportsSSSE3]); - ADD_BOOL(@"Supports SSE4.1", [OFSystemInfo supportsSSE41]); - ADD_BOOL(@"Supports SSE4.2", [OFSystemInfo supportsSSE42]); - ADD_BOOL(@"Supports AVX", [OFSystemInfo supportsAVX]); - ADD_BOOL(@"Supports AVX2", [OFSystemInfo supportsAVX2]); - ADD_BOOL(@"Supports AES-NI", [OFSystemInfo supportsAESNI]); - ADD_BOOL(@"Supports SHA extensions", - [OFSystemInfo supportsSHAExtensions]); - ADD_BOOL(@"Supports fused multiply-add", - [OFSystemInfo supportsFusedMultiplyAdd]); - ADD_BOOL(@"Supports F16C", [OFSystemInfo supportsF16C]); - ADD_BOOL(@"Supports AVX-512 Foundation", - [OFSystemInfo supportsAVX512Foundation]); - ADD_BOOL(@"Supports AVX-512 Conflict Detection Instructions", - [OFSystemInfo supportsAVX512ConflictDetectionInstructions]); - ADD_BOOL(@"Supports AVX-512 Exponential and Reciprocal Instructions", - [OFSystemInfo supportsAVX512ExponentialAndReciprocalInstructions]); - ADD_BOOL(@"Supports AVX-512 Prefetch Instructions", - [OFSystemInfo supportsAVX512PrefetchInstructions]); - ADD_BOOL(@"Supports AVX-512 Vector Length Extensions", - [OFSystemInfo supportsAVX512VectorLengthExtensions]); - ADD_BOOL(@"Supports AVX-512 Doubleword and Quadword Instructions", - [OFSystemInfo supportsAVX512DoublewordAndQuadwordInstructions]); - ADD_BOOL(@"Supports AVX-512 Byte and Word Instructions", - [OFSystemInfo supportsAVX512ByteAndWordInstructions]); - ADD_BOOL(@"Supports AVX-512 Integer Fused Multiply Add", - [OFSystemInfo supportsAVX512IntegerFusedMultiplyAdd]); - ADD_BOOL(@"Supports AVX-512 Vector Byte Manipulation Instructions", - [OFSystemInfo supportsAVX512VectorByteManipulationInstructions]); - ADD_BOOL(@"Supports AVX-512 Vector Population Count Instruction", - [OFSystemInfo supportsAVX512VectorPopulationCountInstruction]); - ADD_BOOL(@"Supports AVX-512 Vector Neutral Network Instructions", - [OFSystemInfo supportsAVX512VectorNeuralNetworkInstructions]); - ADD_BOOL(@"Supports AVX-512 Vector Byte Manipulation Instructions 2", - [OFSystemInfo supportsAVX512VectorByteManipulationInstructions2]); - ADD_BOOL(@"Supports AVX-512 Bit Algorithms", - [OFSystemInfo supportsAVX512BitAlgorithms]); - ADD_BOOL(@"Supports AVX-512 Float16 Instructions", - [OFSystemInfo supportsAVX512Float16Instructions]); - ADD_BOOL(@"Supports AVX-512 BFloat16 Instructions", - [OFSystemInfo supportsAVX512BFloat16Instructions]); -#endif - -#ifdef OF_POWERPC - ADD_BOOL(@"Supports AltiVec", [OFSystemInfo supportsAltiVec]); -#endif - -#undef ADD -#undef ADD_UINT -#undef ADD_ULONGLONG -#undef ADD_BOOL - -#ifdef OF_HAVE_SOCKETS - networkInterfaces = [OFSystemInfo networkInterfaces]; - networkInterfacesString = [OFMutableString string]; - for (OFString *name in networkInterfaces) { - bool firstAddress = true; - OFNetworkInterface interface; - OFData *hardwareAddress; - - if (!firstInterface) - [networkInterfacesString appendString: @"; "]; - - firstInterface = false; - - [networkInterfacesString appendFormat: @"%@(", name]; - - interface = [networkInterfaces objectForKey: name]; - - appendAddresses(networkInterfacesString, - [interface objectForKey: OFNetworkInterfaceIPv4Addresses], - &firstAddress); -# ifdef OF_HAVE_IPV6 - appendAddresses(networkInterfacesString, - [interface objectForKey: OFNetworkInterfaceIPv6Addresses], - &firstAddress); -# endif -# ifdef OF_HAVE_IPX - appendAddresses(networkInterfacesString, - [interface objectForKey: OFNetworkInterfaceIPXAddresses], - &firstAddress); -# endif -# ifdef OF_HAVE_APPLETALK - appendAddresses(networkInterfacesString, - [interface objectForKey: - OFNetworkInterfaceAppleTalkAddresses], &firstAddress); -# endif - - hardwareAddress = [interface - objectForKey: OFNetworkInterfaceHardwareAddress]; - if (hardwareAddress != nil) { - const unsigned char *bytes = hardwareAddress.items; - size_t length = hardwareAddress.count; - - if (!firstAddress) - [networkInterfacesString appendString: @", "]; - - for (size_t i = 0; i < length; i++) { - if (i > 0) - [networkInterfacesString - appendString: @":"]; - - [networkInterfacesString - appendFormat: @"%02X", bytes[i]]; - } - } - - [networkInterfacesString appendString: @")"]; - } - [summary addObject: - [OFPair pairWithFirstObject: @"Network interfaces" - secondObject: networkInterfacesString]]; -#endif - - return summary; -} -@end DELETED new_tests/OFTCPSocketTests.m Index: new_tests/OFTCPSocketTests.m ================================================================== --- new_tests/OFTCPSocketTests.m +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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" - -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFTCPSocketTests: OTTestCase -@end - -@implementation OFTCPSocketTests -- (void)testTCPSocket -{ - OFTCPSocket *server, *client, *accepted; - OFSocketAddress address; - char buffer[6]; - - server = [OFTCPSocket socket]; - client = [OFTCPSocket socket]; - - address = [server bindToHost: @"127.0.0.1" port: 0]; - [server listen]; - - [client connectToHost: @"127.0.0.1" - port: OFSocketAddressIPPort(&address)]; - - accepted = [server accept]; - OTAssertEqualObjects(OFSocketAddressString(accepted.remoteAddress), - @"127.0.0.1"); - - [client writeString: @"Hello!"]; - - [accepted readIntoBuffer: buffer exactLength: 6]; - OTAssertEqual(memcmp(buffer, "Hello!", 6), 0); -} -@end DELETED new_tests/OFThreadTests.m Index: new_tests/OFThreadTests.m ================================================================== --- new_tests/OFThreadTests.m +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFThreadTests: OTTestCase -@end - -@interface TestThread: OFThread -@end - -@implementation TestThread -- (id)main -{ - [[OFThread threadDictionary] setObject: @"bar" forKey: @"foo"]; - OFEnsure([[[OFThread threadDictionary] - objectForKey: @"foo"] isEqual: @"bar"]); - - return @"success"; -} -@end - -@implementation OFThreadTests -- (void)testThread -{ - TestThread *thread = [TestThread thread]; - - [thread start]; - - OTAssertEqualObjects([thread join], @"success"); - OTAssertNil([[OFThread threadDictionary] objectForKey: @"foo"]); -} -@end DELETED new_tests/OFUDPSocketTests.m Index: new_tests/OFUDPSocketTests.m ================================================================== --- new_tests/OFUDPSocketTests.m +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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" - -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFUDPSocketTests: OTTestCase -@end - -@implementation OFUDPSocketTests -- (void)testUDPSocket -{ - OFUDPSocket *sock = [OFUDPSocket socket]; - OFSocketAddress addr1, addr2; - char buffer[6]; - - sock = [OFUDPSocket socket]; - - addr1 = [sock bindToHost: @"127.0.0.1" port: 0]; - OTAssertEqualObjects(OFSocketAddressString(&addr1), @"127.0.0.1"); - - [sock sendBuffer: "Hello" length: 6 receiver: &addr1]; - - [sock receiveIntoBuffer: buffer length: 6 sender: &addr2]; - OTAssertEqual(memcmp(buffer, "Hello", 6), 0); - OTAssertEqualObjects(OFSocketAddressString(&addr2), @"127.0.0.1"); - OTAssertEqual(OFSocketAddressIPPort(&addr2), - OFSocketAddressIPPort(&addr1)); -} -@end DELETED new_tests/OFUNIXDatagramSocketTests.m Index: new_tests/OFUNIXDatagramSocketTests.m ================================================================== --- new_tests/OFUNIXDatagramSocketTests.m +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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" - -#include -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFUNIXDatagramSocketTests: OTTestCase -@end - -@implementation OFUNIXDatagramSocketTests -- (void)testUNIXDatagramSocket -{ - OFUNIXDatagramSocket *sock = [OFUNIXDatagramSocket socket]; - OFString *path; - OFSocketAddress address1, address2; - char buffer[5]; - -#if defined(OF_HAVE_FILES) && !defined(OF_IOS) - path = [[OFSystemInfo temporaryDirectoryIRI] - IRIByAppendingPathComponent: [[OFUUID UUID] UUIDString]] - .fileSystemRepresentation; -#else - /* - * We can have sockets, including UNIX sockets, while file support is - * disabled. - * - * We also use this code path for iOS, as the temporaryDirectoryIRI is - * too long on the iOS simulator. - */ - path = [OFString stringWithFormat: @"/tmp/%@", - [[OFUUID UUID] UUIDString]]; -#endif - - @try { - address1 = [sock bindToPath: path]; - } @catch (OFBindSocketFailedException *e) { - switch (e.errNo) { - case EAFNOSUPPORT: - case EPERM: - OTSkip(@"UNIX datagram sockets unsupported"); - default: - @throw e; - } - } - - @try { - [sock sendBuffer: "Hello" length: 5 receiver: &address1]; - - OTAssertEqual([sock receiveIntoBuffer: buffer - length: 5 - sender: &address2], 5); - OTAssertEqual(memcmp(buffer, "Hello", 5), 0); - OTAssertTrue(OFSocketAddressEqual(&address1, &address2)); - OTAssertEqual(OFSocketAddressHash(&address1), - OFSocketAddressHash(&address2)); - } @finally { -#ifdef OF_HAVE_FILES - [[OFFileManager defaultManager] removeItemAtPath: path]; -#endif - } -} -@end DELETED new_tests/OFUNIXStreamSocketTests.m Index: new_tests/OFUNIXStreamSocketTests.m ================================================================== --- new_tests/OFUNIXStreamSocketTests.m +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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" - -#include -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFUNIXStreamSocketTests: OTTestCase -@end - -@implementation OFUNIXStreamSocketTests -- (void)testUNIXStreamSocket -{ - OFString *path; - OFUNIXStreamSocket *sockClient, *sockServer, *sockAccepted; - char buffer[5]; - -#if defined(OF_HAVE_FILES) && !defined(OF_IOS) - path = [[OFSystemInfo temporaryDirectoryIRI] - IRIByAppendingPathComponent: [[OFUUID UUID] UUIDString]] - .fileSystemRepresentation; -#else - /* - * We can have sockets, including UNIX sockets, while file support is - * disabled. - * - * We also use this code path for iOS, as the temporaryDirectory:RI is - * too long on the iOS simulator. - */ - path = [OFString stringWithFormat: @"/tmp/%@", - [[OFUUID UUID] UUIDString]]; -#endif - - sockClient = [OFUNIXStreamSocket socket]; - sockServer = [OFUNIXStreamSocket socket]; - - @try { - [sockServer bindToPath: path]; - } @catch (OFBindSocketFailedException *e) { - switch (e.errNo) { - case EAFNOSUPPORT: - case EPERM: - OTSkip(@"UNIX stream sockets unsupported"); - default: - @throw e; - } - } - - @try { - [sockServer listen]; - - [sockClient connectToPath: path]; - - sockAccepted = [sockServer accept]; - [sockAccepted writeBuffer: "Hello" length: 5]; - - OTAssertEqual([sockClient readIntoBuffer: buffer length: 5], 5); - OTAssertEqual(memcmp(buffer, "Hello", 5), 0); - - OTAssertEqual(OFSocketAddressUNIXPath( - sockAccepted.remoteAddress).length, 0); - } @finally { -#ifdef OF_HAVE_FILES - [[OFFileManager defaultManager] removeItemAtPath: path]; -#endif - } -} -@end DELETED new_tests/OFUTF8StringTests.m Index: new_tests/OFUTF8StringTests.m ================================================================== --- new_tests/OFUTF8StringTests.m +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 "OFStringTests.h" - -#import "OFUTF8String.h" - -@interface OFUTF8StringTests: OFStringTests -@end - -@implementation OFUTF8StringTests -- (Class)arrayClass -{ - return [OFUTF8String class]; -} -@end DELETED new_tests/OFValueTests.m Index: new_tests/OFValueTests.m ================================================================== --- new_tests/OFValueTests.m +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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" - -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFValueTests: OTTestCase -@end - -@implementation OFValueTests -- (void)testObjCType -{ - OFRange range = OFMakeRange(1, 64); - OFValue *value = [OFValue valueWithBytes: &range - objCType: @encode(OFRange)]; - - OTAssertEqual(strcmp(value.objCType, @encode(OFRange)), 0); -} - -- (void)testGetValueSize -{ - OFRange range = OFMakeRange(1, 64), range2; - OFValue *value = [OFValue valueWithBytes: &range - objCType: @encode(OFRange)]; - - [value getValue: &range2 size: sizeof(OFRange)]; - OTAssert(OFEqualRanges(range2, range)); -} - -- (void)testGetValueSizeThrowsOnWrongSize -{ - OFRange range = OFMakeRange(1, 64); - OFValue *value = [OFValue valueWithBytes: &range - objCType: @encode(OFRange)]; - - OTAssertThrowsSpecific( - [value getValue: &range size: sizeof(OFRange) - 1], - OFOutOfRangeException); -} - -- (void)testPointer -{ - void *pointer = &pointer; - OFValue *value = [OFValue valueWithPointer: pointer]; - - OTAssertEqual(value.pointerValue, pointer); - OTAssertEqual([[OFValue valueWithBytes: &pointer - objCType: @encode(void *)] pointerValue], - pointer); - - OTAssertThrowsSpecific( - [[OFValue valueWithBytes: "a" - objCType: @encode(char)] pointerValue], - OFOutOfRangeException); -} - -- (void)testNonretainedObject -{ - id object = (id)&object; - OFValue *value = [OFValue valueWithNonretainedObject: object]; - - OTAssertEqual(value.nonretainedObjectValue, object); - OTAssertEqual([[OFValue - valueWithBytes: &object - objCType: @encode(id)] nonretainedObjectValue], object); - - OTAssertThrowsSpecific( - [[OFValue valueWithBytes: "a" - objCType: @encode(char)] nonretainedObjectValue], - OFOutOfRangeException); -} - -- (void)testRange -{ - OFRange range = OFMakeRange(1, 64), range2; - OFValue *value = [OFValue valueWithRange: range]; - - OTAssert(OFEqualRanges(value.rangeValue, range)); - OTAssert(OFEqualRanges( - [[OFValue valueWithBytes: &range - objCType: @encode(OFRange)] rangeValue], range)); - - [value getValue: &range2 size: sizeof(range2)]; - OTAssert(OFEqualRanges(range2, range)); - - OTAssertThrowsSpecific( - [[OFValue valueWithBytes: "a" - objCType: @encode(char)] rangeValue], - OFOutOfRangeException); -} - -- (void)testPoint -{ - OFPoint point = OFMakePoint(1.5f, 3.0f), point2; - OFValue *value = [OFValue valueWithPoint: point]; - - OTAssert(OFEqualPoints(value.pointValue, point)); - OTAssert(OFEqualPoints( - [[OFValue valueWithBytes: &point - objCType: @encode(OFPoint)] pointValue], point)); - - [value getValue: &point2 size: sizeof(point2)]; - OTAssert(OFEqualPoints(point2, point)); - - OTAssertThrowsSpecific( - [[OFValue valueWithBytes: "a" - objCType: @encode(char)] pointValue], - OFOutOfRangeException); -} - -- (void)testSize -{ - OFSize size = OFMakeSize(4.5f, 5.0f), size2; - OFValue *value = [OFValue valueWithSize: size]; - - OTAssert(OFEqualSizes(value.sizeValue, size)); - OTAssert(OFEqualSizes( - [[OFValue valueWithBytes: &size - objCType: @encode(OFSize)] sizeValue], size)); - - [value getValue: &size2 size: sizeof(size2)]; - OTAssert(OFEqualSizes(size2, size)); - - OTAssertThrowsSpecific( - [[OFValue valueWithBytes: "a" - objCType: @encode(char)] sizeValue], - OFOutOfRangeException); -} - -- (void)testRect -{ - OFRect rect = OFMakeRect(1.5f, 3.0f, 4.5f, 6.0f), rect2; - OFValue *value = [OFValue valueWithRect: rect]; - - OTAssert(OFEqualRects(value.rectValue, rect)); - OTAssert(OFEqualRects( - [[OFValue valueWithBytes: &rect - objCType: @encode(OFRect)] rectValue], rect)); - - [value getValue: &rect2 size: sizeof(rect2)]; - OTAssert(OFEqualRects(rect2, rect)); - - OTAssertThrowsSpecific( - [[OFValue valueWithBytes: "a" objCType: @encode(char)] rectValue], - OFOutOfRangeException); -} - -- (void)testIsEqual -{ - OFRect rect = OFMakeRect(1.5f, 3.0f, 4.5f, 6.0f); - - OTAssertEqualObjects([OFValue valueWithRect: rect], - [OFValue valueWithBytes: &rect - objCType: @encode(OFRect)]); - OTAssertNotEqualObjects( - [OFValue valueWithBytes: "a" objCType: @encode(signed char)], - [OFValue valueWithBytes: "a" objCType: @encode(unsigned char)]); - OTAssertNotEqualObjects( - [OFValue valueWithBytes: "a" objCType: @encode(char)], - [OFValue valueWithBytes: "b" objCType: @encode(char)]); -} -@end DELETED new_tests/OFWindowsRegistryKeyTests.m Index: new_tests/OFWindowsRegistryKeyTests.m ================================================================== --- new_tests/OFWindowsRegistryKeyTests.m +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFWindowsRegistryKeyTests: OTTestCase -{ - OFWindowsRegistryKey *_softwareKey, *_objFWKey; -} -@end - -@implementation OFWindowsRegistryKeyTests -- (void)setUp -{ - [super setUp]; - - _softwareKey = [[[OFWindowsRegistryKey currentUserKey] - openSubkeyAtPath: @"Software" - accessRights: KEY_ALL_ACCESS - options: 0] retain]; - _objFWKey = [[_softwareKey createSubkeyAtPath: @"ObjFW" - accessRights: KEY_ALL_ACCESS - securityAttributes: NULL - options: 0 - disposition: NULL] retain]; -} - -- (void)tearDown -{ - [_softwareKey deleteSubkeyAtPath: @"ObjFW"]; - - [super tearDown]; -} - -- (void)dealloc -{ - [_softwareKey release]; - [_objFWKey release]; - - [super dealloc]; -} - -- (void)testClassesRootKey -{ - OTAssertEqual([[OFWindowsRegistryKey classesRootKey] class], - [OFWindowsRegistryKey class]); -} - -- (void)testCurrentConfigKey -{ - OTAssertEqual([[OFWindowsRegistryKey currentConfigKey] class], - [OFWindowsRegistryKey class]); -} - -- (void)testCurrentUserKey -{ - OTAssertEqual([[OFWindowsRegistryKey currentUserKey] class], - [OFWindowsRegistryKey class]); -} - -- (void)testLocalMachineKey -{ - OTAssertEqual([[OFWindowsRegistryKey localMachineKey] class], - [OFWindowsRegistryKey class]); -} - -- (void)testOpenSubkeyAtPathAccessRightsOptionsThrowsForNonExistentKey -{ - OTAssertThrowsSpecific([[OFWindowsRegistryKey currentUserKey] - openSubkeyAtPath: @"nonexistent" - accessRights: KEY_ALL_ACCESS - options: 0], OFOpenWindowsRegistryKeyFailedException); -} - -- (void)testSetAndGetData -{ - OFData *data = [OFData dataWithItems: "abcdef" count: 6]; - DWORD type; - - [_objFWKey setData: data forValueNamed: @"data" type: REG_BINARY]; - OTAssertEqualObjects([_objFWKey dataForValueNamed: @"data" type: &type], - data); - OTAssertEqual(type, REG_BINARY); -} - -- (void)testSetAndGetString -{ - DWORD type; - - [_objFWKey setString: @"foobar" forValueNamed: @"string"]; - OTAssertEqualObjects([_objFWKey stringForValueNamed: @"string"], - @"foobar"); - - [_objFWKey setString: @"%PATH%;foo" - forValueNamed: @"expand" - type: REG_EXPAND_SZ]; - OTAssertEqualObjects([_objFWKey stringForValueNamed: @"expand" - type: &type], - @"%PATH%;foo"); - OTAssertEqual(type, REG_EXPAND_SZ); -} - -- (void)testDeleteValue -{ - [_objFWKey setString: @"foobar" forValueNamed: @"deleteme"]; - OTAssertEqualObjects([_objFWKey stringForValueNamed: @"deleteme"], - @"foobar"); - - [_objFWKey deleteValueNamed: @"deleteme"]; - OTAssertNil([_objFWKey stringForValueNamed: @"deleteme"]); -} -@end DELETED new_tests/OFXMLElementBuilderTests.m Index: new_tests/OFXMLElementBuilderTests.m ================================================================== --- new_tests/OFXMLElementBuilderTests.m +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFXMLElementBuilderTests: OTTestCase -{ - OFXMLNode *_nodes[2]; - size_t _i; -} -@end - -@implementation OFXMLElementBuilderTests -- (void)dealloc -{ - [_nodes[0] release]; - [_nodes[1] release]; - - [super dealloc]; -} - -- (void)elementBuilder: (OFXMLElementBuilder *)builder - didBuildElement: (OFXMLElement *)element -{ - OTAssertEqual(_i, 0); - _nodes[_i++] = [element retain]; -} - -- (void)elementBuilder: (OFXMLElementBuilder *)builder - didBuildOrphanNode: (OFXMLNode *)node -{ - OTAssertEqual(_i, 1); - _nodes[_i++] = [node retain]; -} - -- (void)testElementBuilder -{ - OFXMLParser *parser = [OFXMLParser parser]; - OFXMLElementBuilder *builder = [OFXMLElementBuilder builder]; - OFString *string = @"barbaz" - " " - ""; - - parser.delegate = builder; - builder.delegate = self; - - [parser parseString: string]; - OTAssertEqualObjects(_nodes[0].XMLString, string); - - [parser parseString: @""]; - OTAssertEqualObjects(_nodes[1].XMLString, @""); - - OTAssertEqual(_i, 2); -} -@end DELETED new_tests/OFXMLNodeTests.m Index: new_tests/OFXMLNodeTests.m ================================================================== --- new_tests/OFXMLNodeTests.m +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFXMLNodeTests: OTTestCase -@end - -@implementation OFXMLNodeTests -- (void)testElementWithName -{ - OTAssertEqualObjects( - [[OFXMLElement elementWithName: @"foo"] XMLString], - @""); -} - -- (void)testElementWithNameStringValue -{ - OTAssertEqualObjects( - [[OFXMLElement elementWithName: @"foo" - stringValue: @"b&ar"] XMLString], - @"b&ar"); -} - -- (void)testElementWithNameNamespace -{ - OFXMLElement *element; - - element = [OFXMLElement elementWithName: @"foo" - namespace: @"urn:objfw:test"]; - [element addAttributeWithName: @"test" stringValue: @"test"]; - [element setPrefix: @"objfw-test" forNamespace: @"urn:objfw:test"]; - OTAssertEqualObjects(element.XMLString, - @""); - - element = [OFXMLElement elementWithName: @"foo" - namespace: @"urn:objfw:test"]; - [element addAttributeWithName: @"test" stringValue: @"test"]; - OTAssertEqualObjects(element.XMLString, - @""); -} - -- (void)testElementWithNameNamespaceStringValue -{ - OFXMLElement *element = [OFXMLElement elementWithName: @"foo" - namespace: @"urn:objfw:test" - stringValue: @"x"]; - [element setPrefix: @"objfw-test" forNamespace: @"urn:objfw:test"]; - OTAssertEqualObjects(element.XMLString, - @"x"); -} - -- (void)testElementWithXMLStringAndStringValue -{ - OTAssertEqualObjects([[OFXMLElement elementWithXMLString: - @"\r\nfoo" - @"bazqux"] stringValue], - @"foobarbazqux"); -} - -- (void)testCharactersWithString -{ - OTAssertEqualObjects( - [[OFXMLCharacters charactersWithString: @""] XMLString], - @"<foo>"); -} - -- (void)testCDATAWithString -{ - OTAssertEqualObjects( - [[OFXMLCDATA CDATAWithString: @""] XMLString], - @"]]>"); -} - -- (void)testCommentWithText -{ - OTAssertEqualObjects( - [[OFXMLComment commentWithText: @" comment "] XMLString], - @""); -} - -- (void)testIsEqual -{ - OTAssertEqualObjects( - [OFXMLElement elementWithXMLString: @""], - [OFXMLElement elementWithXMLString: @""]); - - OTAssertEqualObjects( - [OFXMLElement elementWithXMLString: @""], - [OFXMLElement elementWithXMLString: @""]); - - OTAssertNotEqualObjects( - [OFXMLElement elementWithXMLString: @""], - [OFXMLElement elementWithXMLString: @""]); -} - -- (void)testHash -{ - OTAssertEqual( - [[OFXMLElement elementWithXMLString: @""] hash], - [[OFXMLElement elementWithXMLString: @""] - hash]); - - OTAssertEqual( - [[OFXMLElement elementWithXMLString: @""] hash], - [[OFXMLElement elementWithXMLString: @""] hash]); - - OTAssertNotEqual( - [[OFXMLElement elementWithXMLString: @""] hash], - [[OFXMLElement elementWithXMLString: @""] hash]); -} - -- (void)testAddAttributeWithNameStringValue -{ - OFXMLElement *element = [OFXMLElement elementWithName: @"foo" - stringValue: @"b&ar"]; - - [element setPrefix: @"objfw-test" forNamespace: @"urn:objfw:test"]; - [element addAttributeWithName: @"foo" - stringValue: @"b&ar"]; - [element addAttributeWithName: @"foo" - namespace: @"urn:objfw:test" - stringValue: @"bar"]; - - OTAssertEqualObjects(element.XMLString, - @"b&ar"); -} - -- (void)testRemoveAttributeForNameNamespace -{ - OFXMLElement *element = [OFXMLElement elementWithName: @"foo" - stringValue: @"b&ar"]; - - [element setPrefix: @"objfw-test" forNamespace: @"urn:objfw:test"]; - [element addAttributeWithName: @"foo" - stringValue: @"b&ar"]; - [element addAttributeWithName: @"foo" - namespace: @"urn:objfw:test" - stringValue: @"bar"]; - - [element removeAttributeForName: @"foo"]; - OTAssertEqualObjects(element.XMLString, - @"b&ar"); - - [element removeAttributeForName: @"foo" namespace: @"urn:objfw:test"]; - OTAssertEqualObjects(element.XMLString, @"b&ar"); -} - -- (void)testAddChild -{ - OFXMLElement *element; - - element = [OFXMLElement elementWithName: @"foo"]; - [element addAttributeWithName: @"foo" stringValue: @"b&ar"]; - [element addChild: [OFXMLElement elementWithName: @"bar"]]; - OTAssertEqualObjects(element.XMLString, - @""); - - element = [OFXMLElement elementWithName: @"foo" - namespace: @"urn:objfw:test"]; - [element setPrefix: @"objfw-test" forNamespace: @"urn:objfw:test"]; - [element addAttributeWithName: @"test" stringValue: @"test"]; - [element addChild: [OFXMLElement elementWithName: @"bar" - namespace: @"urn:objfw:test"]]; - OTAssertEqualObjects(element.XMLString, - @""); -} - -- (void)testElementsForNameNamespace -{ - OFXMLElement *element = [OFXMLElement elementWithName: @"foo"]; - OFXMLElement *bar; - - [element addChild: [OFXMLElement elementWithName: @"foo"]]; - bar = [OFXMLElement elementWithName: @"bar" - namespace: @"urn:objfw:test"]; - [element addChild: bar]; - - OTAssertEqualObjects([element elementsForName: @"bar" - namespace: @"urn:objfw:test"], - [OFArray arrayWithObject: bar]); -} - -- (void)testXMLStringWithIndentation -{ - OTAssertEqualObjects([[OFXMLElement - elementWithXMLString: @"a\nb"] - XMLStringWithIndentation: 2], - @"\n \n a\nb\n \n \n"); -} -@end DELETED new_tests/OFXMLParserTests.m Index: new_tests/OFXMLParserTests.m ================================================================== --- new_tests/OFXMLParserTests.m +++ /dev/null @@ -1,415 +0,0 @@ -/* - * 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" - -#include -#include - -#import "ObjFW.h" -#import "ObjFWTest.h" - -@interface OFXMLParserTests: OTTestCase -{ - int _i; -} -@end - -enum EventType { - eventTypeProcessingInstruction, - eventTypeTagOpen, - eventTypeTagClose, - eventTypeString, - eventTypeCDATA, - eventTypeComment -}; - -@implementation OFXMLParserTests -- (void)parser: (OFXMLParser *)parser - didCreateEvent: (enum EventType)type - name: (OFString *)name - prefix: (OFString *)prefix - namespace: (OFString *)namespace - attributes: (OFArray *)attrs - string: (OFString *)string -{ - switch (_i++) { - case 0: - OTAssertEqual(type, eventTypeProcessingInstruction); - OTAssertEqualObjects(name, @"xml"); - OTAssertEqualObjects(string, @"version='1.0'"); - break; - case 1: - OTAssertEqual(type, eventTypeProcessingInstruction); - OTAssertEqualObjects(name, @"p?i"); - OTAssertNil(string); - break; - case 2: - OTAssertEqual(type, eventTypeTagOpen); - OTAssertEqualObjects(name, @"root"); - OTAssertNil(prefix); - OTAssertNil(namespace); - OTAssertEqual(attrs.count, 0); - break; - case 3: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n\n "); - break; - case 4: - OTAssertEqual(type, eventTypeCDATA); - OTAssertEqualObjects(string, @"f<]]]oo]"); - OTAssertEqual(parser.lineNumber, 3); - break; - case 5: - OTAssertEqual(type, eventTypeTagOpen); - OTAssertEqualObjects(name, @"bar"); - OTAssertNil(prefix); - OTAssertNil(namespace); - OTAssertNil(attrs); - break; - case 6: - OTAssertEqual(type, eventTypeTagClose); - OTAssertEqualObjects(name, @"bar"); - OTAssertNil(prefix); - OTAssertNil(namespace); - OTAssertNil(attrs); - break; - case 7: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n "); - break; - case 8: - OTAssertEqual(type, eventTypeTagOpen); - OTAssertEqualObjects(name, @"foobar"); - OTAssertNil(prefix); - OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); - OTAssertEqualObjects(attrs, [OFArray arrayWithObject: - [OFXMLAttribute attributeWithName: @"xmlns" - stringValue: @"urn:objfw:test:" - @"foobar"]]); - break; - case 9: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n "); - break; - case 10: - OTAssertEqual(type, eventTypeTagOpen); - OTAssertEqualObjects(name, @"qux"); - OTAssertNil(prefix); - OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); - OTAssertEqualObjects(attrs, [OFArray arrayWithObject: - [OFXMLAttribute attributeWithName: @"foo" - namespace: @"http://www.w3.org/" - @"2000/xmlns/" - stringValue: @"urn:objfw:test:foo"]]); - break; - case 11: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n "); - break; - case 12: - OTAssertEqual(type, eventTypeTagOpen); - OTAssertEqualObjects(name, @"bla"); - OTAssertEqualObjects(prefix, @"foo"); - OTAssertEqualObjects(namespace, @"urn:objfw:test:foo"); - OTAssertEqualObjects(attrs, ([OFArray arrayWithObjects: - [OFXMLAttribute attributeWithName: @"bla" - namespace: @"urn:objfw:test:foo" - stringValue: @"bla"], - [OFXMLAttribute attributeWithName: @"blafoo" - stringValue: @"foo"], nil])); - break; - case 13: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n "); - break; - case 14: - OTAssertEqual(type, eventTypeTagOpen); - OTAssertEqualObjects(name, @"blup"); - OTAssertNil(prefix); - OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); - OTAssertEqualObjects(attrs, ([OFArray arrayWithObjects: - [OFXMLAttribute attributeWithName: @"qux" - namespace: @"urn:objfw:test:foo" - stringValue: @"asd"], - [OFXMLAttribute attributeWithName: @"quxqux" - stringValue: @"test"], nil])); - break; - case 15: - OTAssertEqual(type, eventTypeTagClose); - OTAssertEqualObjects(name, @"blup"); - OTAssertNil(prefix); - OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); - break; - case 16: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n "); - break; - case 17: - OTAssertEqual(type, eventTypeTagOpen); - OTAssertEqualObjects(name, @"bla"); - OTAssertEqualObjects(prefix, @"bla"); - OTAssertEqualObjects(namespace, @"urn:objfw:test:bla"); - OTAssertEqualObjects(attrs, ([OFArray arrayWithObjects: - [OFXMLAttribute attributeWithName: @"bla" - namespace: @"http://www.w3.org/" - @"2000/xmlns/" - stringValue: @"urn:objfw:test:bla"], - [OFXMLAttribute attributeWithName: @"qux" - stringValue: @"qux"], - [OFXMLAttribute attributeWithName: @"foo" - namespace: @"urn:objfw:test:bla" - stringValue: @"blafoo"], nil])); - break; - case 18: - OTAssertEqual(type, eventTypeTagClose); - OTAssertEqualObjects(name, @"bla"); - OTAssertEqualObjects(prefix, @"bla"); - OTAssertEqualObjects(namespace, @"urn:objfw:test:bla"); - break; - case 19: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n "); - break; - case 20: - OTAssertEqual(type, eventTypeTagOpen); - OTAssertEqualObjects(name, @"abc"); - OTAssertNil(prefix); - OTAssertEqualObjects(namespace, @"urn:objfw:test:abc"); - OTAssertEqualObjects(attrs, ([OFArray arrayWithObjects: - [OFXMLAttribute attributeWithName: @"xmlns" - stringValue: @"urn:objfw:test:abc"], - [OFXMLAttribute attributeWithName: @"abc" - stringValue: @"abc"], - [OFXMLAttribute attributeWithName: @"abc" - namespace: @"urn:objfw:test:foo" - stringValue: @"abc"], nil])); - break; - case 21: - OTAssertEqual(type, eventTypeTagClose); - OTAssertEqualObjects(name, @"abc"); - OTAssertNil(prefix); - OTAssertEqualObjects(namespace, @"urn:objfw:test:abc"); - break; - case 22: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n "); - break; - case 23: - OTAssertEqual(type, eventTypeTagClose); - OTAssertEqualObjects(name, @"bla"); - OTAssertEqualObjects(prefix, @"foo"); - OTAssertEqualObjects(namespace, @"urn:objfw:test:foo"); - break; - case 24: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n "); - break; - case 25: - OTAssertEqual(type, eventTypeComment); - OTAssertEqualObjects(string, @" commänt "); - break; - case 26: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n "); - break; - case 27: - OTAssertEqual(type, eventTypeTagClose); - OTAssertEqualObjects(name, @"qux"); - OTAssertNil(prefix); - OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); - break; - case 28: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n "); - break; - case 29: - OTAssertEqual(type, eventTypeTagClose); - OTAssertEqualObjects(name, @"foobar"); - OTAssertNil(prefix); - OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); - break; - case 30: - OTAssertEqual(type, eventTypeString); - OTAssertEqualObjects(string, @"\n"); - break; - case 31: - OTAssertEqual(type, eventTypeTagClose); - OTAssertEqualObjects(name, @"root"); - OTAssertNil(prefix); - OTAssertNil(namespace); - break; - } -} - -- (void)parser: (OFXMLParser *)parser - foundProcessingInstructionWithTarget: (OFString *)target - text: (OFString *)text -{ - [self parser: parser - didCreateEvent: eventTypeProcessingInstruction - name: target - prefix: nil - namespace: nil - attributes: nil - string: text]; -} - -- (void)parser: (OFXMLParser *)parser - didStartElement: (OFString *)name - prefix: (OFString *)prefix - namespace: (OFString *)namespace - attributes: (OFArray *)attrs -{ - [self parser: parser - didCreateEvent: eventTypeTagOpen - name: name - prefix: prefix - namespace: namespace - attributes: attrs - string: nil]; -} - -- (void)parser: (OFXMLParser *)parser - didEndElement: (OFString *)name - prefix: (OFString *)prefix - namespace: (OFString *)namespace -{ - [self parser: parser - didCreateEvent: eventTypeTagClose - name: name - prefix: prefix - namespace: namespace - attributes: nil - string: nil]; -} - -- (void)parser: (OFXMLParser *)parser foundCharacters: (OFString *)string -{ - [self parser: parser - didCreateEvent: eventTypeString - name: nil - prefix: nil - namespace: nil - attributes: nil - string: string]; -} - -- (void)parser: (OFXMLParser *)parser foundCDATA: (OFString *)CDATA -{ - [self parser: parser - didCreateEvent: eventTypeCDATA - name: nil - prefix: nil - namespace: nil - attributes: nil - string: CDATA]; -} - -- (void)parser: (OFXMLParser *)parser foundComment: (OFString *)comment -{ - [self parser: parser - didCreateEvent: eventTypeComment - name: nil - prefix: nil - namespace: nil - attributes: nil - string: comment]; -} - -- (OFString *)parser: (OFXMLParser *)parser - foundUnknownEntityNamed: (OFString *)entity -{ - if ([entity isEqual: @"foo"]) - return @"foobar"; - - return nil; -} - -- (void)testParser -{ - static const char *string = "\xEF\xBB\xBF" - "\r\r" - " \n" - " \r\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ""; - OFXMLParser *parser; - size_t j, length; - - parser = [OFXMLParser parser]; - parser.delegate = self; - - /* Simulate a stream where we only get chunks */ - length = strlen(string); - - for (j = 0; j < length; j+= 2) { - if (parser.hasFinishedParsing) - abort(); - - if (j + 2 > length) - [parser parseBuffer: string + j length: 1]; - else - [parser parseBuffer: string + j length: 2]; - } - - OTAssertEqual(_i, 32); - OTAssertEqual(parser.lineNumber, 18); - OTAssertTrue(parser.hasFinishedParsing); - - /* Parsing whitespaces after the document */ - [parser parseString: @" \t\r\n "]; - - /* Parsing comments after the document */ - [parser parseString: @" \t\r\n "]; - - /* Detection of junk after the document */ - OTAssertThrowsSpecific([parser parseString: @"a"], - OFMalformedXMLException); - OTAssertThrowsSpecific([parser parseString: @""], - OFMalformedXMLException); - - parser = [OFXMLParser parser]; - OTAssertThrowsSpecific([parser parseString: @""], - OFMalformedXMLException); -} - -- (void)testDetectionOfInvalidEncoding -{ - OFXMLParser *parser = [OFXMLParser parser]; - - OTAssertThrowsSpecific( - [parser parseString: @""], - OFInvalidEncodingException); -} -@end DELETED new_tests/RuntimeARCTests.m Index: new_tests/RuntimeARCTests.m ================================================================== --- new_tests/RuntimeARCTests.m +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 "ObjFW.h" -#import "ObjFWTest.h" - -@interface RuntimeARCTests: OTTestCase -@end - -@interface RuntimeARCTestClass: OFObject -@end - -@implementation RuntimeARCTests -- (void)testExceptionsDuringInit -{ - OTAssertThrows((void)[[RuntimeARCTestClass alloc] init]); -} - -- (void)testWeakReferences -{ - id object = [[OFObject alloc] init]; - __weak id weak = object; - - OTAssertEqual(weak, object); - - object = nil; - OTAssertNil(weak); -} -@end - -@implementation RuntimeARCTestClass -- (instancetype)init -{ - self = [super init]; - -#if defined(OF_WINDOWS) && defined(OF_AMD64) - /* - * Clang has a bug on Windows where it creates an invalid call into - * objc_retainAutoreleasedReturnValue(). Work around it by not using an - * autoreleased exception. - */ - @throw [[OFException alloc] init]; -#else - @throw [OFException exception]; -#endif - - return self; -} -@end DELETED new_tests/RuntimeTests.m Index: new_tests/RuntimeTests.m ================================================================== --- new_tests/RuntimeTests.m +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 "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 DELETED new_tests/plugin/Info.plist.in Index: new_tests/plugin/Info.plist.in ================================================================== --- new_tests/plugin/Info.plist.in +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleExecutable - TestPlugin - CFBundleName - TestPlugin - CFBundleIdentifier - im.nil.objfw.tests.plugin - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - BNDL - CFBundleVersion - @BUNDLE_VERSION@ - CFBundleShortVersionString - @BUNDLE_SHORT_VERSION@ - MinimumOSVersion - 9.0 - - DELETED new_tests/plugin/Makefile Index: new_tests/plugin/Makefile ================================================================== --- new_tests/plugin/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -DISTCLEAN = Info.plist - -PLUGIN_NOINST = TestPlugin${PLUGIN_SUFFIX} -SRCS = TestPlugin.m - -include ../../buildsys.mk -include ../../extra.mk - -CPPFLAGS += -I../.. -I../../src -I../../src/runtime -LIBS := ${TESTPLUGIN_LIBS} ${LIBS} -LD = ${OBJC} DELETED new_tests/plugin/TestPlugin.h Index: new_tests/plugin/TestPlugin.h ================================================================== --- new_tests/plugin/TestPlugin.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 "OFObject.h" - -@interface TestPlugin: OFObject -- (int)test: (int)num; -@end DELETED new_tests/plugin/TestPlugin.m Index: new_tests/plugin/TestPlugin.m ================================================================== --- new_tests/plugin/TestPlugin.m +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 "TestPlugin.h" - -#ifdef OF_OBJFW_RUNTIME -# import "runtime/private.h" - -OF_DESTRUCTOR() -{ - Class class = objc_getClass("TestPlugin"); - - if (class == Nil) - /* - * musl has broken dlclose(): Instead of calling the destructor - * on dlclose(), they call it on exit(). This of course means - * that our tests might have already called objc_deinit() and - * the class is already gone. - */ - return; - - objc_unregisterClass(class); -} -#endif - -@implementation TestPlugin -- (int)test: (int)num -{ - return num * 2; -} -@end - -Class -class(void) -{ - return [TestPlugin class]; -} DELETED new_tests/subprocess/Makefile Index: new_tests/subprocess/Makefile ================================================================== --- new_tests/subprocess/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -PROG_NOINST = subprocess${PROG_SUFFIX} -SRCS = Subprocess.m - -include ../../buildsys.mk -include ../../extra.mk - -CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../.. -LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} -LD = ${OBJC} DELETED new_tests/subprocess/Subprocess.m Index: new_tests/subprocess/Subprocess.m ================================================================== --- new_tests/subprocess/Subprocess.m +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 "ObjFW.h" - -@interface Subprocess: OFObject -@end - -OF_APPLICATION_DELEGATE(Subprocess) - -@implementation Subprocess -- (void)applicationDidFinishLaunching: (OFNotification *)notification -{ - OFString *line; - - if (![[OFApplication arguments] isEqual: - [OFArray arrayWithObjects: @"tést", @"123", nil]]) - [OFApplication terminateWithStatus: 1]; - - if (![[[OFApplication environment] objectForKey: @"tëst"] - isEqual: @"yés"]) - [OFApplication terminateWithStatus: 2]; - - while ((line = [OFStdIn readLine]) != nil) - [OFStdOut writeLine: line.uppercaseString]; - - [OFApplication terminate]; -} -@end DELETED new_tests/testfile.bin Index: new_tests/testfile.bin ================================================================== --- new_tests/testfile.bin +++ /dev/null cannot compute difference between binary files DELETED new_tests/testfile.ini Index: new_tests/testfile.ini ================================================================== --- new_tests/testfile.ini +++ /dev/null @@ -1,21 +0,0 @@ -[tests] -foo = bar -foobar=baz -;comment - -[foobar] -;foobarcomment -qux=" asd" -"quxqux " = asd -quxquxqux="hello\"wrld" -qux2="a\f" - -[types] -integer = 0x20 -bool = true -float = 0.5 -array1 = 1 -array2 = 1 -double = 0.25 -array1 = 2 -array2 = 2 DELETED new_tests/testfile.txt Index: new_tests/testfile.txt ================================================================== --- new_tests/testfile.txt +++ /dev/null @@ -1,1 +0,0 @@ -test ADDED tests/ForwardingTests.m Index: tests/ForwardingTests.m ================================================================== --- /dev/null +++ tests/ForwardingTests.m @@ -0,0 +1,317 @@ +/* + * 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" + +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +#define FORMAT @"%@ %@ %@ %@ %@ %@ %@ %@ %@ %g %g %g %g %g %g %g %g %g" +#define ARGS @"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", \ + 1.5, 2.25, 3.125, 4.0625, 5.03125, 6.5, 7.25, 8.0, 9.0 +#define RESULT @"a b c d e f g h i 1.5 2.25 3.125 4.0625 5.03125 6.5 7.25 8 9" + +@interface ForwardingTests: OTTestCase +@end + +static size_t forwardingsCount = 0; +static bool success = false; +static id target = nil; + +struct StretTest { + char buffer[1024]; +}; + +@interface ForwardingTestObject: OFObject +@end + +@interface ForwardingTestObject (NonExistentMethods) ++ (void)test; +- (void)test; +- (uint32_t)forwardingTargetTest: (intptr_t)a0 + : (intptr_t)a1 + : (double)a2 + : (double)a3; +- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)format, ...; +- (long double)forwardingTargetFPRetTest; +- (struct StretTest)forwardingTargetStRetTest; +- (void)forwardingTargetNilTest; +- (void)forwardingTargetSelfTest; +- (struct StretTest)forwardingTargetNilStRetTest; +- (struct StretTest)forwardingTargetSelfStRetTest; +@end + +@interface ForwardingTarget: OFObject +@end + +static void +test(id self, SEL _cmd) +{ + success = true; +} + +@implementation ForwardingTests +- (void)setUp +{ + [super setUp]; + + forwardingsCount = 0; + success = false; + target = nil; +} + +- (void)testForwardingMessageAndAddingClassMethod +{ + [ForwardingTestObject test]; + OTAssertTrue(success); + OTAssertEqual(forwardingsCount, 1); + + [ForwardingTestObject test]; + OTAssertEqual(forwardingsCount, 1); +} + +- (void)forwardingMessageAndAddingInstanceMethod +{ + ForwardingTestObject *testObject = + [[[ForwardingTestObject alloc] init] autorelease]; + + [testObject test]; + OTAssertTrue(success); + OTAssertEqual(forwardingsCount, 1); + + [testObject test]; + OTAssertEqual(forwardingsCount, 1); +} + +#ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR +- (void)testForwardingTargetForSelector +{ + ForwardingTestObject *testObject = + [[[ForwardingTestObject alloc] init] autorelease]; + + target = [[[ForwardingTarget alloc] init] autorelease]; + + OTAssertEqual( + [testObject forwardingTargetTest: 0xDEADBEEF + : -1 + : 1.25 + : 2.75], 0x12345678); +} + +- (void)testForwardingTargetForSelectorWithVariableArguments +{ + ForwardingTestObject *testObject = + [[[ForwardingTestObject alloc] init] autorelease]; + + target = [[[ForwardingTarget alloc] init] autorelease]; + + OTAssertEqualObjects( + ([testObject forwardingTargetVarArgTest: FORMAT, ARGS]), RESULT); +} + +/* + * Don't try fpret on Win64 if we don't have stret forwarding, as long double + * is handled as a struct there. + */ +# if !defined(OF_WINDOWS) || !defined(OF_AMD64) || \ + defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET) +- (void)testForwardingTargetForSelectorFPRet +{ + ForwardingTestObject *testObject = + [[[ForwardingTestObject alloc] init] autorelease]; + + target = [[[ForwardingTarget alloc] init] autorelease]; + + OTAssertEqual([testObject forwardingTargetFPRetTest], + 12345678.00006103515625); +} +# endif + +# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET +- (void)testForwardingTargetForSelectorStRet +{ + ForwardingTestObject *testObject = + [[[ForwardingTestObject alloc] init] autorelease]; + + target = [[[ForwardingTarget alloc] init] autorelease]; + + OTAssertEqual(memcmp([testObject forwardingTargetStRetTest].buffer, + "abcdefghijklmnopqrstuvwxyz", 27), 0); +} +# endif + +- (void)testForwardingTargetForSelectorReturningNilThrows +{ + ForwardingTestObject *testObject = + [[[ForwardingTestObject alloc] init] autorelease]; + + target = [[[ForwardingTarget alloc] init] autorelease]; + + OTAssertThrowsSpecific([testObject forwardingTargetNilTest], + OFNotImplementedException); +} + +- (void)testForwardingTargetForSelectorReturningSelfThrows +{ + ForwardingTestObject *testObject = + [[[ForwardingTestObject alloc] init] autorelease]; + + target = [[[ForwardingTarget alloc] init] autorelease]; + + OTAssertThrowsSpecific([testObject forwardingTargetSelfTest], + OFNotImplementedException); +} + +# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET +- (void)testForwardingTargetForSelectorStRetReturningNilThrows +{ + ForwardingTestObject *testObject = + [[[ForwardingTestObject alloc] init] autorelease]; + + target = [[[ForwardingTarget alloc] init] autorelease]; + + OTAssertThrowsSpecific([testObject forwardingTargetNilStRetTest], + OFNotImplementedException); +} + +- (void)testForwardingTargetForSelectorStRetReturningSelfThrows +{ + ForwardingTestObject *testObject = + [[[ForwardingTestObject alloc] init] autorelease]; + + target = [[[ForwardingTarget alloc] init] autorelease]; + + OTAssertThrowsSpecific([testObject forwardingTargetSelfStRetTest], + OFNotImplementedException); +} +# endif +#endif +@end + +@implementation ForwardingTestObject ++ (bool)resolveClassMethod: (SEL)selector +{ + forwardingsCount++; + + if (sel_isEqual(selector, @selector(test))) { + class_replaceMethod(object_getClass(self), @selector(test), + (IMP)test, "v#:"); + return YES; + } + + return NO; +} + ++ (bool)resolveInstanceMethod: (SEL)selector +{ + forwardingsCount++; + + if (sel_isEqual(selector, @selector(test))) { + class_replaceMethod(self, @selector(test), (IMP)test, "v@:"); + return YES; + } + + return NO; +} + +- (id)forwardingTargetForSelector: (SEL)selector +{ + /* + * Do some useless calculations in as many registers as possible to + * check if the arguments are properly saved and restored. + */ + volatile register intptr_t r0 = 0, r1 = 1, r2 = 2, r3 = 3, r4 = 4, + r5 = 5, r6 = 6, r7 = 7, r8 = 8, r9 = 9, r10 = 10, r11 = 11; + volatile register double f0 = 0.5, f1 = 1.5, f2 = 2.5, f3 = 3.5, + f4 = 4.5, f5 = 5.5, f6 = 6.5, f7 = 7.5, f8 = 8.5, f9 = 9.5, + f10 = 10.5, f11 = 11.5; + double add = r0 * r1 * r2 * r3 * r4 * r5 * r6 * r7 * r8 * r9 * r10 * + r11 * f0 * f1 * f2 * f3 * f4 * f5 * f6 * f7 * f8 * f9 * f10 * f11; + + if (sel_isEqual(selector, @selector(forwardingTargetTest::::)) || + sel_isEqual(selector, @selector(forwardingTargetVarArgTest:)) || + sel_isEqual(selector, @selector(forwardingTargetFPRetTest)) || + sel_isEqual(selector, @selector(forwardingTargetStRetTest))) + return (id)((char *)target + (ptrdiff_t)add); + + if (sel_isEqual(selector, @selector(forwardingTargetNilTest)) || + sel_isEqual(selector, @selector(forwardingTargetNilStRetTest))) + return nil; + + if (sel_isEqual(selector, @selector(forwardingTargetSelfTest)) || + sel_isEqual(selector, @selector(forwardingTargetSelfStRetTest))) + return self; + + abort(); + + OF_UNREACHABLE +} +@end + +@implementation ForwardingTarget +- (uint32_t)forwardingTargetTest: (intptr_t)a0 + : (intptr_t)a1 + : (double)a2 + : (double)a3 +{ + OFEnsure(self == target); + + if (a0 != (intptr_t)0xDEADBEEF) + return 0; + if (a1 != -1) + return 0; + if (a2 != 1.25) + return 0; + if (a3 != 2.75) + return 0; + + return 0x12345678; +} + +- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)format, ... +{ + va_list args; + OFString *ret; + + OFEnsure(self == target); + + va_start(args, format); + ret = [[[OFString alloc] initWithFormat: format + arguments: args] autorelease]; + va_end(args); + + return ret; +} + +- (long double)forwardingTargetFPRetTest +{ + OFEnsure(self == target); + + return 12345678.00006103515625; +} + +- (struct StretTest)forwardingTargetStRetTest +{ + struct StretTest ret = { { 0 } }; + + OFEnsure(self == target); + + memcpy(ret.buffer, "abcdefghijklmnopqrstuvwxyz", 27); + + return ret; +} +@end ADDED tests/Makefile Index: tests/Makefile ================================================================== --- /dev/null +++ tests/Makefile @@ -0,0 +1,232 @@ +include ../extra.mk + +SUBDIRS = ${TESTPLUGIN} ${SUBPROCESS} ${OBJC_SYNC} terminal + +CLEAN = EBOOT.PBP \ + boot.dol \ + ${PROG_NOINST}.arm9 \ + ${PROG_NOINST}.nds \ + ${PROG_NOINST}.nro \ + ${PROG_NOINST}.rpx \ + testfile_bin.m \ + testfile_ini.m +DISTCLEAN = Info.plist + +PROG_NOINST = tests${PROG_SUFFIX} +STATIC_LIB_NOINST = ${TESTS_STATIC_LIB} +SRCS = ${OF_BLOCK_TESTS_M} \ + ForwardingTests.m \ + OFArrayTests.m \ + OFCharacterSetTests.m \ + OFColorTests.m \ + OFConcreteArrayTests.m \ + OFConcreteDictionaryTests.m \ + OFConcreteMutableArrayTests.m \ + OFConcreteMutableDictionaryTests.m \ + OFConcreteMutableSetTests.m \ + OFConcreteSetTests.m \ + OFCryptographicHashTests.m \ + OFDataTests.m \ + OFDateTests.m \ + OFDictionaryTests.m \ + OFHMACTests.m \ + OFINIFileTests.m \ + OFIRITests.m \ + OFInvocationTests.m \ + OFJSONTests.m \ + OFListTests.m \ + OFLocaleTests.m \ + OFMatrix4x4Tests.m \ + OFMemoryStreamTests.m \ + OFMethodSignatureTests.m \ + OFMutableArrayTests.m \ + OFMutableDataTests.m \ + OFMutableDictionaryTests.m \ + OFMutableSetTests.m \ + OFMutableStringTests.m \ + OFMutableUTF8StringTests.m \ + OFNotificationCenterTests.m \ + OFNumberTests.m \ + OFObjectTests.m \ + OFPBKDF2Tests.m \ + OFPropertyListTests.m \ + OFScryptTests.m \ + OFSetTests.m \ + OFStreamTests.m \ + OFStringTests.m \ + OFSystemInfoTests.m \ + OFUTF8StringTests.m \ + OFValueTests.m \ + OFXMLElementBuilderTests.m \ + OFXMLNodeTests.m \ + OFXMLParserTests.m \ + ${RUNTIME_ARC_TESTS_M} \ + RuntimeTests.m \ + ${USE_SRCS_PLUGINS} \ + ${USE_SRCS_SOCKETS} \ + ${USE_SRCS_SUBPROCESSES} \ + ${USE_SRCS_THREADS} \ + ${USE_SRCS_WINDOWS} \ + testfile_bin.m \ + testfile_ini.m +SRCS_PLUGINS = OFPluginTests.m +SRCS_SOCKETS = OFDNSResolverTests.m \ + ${OF_HTTP_CLIENT_TESTS_M} \ + OFHTTPCookieManagerTests.m \ + OFHTTPCookieTests.m \ + OFKernelEventObserverTests.m \ + OFSocketTests.m \ + OFTCPSocketTests.m \ + OFUDPSocketTests.m \ + ${USE_SRCS_IPX} \ + ${USE_SRCS_UNIX_SOCKETS} \ + ${USE_SRCS_APPLETALK} +SRCS_APPLETALK = OFDDPSocketTests.m +SRCS_IPX = OFIPXSocketTests.m \ + OFSPXSocketTests.m \ + OFSPXStreamSocketTests.m +SRCS_UNIX_SOCKETS = OFUNIXDatagramSocketTests.m \ + OFUNIXStreamSocketTests.m +SRCS_SUBPROCESSES = OFSubprocessTests.m +SRCS_THREADS = OFThreadTests.m +SRCS_WINDOWS = OFWindowsRegistryKeyTests.m + +include ../buildsys.mk + +testfile_bin.m: testfile.bin + ${SHELL} ../utils/objfw-embed testfile.bin testfile.bin $@ +testfile_ini.m: testfile.ini + ${SHELL} ../utils/objfw-embed testfile.ini testfile.ini $@ + +.PHONY: run run-on-ios run-on-android +run: + rm -f libobjfw.so.${OBJFW_LIB_MAJOR} + rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} + rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib + rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} + rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll + rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib + if test -f ../src/libobjfw.so; then \ + ${LN_S} ../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ + ${LN_S} ../src/libobjfw.so \ + libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ + elif test -f ../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ + ${LN_S} ../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \ + libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ + fi + if test -f ../src/objfw${OBJFW_LIB_MAJOR}.dll; then \ + ${LN_S} ../src/objfw${OBJFW_LIB_MAJOR}.dll \ + objfw${OBJFW_LIB_MAJOR}.dll; \ + fi + if test -f ../src/libobjfw.dylib; then \ + ${LN_S} ../src/libobjfw.dylib \ + libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ + fi + if test -f ../src/runtime/libobjfwrt.so; then \ + ${LN_S} ../src/runtime/libobjfwrt.so \ + libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ + ${LN_S} ../src/runtime/libobjfwrt.so \ + libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ + elif test -f ../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; then \ + ${LN_S} ../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ + fi + if test -f ../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll; then \ + ${LN_S} ../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll \ + objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ + fi + if test -f ../src/runtime/libobjfwrt.dylib; then \ + ${LN_S} ../src/runtime/libobjfwrt.dylib \ + libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ + fi + LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \ + DYLD_FRAMEWORK_PATH=../src:../src/runtime$${DYLD_FRAMEWORK_PATH+:}$$DYLD_FRAMEWORK_PATH \ + DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ + LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ + ASAN_OPTIONS=allocator_may_return_null=1 \ + ${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \ + rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \ + rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ + rm -f objfw${OBJFW_LIB_MAJOR}.dll; \ + rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ + rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ + rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ + rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ + rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ + exit $$EXIT + +run-on-android: all + echo "Uploading files to Android device..." + if test -f ../src/libobjfw.so; then \ + adb push ../src/libobjfw.so \ + /data/local/tmp/objfw/libobjfw.so.${OBJFW_LIB_MAJOR}; \ + fi + if test -f ../src/runtime/libobjfwrt.so; then \ + adb push ../src/runtime/libobjfwrt.so \ + /data/local/tmp/objfw/libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ + fi + adb push tests /data/local/tmp/objfw/tests + adb push testfile.txt /data/local/tmp/objfw/testfile.txt + if test -f plugin/TestPlugin.so; then \ + adb push plugin/TestPlugin.so \ + /data/local/tmp/objfw/plugin/TestPlugin.so; \ + fi + echo "Running tests binary on Android device..." + adb shell 'cd /data/local/tmp/objfw && LD_LIBRARY_PATH=. exec ${WRAPPER} ./tests' + +EBOOT.PBP: ${PROG_NOINST} + psp-fixup-imports ${PROG_NOINST} + mksfo "ObjFW Tests" PARAM.SFO + psp-strip ${PROG_NOINST} + pack-pbp $@ PARAM.SFO NULL NULL NULL NULL NULL ${PROG_NOINST} NULL + +boot.dol: ${PROG_NOINST} + elf2dol ${PROG_NOINST} $@ + +${PROG_NOINST}: ${LIBOBJFW_DEP} ${LIBOBJFWRT_DEP} ../src/test/libobjfwtest.a + +${PROG_NOINST}.3dsx: ${PROG_NOINST} + 3dsxtool $< $@ + +${PROG_NOINST}.arm9: ${PROG_NOINST} + arm-none-eabi-objcopy -O binary $< $@ + +${PROG_NOINST}.nds: ${PROG_NOINST}.arm9 testfile.txt + rm -fr nds-data + mkdir -p nds-data + cp testfile.txt nds-data + ndstool -c $@ -9 ${PROG_NOINST} -d nds-data + rm -fr nds-data + +${PROG_NOINST}.nro: ${PROG_NOINST} testfile.txt + rm -fr romfs + mkdir -p romfs + cp testfile.txt romfs + nacptool --create "ObjFW tests" "Jonathan Schleifer" \ + "${PACKAGE_VERSION}" tests.nacp + elf2nro ${PROG_NOINST} $@ --nacp=tests.nacp --romfsdir=romfs + rm -fr romfs tests.nacp + +${PROG_NOINST}.rpx: ${PROG_NOINST} + elf2rpl $< $@ + +CPPFLAGS += -I../src \ + -I../src/exceptions \ + -I../src/runtime \ + -I../src/test \ + -I.. \ + -DOBJFWTEST_LOCAL_INCLUDES \ + -DPROG_SUFFIX=\"${PROG_SUFFIX}\" +OBJCFLAGS_RuntimeARCTests.m = -fobjc-arc -fobjc-arc-exceptions +# Repetition is required for Wii U, as otherwise it cannot find main. Just +# moving -lobjfwtest later doesn't work either, as then the linker cannot find +# ObjFW symbols. So the only solution is to list everything twice. +LIBS := -L../src/test \ + -lobjfwtest \ + ${TESTS_LIBS} \ + ${LIBS} \ + -lobjfwtest \ + ${TESTS_LIBS} \ + ${LIBS} +LDFLAGS += ${MAP_LDFLAGS} +LD = ${OBJC} ADDED tests/OFArrayTests.h Index: tests/OFArrayTests.h ================================================================== --- /dev/null +++ tests/OFArrayTests.h @@ -0,0 +1,25 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFArrayTests: OTTestCase +{ + OFArray *_array; +} + +@property (readonly, nonatomic) Class arrayClass; +@end ADDED tests/OFArrayTests.m Index: tests/OFArrayTests.m ================================================================== --- /dev/null +++ tests/OFArrayTests.m @@ -0,0 +1,313 @@ +/* + * 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 "OFArrayTests.h" + +@interface CustomArray: OFArray +{ + OFArray *_array; +} +@end + +static OFString *const cArray[] = { + @"Foo", + @"Bar", + @"Baz" +}; + +@implementation OFArrayTests +- (Class)arrayClass +{ + return [CustomArray class]; +} + +- (void)setUp +{ + [super setUp]; + + _array = [[self.arrayClass alloc] + initWithObjects: cArray + count: sizeof(cArray) / sizeof(*cArray)]; +} + +- (void)dealloc +{ + [_array release]; + + [super dealloc]; +} + +- (void)testArray +{ + OFArray *array = [self.arrayClass array]; + + OTAssertNotNil(array); + OTAssertEqual(array.count, 0); +} + +- (void)testArrayWithObjects +{ + OFArray *array = [self.arrayClass arrayWithObjects: + @"Foo", @"Bar", @"Baz", nil]; + + OTAssertNotNil(array); + OTAssertEqual(array.count, 3); + OTAssertEqualObjects([array objectAtIndex: 0], @"Foo"); + OTAssertEqualObjects([array objectAtIndex: 1], @"Bar"); + OTAssertEqualObjects([array objectAtIndex: 2], @"Baz"); +} + +- (void)testArrayWithObjectsCount +{ + OFArray *array1 = [self.arrayClass arrayWithObjects: + @"Foo", @"Bar", @"Baz", nil]; + OFArray *array2 = [self.arrayClass arrayWithObjects: cArray count: 3]; + + OTAssertEqualObjects(array1, array2); +} + +- (void)testDescription +{ + OTAssertEqualObjects(_array.description, + @"(\n\tFoo,\n\tBar,\n\tBaz\n)"); +} + +- (void)testCount +{ + OTAssertEqual(_array.count, 3); +} + +- (void)testIsEqual +{ + OFArray *array = [self.arrayClass arrayWithObjects: cArray count: 3]; + + OTAssertEqualObjects(array, _array); + OTAssertNotEqual(array, _array); +} + +- (void)testObjectAtIndex +{ + OTAssertEqualObjects([_array objectAtIndex: 0], cArray[0]); + OTAssertEqualObjects([_array objectAtIndex: 1], cArray[1]); + OTAssertEqualObjects([_array objectAtIndex: 2], cArray[2]); +} + +- (void)testObjectAtIndexFailsWhenOutOfRange +{ + OTAssertThrowsSpecific([_array objectAtIndex: _array.count], + OFOutOfRangeException); +} + +- (void)testContainsObject +{ + OTAssertTrue([_array containsObject: cArray[1]]); + OTAssertFalse([_array containsObject: @"nonexistent"]); +} + +- (void)testContainsObjectIdenticalTo +{ + OTAssertTrue([_array containsObjectIdenticalTo: cArray[1]]); + OTAssertFalse([_array containsObjectIdenticalTo: + [OFString stringWithString: cArray[1]]]); +} + +- (void)testIndexOfObject +{ + OTAssertEqual([_array indexOfObject: cArray[1]], 1); + OTAssertEqual([_array indexOfObject: @"nonexistent"], OFNotFound); +} + +- (void)testIndexOfObjectIdenticalTo +{ + OTAssertEqual([_array indexOfObjectIdenticalTo: cArray[1]], 1); + OTAssertEqual([_array indexOfObjectIdenticalTo: + [OFString stringWithString: cArray[1]]], + OFNotFound); +} + +- (void)objectsInRange +{ + OTAssertEqualObjects([_array objectsInRange: OFMakeRange(1, 2)], + ([self.arrayClass arrayWithObjects: cArray[1], cArray[2], nil])); +} + +- (void)testEnumerator +{ + OFEnumerator *enumerator = [_array objectEnumerator]; + + OTAssertEqualObjects([enumerator nextObject], cArray[0]); + OTAssertEqualObjects([enumerator nextObject], cArray[1]); + OTAssertEqualObjects([enumerator nextObject], cArray[2]); + OTAssertNil([enumerator nextObject]); +} + +- (void)testFastEnumeration +{ + size_t i = 0; + + for (OFString *object in _array) { + OTAssertLessThan(i, 3); + OTAssertEqualObjects(object, cArray[i++]); + } +} + +- (void)testComponentsJoinedByString +{ + OFArray *array; + + array = [self.arrayClass arrayWithObjects: @"", @"a", @"b", @"c", nil]; + OTAssertEqualObjects([array componentsJoinedByString: @" "], + @" a b c"); + + array = [self.arrayClass arrayWithObject: @"foo"]; + OTAssertEqualObjects([array componentsJoinedByString: @" "], @"foo"); +} + +- (void)testComponentsJoinedByStringOptions +{ + OFArray *array; + + array = [self.arrayClass + arrayWithObjects: @"", @"foo", @"", @"", @"bar", @"", nil]; + OTAssertEqualObjects( + [array componentsJoinedByString: @" " + options: OFArraySkipEmptyComponents], + @"foo bar"); +} + +- (void)testSortedArray +{ + OFArray *array = [_array arrayByAddingObjectsFromArray: + [OFArray arrayWithObjects: @"0", @"z", nil]]; + + OTAssertEqualObjects([array sortedArray], + ([OFArray arrayWithObjects: @"0", @"Bar", @"Baz", @"Foo", @"z", + nil])); + + OTAssertEqualObjects( + [array sortedArrayUsingSelector: @selector(compare:) + options: OFArraySortDescending], + ([OFArray arrayWithObjects: @"z", @"Foo", @"Baz", @"Bar", @"0", + nil])); +} + +- (void)testReversedArray +{ + OTAssertEqualObjects(_array.reversedArray, + ([OFArray arrayWithObjects: cArray[2], cArray[1], cArray[0], nil])); +} + +#ifdef OF_HAVE_BLOCKS +- (void)testEnumerateObjectsUsingBlock +{ + __block size_t i = 0; + + [_array enumerateObjectsUsingBlock: + ^ (id object, size_t idx, bool *stop) { + OTAssertEqualObjects(object, [_array objectAtIndex: i++]); + }]; + + OTAssertEqual(i, _array.count); +} + +- (void)testMappedArrayUsingBlock +{ + OTAssertEqualObjects( + [_array mappedArrayUsingBlock: ^ id (id object, size_t idx) { + switch (idx) { + case 0: + return @"foobar"; + case 1: + return @"qux"; + } + + return @""; + }].description, + @"(\n\tfoobar,\n\tqux,\n\t\n)"); +} + +- (void)testFilteredArrayUsingBlock +{ + OTAssertEqualObjects( + [_array filteredArrayUsingBlock: ^ bool (id object, size_t idx) { + return [object isEqual: @"Foo"]; + }].description, + @"(\n\tFoo\n)"); + +} + +- (void)testFoldUsingBlock +{ + OTAssertEqualObjects( + [([self.arrayClass arrayWithObjects: [OFMutableString string], + @"foo", @"bar", @"baz", nil]) + foldUsingBlock: ^ id (id left, id right) { + [left appendString: right]; + return left; + }], + @"foobarbaz"); +} +#endif + +- (void)testValueForKey +{ + OTAssertEqualObjects( + [([self.arrayClass arrayWithObjects: @"foo", @"bar", @"quxqux", + nil]) valueForKey: @"length"], + ([self.arrayClass arrayWithObjects: [OFNumber numberWithInt: 3], + [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil])); + + OTAssertEqualObjects( + [([self.arrayClass arrayWithObjects: @"1", @"2", nil]) + valueForKey: @"@count"], + [OFNumber numberWithInt: 2]); +} +@end + +@implementation CustomArray +- (instancetype)initWithObjects: (id const *)objects count: (size_t)count +{ + self = [super init]; + + @try { + _array = [[OFArray alloc] initWithObjects: objects + count: count]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_array release]; + + [super dealloc]; +} + +- (id)objectAtIndex: (size_t)idx +{ + return [_array objectAtIndex: idx]; +} + +- (size_t)count +{ + return [_array count]; +} +@end ADDED tests/OFBlockTests.m Index: tests/OFBlockTests.m ================================================================== --- /dev/null +++ tests/OFBlockTests.m @@ -0,0 +1,138 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFBlockTests: OTTestCase +@end + +#if defined(OF_OBJFW_RUNTIME) +extern struct objc_class _NSConcreteStackBlock; +extern struct objc_class _NSConcreteGlobalBlock; +extern struct objc_class _NSConcreteMallocBlock; +#elif defined(OF_APPLE_RUNTIME) +extern void *_NSConcreteStackBlock; +extern void *_NSConcreteGlobalBlock; +extern void *_NSConcreteMallocBlock; +#endif + +/* Clang on Win32 generates broken code that crashes for global blocks. */ +#if !defined(OF_WINDOWS) || !defined(__clang__) +static void (^globalBlock)(void) = ^ {}; +#endif + +static int +(^returnStackBlock(void))(void) +{ + __block int i = 42; + + return [Block_copy(^ int { return ++i; }) autorelease]; +} + +static double +forwardTest(void) +{ + __block double d; + void (^block)(void) = Block_copy(^ { + d = 5; + }); + + block(); + Block_release(block); + + return d; +} + +@implementation OFBlockTests +- (void)testClassOfStackBlock +{ + __block int x; + void (^stackBlock)(void) = ^ { + x = 0; + (void)x; + }; + + OTAssertEqual((Class)&_NSConcreteStackBlock, + objc_getClass("OFStackBlock")); + OTAssertTrue([stackBlock isKindOfClass: [OFBlock class]]); +} + +#if !defined(OF_WINDOWS) || !defined(__clang__) +- (void)testClassOfGlobalBlock +{ + OTAssertEqual((Class)&_NSConcreteGlobalBlock, + objc_getClass("OFGlobalBlock")); + OTAssertTrue([globalBlock isKindOfClass: [OFBlock class]]); +} +#endif + +- (void)testClassOfMallocBlock +{ + OTAssertEqual((Class)&_NSConcreteMallocBlock, + objc_getClass("OFMallocBlock")); +} + +- (void)testCopyStackBlock +{ + __block int x; + void (^stackBlock)(void) = ^ { + x = 0; + (void)x; + }; + void (^mallocBlock)(void); + + mallocBlock = [[stackBlock copy] autorelease]; + OTAssertEqual([mallocBlock class], objc_getClass("OFMallocBlock")); + OTAssertTrue([mallocBlock isKindOfClass: [OFBlock class]]); +} + +- (void)testCopyStackBlockAndReferenceVariable +{ + OTAssertEqual(forwardTest(), 5); +} + +- (void)testCopyStackBlockAndReferenceCopiedVariable +{ + int (^voidBlock)(void) = returnStackBlock(); + + OTAssertEqual(voidBlock(), 43); + OTAssertEqual(voidBlock(), 44); + OTAssertEqual(voidBlock(), 45); +} + +#if !defined(OF_WINDOWS) || !defined(__clang__) +- (void)testCopyGlobalBlock +{ + OTAssertEqual([[globalBlock copy] autorelease], (id)globalBlock); +} +#endif + +- (void)testCopyMallocBlock +{ + __block int x; + void (^stackBlock)(void) = ^ { + x = 0; + (void)x; + }; + void (^mallocBlock)(void); + + mallocBlock = [[stackBlock copy] autorelease]; + OTAssertEqual([[mallocBlock copy] autorelease], (id)mallocBlock); + OTAssertEqual([mallocBlock retainCount], 2); +} +@end ADDED tests/OFCharacterSetTests.m Index: tests/OFCharacterSetTests.m ================================================================== --- /dev/null +++ tests/OFCharacterSetTests.m @@ -0,0 +1,100 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +#import "OFCharacterSet.h" +#import "OFBitSetCharacterSet.h" +#import "OFRangeCharacterSet.h" + +@interface OFCharacterSetTests: OTTestCase +@end + +@interface CustomCharacterSet: OFCharacterSet +@end + +@implementation CustomCharacterSet +- (bool)characterIsMember: (OFUnichar)character +{ + return (character % 2 == 0); +} +@end + +@implementation OFCharacterSetTests +- (void)testCustomCharacterSet +{ + OFCharacterSet *characterSet = + [[[CustomCharacterSet alloc] init] autorelease]; + + for (OFUnichar c = 0; c < 65536; c++) + if (c % 2 == 0) + OTAssertTrue([characterSet characterIsMember: c]); + else + OTAssertFalse([characterSet characterIsMember: c]); +} + +- (void)testBitSetCharacterSet +{ + OFCharacterSet *characterSet = + [OFCharacterSet characterSetWithCharactersInString: @"0123456789"]; + + OTAssertTrue( + [characterSet isKindOfClass: [OFBitSetCharacterSet class]]); + + for (OFUnichar c = 0; c < 65536; c++) + if (c >= '0' && c <= '9') + OTAssertTrue([characterSet characterIsMember: c]); + else if ([characterSet characterIsMember: c]) + OTAssertFalse([characterSet characterIsMember: c]); +} + +- (void)testRangeCharacterSet +{ + OFCharacterSet *characterSet = + [OFCharacterSet characterSetWithRange: OFMakeRange('0', 10)]; + + OTAssertTrue( + [characterSet isKindOfClass: [OFRangeCharacterSet class]]); + + for (OFUnichar c = 0; c < 65536; c++) + if (c >= '0' && c <= '9') + OTAssertTrue([characterSet characterIsMember: c]); + else + OTAssertFalse([characterSet characterIsMember: c]); +} + +- (void)testInvertedCharacterSet +{ + OFCharacterSet *characterSet = [[OFCharacterSet + characterSetWithRange: OFMakeRange('0', 10)] invertedSet]; + + for (OFUnichar c = 0; c < 65536; c++) + if (c >= '0' && c <= '9') + OTAssertFalse([characterSet characterIsMember: c]); + else + OTAssertTrue([characterSet characterIsMember: c]); +} + +- (void)testInvertingInvertedSetReturnsOriginal +{ + OFCharacterSet *characterSet = + [OFCharacterSet characterSetWithRange: OFMakeRange('0', 10)]; + + OTAssertEqual(characterSet, characterSet.invertedSet.invertedSet); +} +@end ADDED tests/OFColorTests.m Index: tests/OFColorTests.m ================================================================== --- /dev/null +++ tests/OFColorTests.m @@ -0,0 +1,62 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFColorTests: OTTestCase +{ + OFColor *_color; +} +@end + +@implementation OFColorTests +- (void)setUp +{ + [super setUp]; + + _color = [[OFColor alloc] initWithRed: 63.f / 255 + green: 127.f / 255 + blue: 1 + alpha: 1]; +} + +- (void)dealloc +{ + [_color release]; + + [super dealloc]; +} + +#ifdef OF_OBJFW_RUNTIME +- (void)testReturnsTaggedPointer +{ + OTAssertTrue(object_isTaggedPointer(_color)); +} +#endif + +- (void)testGetRedGreenBlueAlpha +{ + float red, green, blue, alpha; + + [_color getRed: &red green: &green blue: &blue alpha: &alpha]; + OTAssertEqual(red, 63.f / 255); + OTAssertEqual(green, 127.f / 255); + OTAssertEqual(blue, 1); + OTAssertEqual(alpha, 1); +} +@end ADDED tests/OFConcreteArrayTests.m Index: tests/OFConcreteArrayTests.m ================================================================== --- /dev/null +++ tests/OFConcreteArrayTests.m @@ -0,0 +1,30 @@ +/* + * 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 "OFArrayTests.h" + +#import "OFConcreteArray.h" + +@interface OFConcreteArrayTests: OFArrayTests +@end + +@implementation OFConcreteArrayTests +- (Class)arrayClass +{ + return [OFConcreteArray class]; +} +@end ADDED tests/OFConcreteDictionaryTests.m Index: tests/OFConcreteDictionaryTests.m ================================================================== --- /dev/null +++ tests/OFConcreteDictionaryTests.m @@ -0,0 +1,30 @@ +/* + * 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 "OFDictionaryTests.h" + +#import "OFConcreteDictionary.h" + +@interface OFConcreteDictionaryTests: OFDictionaryTests +@end + +@implementation OFConcreteDictionaryTests +- (Class)dictionaryClass +{ + return [OFConcreteDictionary class]; +} +@end ADDED tests/OFConcreteMutableArrayTests.m Index: tests/OFConcreteMutableArrayTests.m ================================================================== --- /dev/null +++ tests/OFConcreteMutableArrayTests.m @@ -0,0 +1,105 @@ +/* + * 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 "OFMutableArrayTests.h" + +#import "OFConcreteMutableArray.h" + +@interface OFConcreteMutableArrayTests: OFMutableArrayTests +@end + +static OFString *const cArray[] = { + @"Foo", + @"Bar", + @"Baz" +}; + +@implementation OFConcreteMutableArrayTests +- (Class)arrayClass +{ + return [OFConcreteMutableArray class]; +} + +- (void)testDetectMutationDuringEnumeration +{ + OFEnumerator *enumerator = [_mutableArray objectEnumerator]; + OFString *object; + size_t i; + + i = 0; + while ((object = [enumerator nextObject]) != nil) { + OTAssertEqualObjects(object, cArray[i]); + + [_mutableArray replaceObjectAtIndex: i withObject: @""]; + i++; + } + OTAssertEqual(i, _mutableArray.count); + + [_mutableArray removeObjectAtIndex: 0]; + OTAssertThrowsSpecific([enumerator nextObject], + OFEnumerationMutationException); +} + +- (void)testDetectMutationDuringFastEnumeration +{ + bool detected = false; + size_t i; + + i = 0; + for (OFString *object in _mutableArray) { + OTAssertEqualObjects(object, cArray[i]); + + [_mutableArray replaceObjectAtIndex: i withObject: @""]; + i++; + } + OTAssertEqual(i, _mutableArray.count); + + @try { + for (OFString *object in _mutableArray) { + (void)object; + [_mutableArray removeObjectAtIndex: 0]; + } + } @catch (OFEnumerationMutationException *e) { + detected = true; + } + OTAssertTrue(detected); +} + +#ifdef OF_HAVE_BLOCKS +- (void)testDetectMutationDuringEnumerateObjectsUsingBlock +{ + __block size_t i; + + i = 0; + [_mutableArray enumerateObjectsUsingBlock: + ^ (id object, size_t idx, bool *stop) { + OTAssertEqualObjects(object, cArray[idx]); + + [_mutableArray replaceObjectAtIndex: idx withObject: @""]; + i++; + }]; + OTAssertEqual(i, _mutableArray.count); + + OTAssertThrowsSpecific( + [_mutableArray enumerateObjectsUsingBlock: + ^ (id object, size_t idx, bool *stop) { + [_mutableArray removeObjectAtIndex: 0]; + }], + OFEnumerationMutationException); +} +#endif +@end ADDED tests/OFConcreteMutableDictionaryTests.m Index: tests/OFConcreteMutableDictionaryTests.m ================================================================== --- /dev/null +++ tests/OFConcreteMutableDictionaryTests.m @@ -0,0 +1,100 @@ +/* + * 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 "OFMutableDictionaryTests.h" + +#import "OFConcreteMutableDictionary.h" + +@interface OFConcreteMutableDictionaryTests: OFMutableDictionaryTests +@end + +@implementation OFConcreteMutableDictionaryTests +- (Class)dictionaryClass +{ + return [OFConcreteMutableDictionary class]; +} + +- (void)testDetectMutationDuringEnumeration +{ + OFMutableDictionary *mutableDictionary = + [[_dictionary mutableCopy] autorelease]; + OFEnumerator *keyEnumerator = [mutableDictionary keyEnumerator]; + OFEnumerator *objectEnumerator = [mutableDictionary objectEnumerator]; + OFString *key; + size_t i; + + i = 0; + while ((key = [keyEnumerator nextObject]) != nil) { + [mutableDictionary setObject: @"test" forKey: key]; + i++; + } + OTAssertEqual(i, mutableDictionary.count); + + [mutableDictionary removeObjectForKey: @"key2"]; + OTAssertThrowsSpecific([keyEnumerator nextObject], + OFEnumerationMutationException); + OTAssertThrowsSpecific([objectEnumerator nextObject], + OFEnumerationMutationException); +} + +- (void)testDetectMutationDuringFastEnumeration +{ + OFMutableDictionary *mutableDictionary = + [[_dictionary mutableCopy] autorelease]; + bool detected = false; + size_t i; + + i = 0; + for (OFString *key in mutableDictionary) { + [mutableDictionary setObject: @"test" forKey: key]; + i++; + } + OTAssertEqual(i, mutableDictionary.count); + + @try { + for (OFString *key in mutableDictionary) + [mutableDictionary removeObjectForKey: key]; + } @catch (OFEnumerationMutationException *e) { + detected = true; + } + OTAssertTrue(detected); +} + +#ifdef OF_HAVE_BLOCKS +- (void)testDetectMutationDuringEnumerateObjectsUsingBlock +{ + OFMutableDictionary *mutableDictionary = + [[_dictionary mutableCopy] autorelease]; + __block size_t i; + + i = 0; + [mutableDictionary enumerateKeysAndObjectsUsingBlock: + ^ (id key, id object, bool *stop) { + [mutableDictionary setObject: @"test" forKey: key]; + i++; + }]; + OTAssertEqual(i, mutableDictionary.count); + + OTAssertThrowsSpecific( + [mutableDictionary enumerateKeysAndObjectsUsingBlock: + ^ (id key, id object, bool *stop) { + [mutableDictionary removeObjectForKey: key]; + }], + OFEnumerationMutationException); +} +#endif +@end ADDED tests/OFConcreteMutableSetTests.m Index: tests/OFConcreteMutableSetTests.m ================================================================== --- /dev/null +++ tests/OFConcreteMutableSetTests.m @@ -0,0 +1,65 @@ +/* + * 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 "OFMutableSetTests.h" + +#import "OFConcreteMutableSet.h" + +@interface OFConcreteMutableSetTests: OFMutableSetTests +@end + +@implementation OFConcreteMutableSetTests +- (Class)setClass +{ + return [OFConcreteMutableSet class]; +} + +- (void)testDetectMutationDuringEnumeration +{ + OFEnumerator *enumerator = [_mutableSet objectEnumerator]; + + [_mutableSet removeObject: @"foo"]; + + OTAssertThrowsSpecific([enumerator nextObject], + OFEnumerationMutationException); +} + +- (void)testDetectMutationDuringFastEnumeration +{ + bool detected = false; + + @try { + for (OFString *object in _mutableSet) + [_mutableSet removeObject: object]; + } @catch (OFEnumerationMutationException *e) { + detected = true; + } + + OTAssertTrue(detected); +} + +#ifdef OF_HAVE_BLOCKS +- (void)testDetectMutationDuringEnumerateObjectsUsingBlock +{ + OTAssertThrowsSpecific( + [_mutableSet enumerateObjectsUsingBlock: ^ (id object, bool *stop) { + [_mutableSet removeObject: object]; + }], + OFEnumerationMutationException); +} +#endif +@end ADDED tests/OFConcreteSetTests.m Index: tests/OFConcreteSetTests.m ================================================================== --- /dev/null +++ tests/OFConcreteSetTests.m @@ -0,0 +1,30 @@ +/* + * 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 "OFSetTests.h" + +#import "OFConcreteSet.h" + +@interface OFConcreteSetTests: OFSetTests +@end + +@implementation OFConcreteSetTests +- (Class)setClass +{ + return [OFConcreteSet class]; +} +@end ADDED tests/OFCryptographicHashTests.m Index: tests/OFCryptographicHashTests.m ================================================================== --- /dev/null +++ tests/OFCryptographicHashTests.m @@ -0,0 +1,140 @@ +/* + * 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" + +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFCryptographicHashTests: OTTestCase +{ + OFStream *_stream; +} +@end + +const unsigned char testFileMD5[16] = + "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38"; +const unsigned char testFileRIPEMD160[20] = + "\x46\x02\x97\xF5\x85\xDF\xB9\x21\x00\xC8\xF9\x87\xC6\xEC\x84\x0D" + "\xCE\xE6\x08\x8B"; +const unsigned char testFileSHA1[20] = + "\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96" + "\xF5\x94\xE7\x17"; +const unsigned char testFileSHA224[28] = + "\x27\x69\xD8\x04\x2D\x0F\xCA\x84\x6C\xF1\x62\x44\xBA\x0C\xBD\x46" + "\x64\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7"; +const unsigned char testFileSHA256[32] = + "\x1A\x02\xD6\x46\xF5\xA6\xBA\xAA\xFF\x7F\xD5\x87\xBA\xC3\xF6\xC6" + "\xB5\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69"; +const unsigned char testFileSHA384[48] = + "\x7E\xDE\x62\xE2\x10\xA5\x1E\x18\x8A\x11\x7F\x78\xD7\xC7\x55\xB6" + "\x43\x94\x1B\xD2\x78\x5C\xCF\xF3\x8A\xB8\x98\x22\xC7\x0E\xFE\xF1" + "\xEC\x53\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54"; +const unsigned char testFileSHA512[64] = + "\x8F\x36\x6E\x3C\x19\x4B\xBB\xC7\x82\xAA\xCD\x7D\x55\xA2\xD3\x29" + "\x29\x97\x6A\x3F\xEB\x9B\xB2\xCB\x75\xC9\xEC\xC8\x10\x07\xD6\x07" + "\x31\x4A\xB1\x30\x97\x82\x58\xA5\x1F\x71\x42\xE6\x56\x07\x99\x57" + "\xB2\xB8\x3B\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0"; + +@implementation OFCryptographicHashTests +- (void)setUp +{ + OFIRI *IRI; + + [super setUp]; + + IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; + _stream = [[OFIRIHandler openItemAtIRI: IRI mode: @"r"] retain]; +} + +- (void)tearDown +{ + [_stream close]; + + [super tearDown]; +} + +- (void)dealloc +{ + [_stream release]; + + [super dealloc]; +} + +- (void)testHash: (Class)hashClass + expectedDigest: (const unsigned char *)expectedDigest +{ + id hash = + [hashClass hashWithAllowsSwappableMemory: true]; + id copy; + + OTAssertNotNil(hash); + + while (!_stream.atEndOfStream) { + char buffer[64]; + size_t length = [_stream readIntoBuffer: buffer length: 64]; + [hash updateWithBuffer: buffer length: length]; + } + + copy = [[hash copy] autorelease]; + + [hash calculate]; + [copy calculate]; + + OTAssertEqual(memcmp(hash.digest, expectedDigest, hash.digestSize), 0); + OTAssertEqual(memcmp(hash.digest, expectedDigest, hash.digestSize), 0); + + OTAssertThrowsSpecific([hash updateWithBuffer: "" length: 1], + OFHashAlreadyCalculatedException); +} + +- (void)testMD5 +{ + [self testHash: [OFMD5Hash class] expectedDigest: testFileMD5]; +} + +- (void)testRIPEMD160 +{ + [self testHash: [OFRIPEMD160Hash class] + expectedDigest: testFileRIPEMD160]; +} + +- (void)testSHA1 +{ + [self testHash: [OFSHA1Hash class] expectedDigest: testFileSHA1]; +} + +- (void)testSHA224 +{ + [self testHash: [OFSHA224Hash class] expectedDigest: testFileSHA224]; +} + +- (void)testSHA256 +{ + [self testHash: [OFSHA256Hash class] expectedDigest: testFileSHA256]; +} + +- (void)testSHA384 +{ + [self testHash: [OFSHA384Hash class] expectedDigest: testFileSHA384]; +} + +- (void)testSHA512 +{ + [self testHash: [OFSHA512Hash class] expectedDigest: testFileSHA512]; +} +@end ADDED tests/OFDDPSocketTests.m Index: tests/OFDDPSocketTests.m ================================================================== --- /dev/null +++ tests/OFDDPSocketTests.m @@ -0,0 +1,63 @@ +/* + * 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" + +#include +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFDDPSocketTests: OTTestCase +@end + +@implementation OFDDPSocketTests +- (void)testDDPSocket +{ + OFDDPSocket *sock; + OFSocketAddress address1, address2; + char buffer[5]; + + sock = [OFDDPSocket socket]; + + @try { + address1 = [sock bindToNetwork: 0 + node: 0 + port: 0 + protocolType: 11]; + } @catch (OFBindSocketFailedException *e) { + switch (e.errNo) { + case EAFNOSUPPORT: + case EPROTONOSUPPORT: + OTSkip(@"AppleTalk unsupported"); + case EADDRNOTAVAIL: + OTSkip(@"AppleTalk not configured"); + default: + @throw e; + } + } + + [sock sendBuffer: "Hello" length: 5 receiver: &address1]; + + OTAssertEqual([sock receiveIntoBuffer: buffer + length: 5 + sender: &address2], 5); + OTAssertEqual(memcmp(buffer, "Hello", 5), 0); + OTAssertTrue(OFSocketAddressEqual(&address1, &address2)); + OTAssertEqual(OFSocketAddressHash(&address1), + OFSocketAddressHash(&address2)); +} +@end ADDED tests/OFDNSResolverTests.m Index: tests/OFDNSResolverTests.m ================================================================== --- /dev/null +++ tests/OFDNSResolverTests.m @@ -0,0 +1,74 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFDNSResolverTests: OTTestCase +@end + +@implementation OFDNSResolverTests ++ (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, id) *) *)summary +{ + OFMutableArray *summary = [OFMutableArray array]; + OFDNSResolver *resolver = [OFDNSResolver resolver]; + OFMutableString *staticHosts = [OFMutableString string]; + +#define ADD(name, value) \ + [summary addObject: [OFPair pairWithFirstObject: name \ + secondObject: value]]; +#define ADD_DOUBLE(name, value) \ + ADD(name, [OFNumber numberWithDouble: value]) +#define ADD_UINT(name, value) \ + ADD(name, [OFNumber numberWithUnsignedInt: value]); +#define ADD_BOOL(name, value) \ + ADD(name, [OFNumber numberWithBool: value]); + + for (OFString *host in resolver.staticHosts) { + OFString *IPs; + + if (staticHosts.length > 0) + [staticHosts appendString: @"; "]; + + IPs = [[resolver.staticHosts objectForKey: host] + componentsJoinedByString: @", "]; + + [staticHosts appendFormat: @"%@=(%@)", host, IPs]; + } + ADD(@"Static hosts", staticHosts) + + ADD(@"Name servers", + [resolver.nameServers componentsJoinedByString: @", "]); + ADD(@"Local domain", resolver.localDomain); + ADD(@"Search domains", + [resolver.searchDomains componentsJoinedByString: @", "]); + + ADD_DOUBLE(@"Timeout", resolver.timeout); + ADD_UINT(@"Max attempts", resolver.maxAttempts); + ADD_UINT(@"Min number of dots in absolute name", + resolver.minNumberOfDotsInAbsoluteName); + ADD_BOOL(@"Forces TCP", resolver.forcesTCP); + ADD_DOUBLE(@"Config reload interval", resolver.configReloadInterval); + +#undef ADD +#undef ADD_DOUBLE +#undef ADD_UINT +#undef ADD_BOOL + + return summary; +} +@end ADDED tests/OFDataTests.h Index: tests/OFDataTests.h ================================================================== --- /dev/null +++ tests/OFDataTests.h @@ -0,0 +1,26 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFDataTests: OTTestCase +{ + OFData *_data; + unsigned char _items[2][4096]; +} + +@property (readonly, nonatomic) Class dataClass; +@end ADDED tests/OFDataTests.m Index: tests/OFDataTests.m ================================================================== --- /dev/null +++ tests/OFDataTests.m @@ -0,0 +1,291 @@ +/* + * 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" + +#include + +#import "OFDataTests.h" + +@implementation OFDataTests +- (Class)dataClass +{ + return [OFData class]; +} + +- (void)setUp +{ + [super setUp]; + + memset(&_items[0], 0xFF, 4096); + memset(&_items[1], 0x42, 4096); + + _data = [[self.dataClass alloc] initWithItems: _items + count: 2 + itemSize: 4096]; +} + +- (void)dealloc +{ + [_data release]; + + [super dealloc]; +} + +- (void)testCount +{ + OTAssertEqual(_data.count, 2); +} + +- (void)testItemSize +{ + OTAssertEqual(_data.itemSize, 4096); +} + +- (void)testItems +{ + OTAssertEqual(memcmp(_data.items, _items, 2 * _data.itemSize), 0); +} + +- (void)testItemAtIndex +{ + OTAssertEqual( + memcmp([_data itemAtIndex: 1], &_items[1], _data.itemSize), 0); +} + +- (void)testItemAtIndexThrowsOnOutOfRangeIndex +{ + OTAssertThrowsSpecific([_data itemAtIndex: _data.count], + OFOutOfRangeException); +} + +- (void)testFirstItem +{ + OTAssertEqual(memcmp(_data.firstItem, &_items[0], _data.itemSize), 0); +} + +- (void)testLastItem +{ + OTAssertEqual(memcmp(_data.lastItem, &_items[1], _data.itemSize), 0); +} + +- (void)testIsEqual +{ + OTAssertEqualObjects( + _data, [OFData dataWithItems: _items count: 2 itemSize: 4096]); + OTAssertNotEqualObjects( + _data, [OFData dataWithItems: _items count: 1 itemSize: 4096]); +} + +- (void)testHash +{ + OTAssertEqual(_data.hash, + [[OFData dataWithItems: _items count: 2 itemSize: 4096] hash]); + OTAssertNotEqual(_data.hash, + [[OFData dataWithItems: _items count: 1 itemSize: 4096] hash]); +} + +- (void)testCompare +{ + OFData *data1 = [self.dataClass dataWithItems: "aa" count: 2]; + OFData *data2 = [self.dataClass dataWithItems: "ab" count: 2]; + OFData *data3 = [self.dataClass dataWithItems: "aaa" count: 3]; + + OTAssertEqual([data1 compare: data2], OFOrderedAscending); + OTAssertEqual([data2 compare: data1], OFOrderedDescending); + OTAssertEqual([data1 compare: data1], OFOrderedSame); + OTAssertEqual([data1 compare: data3], OFOrderedAscending); + OTAssertEqual([data2 compare: data3], OFOrderedDescending); +} + +- (void)testCopy +{ + OTAssertEqualObjects([[_data copy] autorelease], _data); +} + +- (void)testRangeOfDataOptionsRange +{ + OFData *data = [self.dataClass dataWithItems: "aaabaccdacaabb" + count: 7 + itemSize: 2]; + OFRange range; + + range = [data rangeOfData: [self.dataClass dataWithItems: "aa" + count: 1 + itemSize: 2] + options: 0 + range: OFMakeRange(0, 7)]; + OTAssertEqual(range.location, 0); + OTAssertEqual(range.length, 1); + + range = [data rangeOfData: [self.dataClass dataWithItems: "aa" + count: 1 + itemSize: 2] + options: OFDataSearchBackwards + range: OFMakeRange(0, 7)]; + OTAssertEqual(range.location, 5); + OTAssertEqual(range.length, 1); + + range = [data rangeOfData: [self.dataClass dataWithItems: "ac" + count: 1 + itemSize: 2] + options: 0 + range: OFMakeRange(0, 7)]; + OTAssertEqual(range.location, 2); + OTAssertEqual(range.length, 1); + + range = [data rangeOfData: [self.dataClass dataWithItems: "aabb" + count: 2 + itemSize: 2] + options: 0 + range: OFMakeRange(0, 7)]; + OTAssertEqual(range.location, 5); + OTAssertEqual(range.length, 2); + + range = [data rangeOfData: [self.dataClass dataWithItems: "aa" + count: 1 + itemSize: 2] + options: 0 + range: OFMakeRange(1, 6)]; + OTAssertEqual(range.location, 5); + OTAssertEqual(range.length, 1); + + range = [data rangeOfData: [self.dataClass dataWithItems: "aa" + count: 1 + itemSize: 2] + options: OFDataSearchBackwards + range: OFMakeRange(0, 5)]; + OTAssertEqual(range.location, 0); + OTAssertEqual(range.length, 1); +} + +- (void)testRangeOfDataOptionsRangeThrowsOnDifferentItemSize +{ + OTAssertThrowsSpecific( + [_data rangeOfData: [OFData dataWithItems: "a" count: 1] + options: 0 + range: OFMakeRange(0, 1)], + OFInvalidArgumentException); +} + +- (void)testRangeOfDataOptionsRangeThrowsOnOutOfRangeRange +{ + OTAssertThrowsSpecific( + [_data rangeOfData: [OFData dataWithItemSize: 4096] + options: 0 + range: OFMakeRange(1, 2)], + OFOutOfRangeException); + + OTAssertThrowsSpecific( + [_data rangeOfData: [OFData dataWithItemSize: 4096] + options: 0 + range: OFMakeRange(2, 1)], + OFOutOfRangeException); +} + +- (void)testSubdataWithRange +{ + OFData *data1 = [self.dataClass dataWithItems: "aaabaccdacaabb" + count: 7 + itemSize: 2]; + OFData *data2 = [self.dataClass dataWithItems: "abcde" count: 5]; + + OTAssertEqualObjects( + [data1 subdataWithRange: OFMakeRange(2, 4)], + [OFData dataWithItems: "accdacaa" count: 4 itemSize: 2]); + + OTAssertEqualObjects( + [data2 subdataWithRange: OFMakeRange(2, 3)], + [OFData dataWithItems: "cde" count: 3]); +} + +- (void)testSubdataWithRangeThrowsOnOutOfRangeRange +{ + OFData *data1 = [self.dataClass dataWithItems: "aaabaccdacaabb" + count: 7 + itemSize: 2]; + OFData *data2 = [self.dataClass dataWithItems: "abcde" count: 5]; + + OTAssertThrowsSpecific([data1 subdataWithRange: OFMakeRange(7, 1)], + OFOutOfRangeException); + + OTAssertThrowsSpecific([data1 subdataWithRange: OFMakeRange(8, 0)], + OFOutOfRangeException); + + OTAssertThrowsSpecific([data2 subdataWithRange: OFMakeRange(6, 1)], + OFOutOfRangeException); +} + +- (void)testStringByMD5Hashing +{ + OTAssertEqualObjects(_data.stringByMD5Hashing, + @"37d65c8816008d58175b1d71ee892de3"); +} + +- (void)testStringByRIPEMD160Hashing +{ + OTAssertEqualObjects(_data.stringByRIPEMD160Hashing, + @"ab33a6a725f9fcec6299054dc604c0eb650cd889"); +} + +- (void)testStringBySHA1Hashing +{ + OTAssertEqualObjects(_data.stringBySHA1Hashing, + @"eb50cfcc29d0bed96b3bafe03e99110bcf6663b3"); +} + +- (void)testStringBySHA224Hashing +{ + OTAssertEqualObjects(_data.stringBySHA224Hashing, + @"204f8418a914a6828f8eb27871e01f74366f6d8fac8936029ebf0041"); +} + +- (void)testStringBySHA256Hashing +{ + OTAssertEqualObjects(_data.stringBySHA256Hashing, + @"27c521859f6f5b10aeac4e210a6d005c" + @"85e382c594e2622af9c46c6da8906821"); +} + +- (void)testStringBySHA384Hashing +{ + OTAssertEqualObjects(_data.stringBySHA384Hashing, + @"af99a52c26c00f01fe649dcc53d7c7a0" + @"a9ee0150b971955be2af395708966120" + @"5f2634f70df083ef63b232d5b8549db4"); +} + +- (void)testStringBySHA512Hashing +{ + OTAssertEqualObjects(_data.stringBySHA512Hashing, + @"1cbd53bf8bed9b45a63edda645ee1217" + @"24d2f0323c865e1039ba13320bc6c66e" + @"c79b6cdf6d08395c612b7decb1e59ad1" + @"e72bfa007c2f76a823d10204d47d2e2d"); +} + +- (void)testStringByBase64Encoding +{ + OTAssertEqualObjects([[self.dataClass dataWithItems: "abcde" count: 5] + stringByBase64Encoding], @"YWJjZGU="); +} + +- (void)testDataWithBase64EncodedString +{ + OTAssertEqualObjects( + [self.dataClass dataWithBase64EncodedString: @"YWJjZGU="], + [OFData dataWithItems: "abcde" count: 5]); +} +@end ADDED tests/OFDateTests.m Index: tests/OFDateTests.m ================================================================== --- /dev/null +++ tests/OFDateTests.m @@ -0,0 +1,198 @@ +/* + * 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" + +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +#import "OFStrPTime.h" + +@interface OFDateTests: OTTestCase +{ + OFDate *_date[2]; +} +@end + +@implementation OFDateTests +- (void)setUp +{ + [super setUp]; + + _date[0] = [[OFDate alloc] initWithTimeIntervalSince1970: 0]; + _date[1] = [[OFDate alloc] + initWithTimeIntervalSince1970: 3600 * 25 + 5.000002]; +} + +- (void)dealloc +{ + [_date[0] release]; + [_date[1] release]; + + [super dealloc]; +} + +- (void)testStrPTime +{ + struct tm tm; + int16_t timeZone; + const char *dateString = "Wed, 09 Jun 2021 +0200x"; + + OTAssertEqual(OFStrPTime(dateString, "%a, %d %b %Y %z", &tm, &timeZone), + dateString + 22); + OTAssertEqual(tm.tm_wday, 3); + OTAssertEqual(tm.tm_mday, 9); + OTAssertEqual(tm.tm_mon, 5); + OTAssertEqual(tm.tm_year, 2021 - 1900); + OTAssertEqual(timeZone, 2 * 60); +} + +- (void)testDateByAddingTimeInterval +{ + OTAssertEqualObjects( + [_date[0] dateByAddingTimeInterval: 3600 * 25 + 5.000002], + _date[1]); +} + +- (void)testDescription +{ + OTAssertEqualObjects(_date[0].description, @"1970-01-01T00:00:00Z"); + OTAssertEqualObjects(_date[1].description, @"1970-01-02T01:00:05Z"); +} + +- (void)testDateWithDateStringFormat +{ + OTAssertEqualObjects( + [[OFDate dateWithDateString: @"2000-06-20T12:34:56+0200" + format: @"%Y-%m-%dT%H:%M:%S%z"] description], + @"2000-06-20T10:34:56Z"); +} + +- (void)testDateWithDateStringFormatFailsWithTrailingCharacters +{ + OTAssertThrowsSpecific( + [OFDate dateWithDateString: @"2000-06-20T12:34:56+0200x" + format: @"%Y-%m-%dT%H:%M:%S%z"], + OFInvalidFormatException); +} + +- (void)testDateWithLocalDateStringFormatFormat +{ + OTAssertEqualObjects( + [[OFDate dateWithLocalDateString: @"2000-06-20T12:34:56" + format: @"%Y-%m-%dT%H:%M:%S"] + localDateStringWithFormat: @"%Y-%m-%dT%H:%M:%S"], + @"2000-06-20T12:34:56"); + + OTAssertEqualObjects( + [[OFDate dateWithLocalDateString: @"2000-06-20T12:34:56-0200" + format: @"%Y-%m-%dT%H:%M:%S%z"] + description], + @"2000-06-20T14:34:56Z"); +} + +- (void)testDateWithLocalDateStringFormatFailsWithTrailingCharacters +{ + OTAssertThrowsSpecific( + [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56x" + format: @"%Y-%m-%dT%H:%M:%S"], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56+0200x" + format: @"%Y-%m-%dT%H:%M:%S%z"], + OFInvalidFormatException); +} + +- (void)testIsEqual +{ + OTAssertEqualObjects(_date[0], + [OFDate dateWithTimeIntervalSince1970: 0]); + + OTAssertNotEqualObjects(_date[0], + [OFDate dateWithTimeIntervalSince1970: 0.0000001]); +} + +- (void)testCompare +{ + OTAssertEqual([_date[0] compare: _date[1]], OFOrderedAscending); +} + +- (void)testSecond +{ + OTAssertEqual(_date[0].second, 0); + OTAssertEqual(_date[1].second, 5); +} + +- (void)testMicrosecond +{ + OTAssertEqual(_date[0].microsecond, 0); + OTAssertEqual(_date[1].microsecond, 2); +} + +- (void)testMinute +{ + OTAssertEqual(_date[0].minute, 0); + OTAssertEqual(_date[1].minute, 0); +} + +- (void)testHour +{ + OTAssertEqual(_date[0].hour, 0); + OTAssertEqual(_date[1].hour, 1); +} + +- (void)testDayOfMonth +{ + OTAssertEqual(_date[0].dayOfMonth, 1); + OTAssertEqual(_date[1].dayOfMonth, 2); +} + +- (void)testMonthOfYear +{ + OTAssertEqual(_date[0].monthOfYear, 1); + OTAssertEqual(_date[1].monthOfYear, 1); +} + +- (void)testYear +{ + OTAssertEqual(_date[0].year, 1970); + OTAssertEqual(_date[1].year, 1970); +} + +- (void)testDayOfWeek +{ + OTAssertEqual(_date[0].dayOfWeek, 4); + OTAssertEqual(_date[1].dayOfWeek, 5); +} + +- (void)testDayOfYear +{ + OTAssertEqual(_date[0].dayOfYear, 1); + OTAssertEqual(_date[1].dayOfYear, 2); +} + +- (void)testEarlierDate +{ + OTAssertEqualObjects([_date[0] earlierDate: _date[1]], _date[0]); +} + +- (void)testLaterDate +{ + OTAssertEqualObjects([_date[0] laterDate: _date[1]], _date[1]); +} +@end ADDED tests/OFDictionaryTests.h Index: tests/OFDictionaryTests.h ================================================================== --- /dev/null +++ tests/OFDictionaryTests.h @@ -0,0 +1,25 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFDictionaryTests: OTTestCase +{ + OFDictionary *_dictionary; +} + +@property (readonly, nonatomic) Class dictionaryClass; +@end ADDED tests/OFDictionaryTests.m Index: tests/OFDictionaryTests.m ================================================================== --- /dev/null +++ tests/OFDictionaryTests.m @@ -0,0 +1,295 @@ +/* + * 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 "OFDictionaryTests.h" + +static OFString *keys[] = { + @"key1", + @"key2" +}; +static OFString *objects[] = { + @"value1", + @"value2" +}; + +@interface CustomDictionary: OFDictionary +{ + OFDictionary *_dictionary; +} +@end + +@implementation OFDictionaryTests +- (Class)dictionaryClass +{ + return [CustomDictionary class]; +} + +- (void)setUp +{ + [super setUp]; + + _dictionary = [[self.dictionaryClass alloc] initWithObjects: objects + forKeys: keys + count: 2]; +} + +- (void)dealloc +{ + [_dictionary release]; + + [super dealloc]; +} + +- (void)testObjectForKey +{ + OTAssertEqualObjects([_dictionary objectForKey: keys[0]], objects[0]); + OTAssertEqualObjects([_dictionary objectForKey: keys[1]], objects[1]); +} + +- (void)testCount +{ + OTAssertEqual(_dictionary.count, 2); +} + +- (void)testIsEqual +{ + OTAssertEqualObjects(_dictionary, + [OFDictionary dictionaryWithObjects: objects + forKeys: keys + count: 2]); + OTAssertNotEqualObjects(_dictionary, + [OFDictionary dictionaryWithObjects: keys + forKeys: objects + count: 2]); +} + +- (void)testHash +{ + OTAssertEqual(_dictionary.hash, + [[OFDictionary dictionaryWithObjects: objects + forKeys: keys + count: 2] hash]); + OTAssertNotEqual(_dictionary.hash, + [[OFDictionary dictionaryWithObject: objects[0] + forKey: keys[0]] hash]); +} + +- (void)testCopy +{ + OTAssertEqualObjects([[_dictionary copy] autorelease], _dictionary); +} + +- (void)testValueForKey +{ + OTAssertEqualObjects([_dictionary valueForKey: keys[0]], objects[0]); + OTAssertEqualObjects([_dictionary valueForKey: keys[1]], objects[1]); + OTAssertEqualObjects( + [_dictionary valueForKey: @"@count"], [OFNumber numberWithInt: 2]); +} + +- (void)testSetValueForKey +{ + OTAssertThrowsSpecific([_dictionary setValue: @"x" forKey: @"x"], + OFUndefinedKeyException); +} + +- (void)testContainsObject +{ + OTAssertTrue([_dictionary containsObject: objects[0]]); + OTAssertFalse([_dictionary containsObject: @"nonexistent"]); +} + +- (void)testContainsObjectIdenticalTo +{ + OTAssertTrue([_dictionary containsObjectIdenticalTo: objects[0]]); + OTAssertFalse([_dictionary containsObjectIdenticalTo: + [[objects[0] mutableCopy] autorelease]]); +} + +- (void)testDescription +{ + OTAssert( + [_dictionary.description isEqual: + @"{\n\tkey1 = value1;\n\tkey2 = value2;\n}"] || + [_dictionary.description isEqual: + @"{\n\tkey2 = value2;\n\tkey1 = value1;\n}"]); +} + +- (void)testAllKeys +{ + OTAssert( + [_dictionary.allKeys isEqual: + ([OFArray arrayWithObjects: keys[0], keys[1], nil])] || + [_dictionary.allKeys isEqual: + ([OFArray arrayWithObjects: keys[1], keys[0], nil])]); +} + +- (void)testAllObjects +{ + OTAssert( + [_dictionary.allObjects isEqual: + ([OFArray arrayWithObjects: objects[0], objects[1], nil])] || + [_dictionary.allObjects isEqual: + ([OFArray arrayWithObjects: objects[1], objects[0], nil])]); +} + +- (void)testKeyEnumerator +{ + OFEnumerator *enumerator = [_dictionary keyEnumerator]; + OFString *first, *second; + + first = [enumerator nextObject]; + second = [enumerator nextObject]; + OTAssertNil([enumerator nextObject]); + + OTAssert( + ([first isEqual: keys[0]] && [second isEqual: keys[1]]) || + ([first isEqual: keys[1]] && [second isEqual: keys[0]])); +} + +- (void)testObjectEnumerator +{ + OFEnumerator *enumerator = [_dictionary objectEnumerator]; + OFString *first, *second; + + first = [enumerator nextObject]; + second = [enumerator nextObject]; + OTAssertNil([enumerator nextObject]); + + OTAssert( + ([first isEqual: objects[0]] && [second isEqual: objects[1]]) || + ([first isEqual: objects[1]] && [second isEqual: objects[0]])); +} + +- (void)testFastEnumeration +{ + size_t i = 0; + OFString *first = nil, *second = nil; + + for (OFString *key in _dictionary) { + OTAssertLessThan(i, 2); + + switch (i++) { + case 0: + first = key; + break; + case 1: + second = key; + break; + } + } + + OTAssertEqual(i, 2); + OTAssert( + ([first isEqual: keys[0]] && [second isEqual: keys[1]]) || + ([first isEqual: keys[1]] && [second isEqual: keys[0]])); +} + +#ifdef OF_HAVE_BLOCKS +- (void)testEnumerateKeysAndObjectsUsingBlock +{ + __block size_t i = 0; + __block OFString *first = nil, *second = nil; + + [_dictionary enumerateKeysAndObjectsUsingBlock: + ^ (id key, id object, bool *stop) { + OTAssertLessThan(i, 2); + + switch (i++) { + case 0: + first = key; + break; + case 1: + second = key; + break; + } + }]; + + OTAssertEqual(i, 2); + OTAssert( + ([first isEqual: keys[0]] && [second isEqual: keys[1]]) || + ([first isEqual: keys[1]] && [second isEqual: keys[0]])); +} + +- (void)testMappedDictionaryUsingBlock +{ + OTAssertEqualObjects([_dictionary mappedDictionaryUsingBlock: + ^ id (id key, id object) { + if ([key isEqual: keys[0]]) + return @"val1"; + if ([key isEqual: keys[1]]) + return @"val2"; + + return nil; + }], + ([OFDictionary dictionaryWithKeysAndObjects: + @"key1", @"val1", @"key2", @"val2", nil])); +} + +- (void)testFilteredDictionaryUsingBlock +{ + OTAssertEqualObjects([_dictionary filteredDictionaryUsingBlock: + ^ bool (id key, id object) { + return [key isEqual: keys[0]]; + }], + [OFDictionary dictionaryWithObject: objects[0] + forKey: keys[0]]); +} +#endif +@end + +@implementation CustomDictionary +- (instancetype)initWithObjects: (const id *)objects_ + forKeys: (const id *)keys_ + count: (size_t)count +{ + self = [super init]; + + @try { + _dictionary = [[OFDictionary alloc] initWithObjects: objects_ + forKeys: keys_ + count: count]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_dictionary release]; + + [super dealloc]; +} + +- (id)objectForKey: (id)key +{ + return [_dictionary objectForKey: key]; +} + +- (size_t)count +{ + return _dictionary.count; +} + +- (OFEnumerator *)keyEnumerator +{ + return [_dictionary keyEnumerator]; +} +@end ADDED tests/OFHMACTests.m Index: tests/OFHMACTests.m ================================================================== --- /dev/null +++ tests/OFHMACTests.m @@ -0,0 +1,138 @@ +/* + * 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" + +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFHMACTests: OTTestCase +{ + OFStream *_stream; +} +@end + +static const uint8_t key[] = + "yM9h8K6IWnJRvxC/0F8XRWG7RnACDBz8wqK2tbXrYVLoKC3vPLeJikyJSM47tVHc" + "DlXHww9zULAC2sJUlm2Kg1z4oz2aXY3Y1PQSB4VkC/m0DQ7hCI6cAg4TWnKdzWTy" + "cvYGX+Y6HWeDY79/PGSd8fNItme6I8w4HDBqU7BP2sum3jbePJqoiSnhcyJZQTeZ" + "jw0ZXoyrfHgOYD2M+NsTDaGpLblFtQ7n5CczjKtafG40PkEwx1dcrd46U9i3GyTK"; +static const size_t keyLength = sizeof(key); +static const uint8_t MD5Digest[] = + "\xCC\x1F\xEF\x09\x29\xA3\x25\x1A\x06\xA9\x83\x99\xF9\xBC\x8F\x42"; +static const uint8_t SHA1Digest[] = + "\x94\xB9\x0A\x6F\xFB\xA7\x13\x6A\x75\x55" + "\xD5\x7F\x5D\xB7\xF4\xCA\xEB\x4A\xDE\xBF"; +static const uint8_t RIPEMD160Digest[] = + "\x2C\xE1\xED\x41\xC6\xF3\x51\xA8\x04\xD2" + "\xC3\x9B\x08\x33\x3B\xD5\xC9\x00\x39\x50"; +static const uint8_t SHA256Digest[] = + "\xFB\x8C\xDA\x88\xB3\x81\x32\x16\xD7\xD8\x62\xD4\xA6\x26\x9D\x77" + "\x01\x99\x62\x65\x29\x02\x41\xE6\xEF\xA1\x02\x31\xA8\x9D\x77\x5D"; +static const uint8_t SHA384Digest[] = + "\x2F\x4A\x47\xAE\x13\x8E\x96\x52\xF1\x8F\x05\xFD\x65\xCD\x9A\x97" + "\x93\x2F\xC9\x02\xD6\xC6\xAB\x2E\x15\x76\xC0\xA7\xA0\x05\xF4\xEF" + "\x14\x52\x33\x4B\x9C\x5F\xD8\x07\x4E\x98\xAE\x97\x46\x29\x24\xB4"; +static const uint8_t SHA512Digest[] = + "\xF5\x8C\x3F\x9C\xA2\x2F\x0A\xF3\x26\xD8\xC0\x7E\x20\x63\x88\x61" + "\xC9\xE1\x1F\xD7\xC7\xE5\x59\x33\xD5\x2F\xAF\x56\x1C\x94\xC8\xA4" + "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E" + "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99"; + +@implementation OFHMACTests +- (void)setUp +{ + OFIRI *IRI; + + [super setUp]; + + IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; + _stream = [[OFIRIHandler openItemAtIRI: IRI mode: @"r"] retain]; +} + +- (void)tearDown +{ + [_stream close]; + + [super tearDown]; +} + +- (void)dealloc +{ + [_stream release]; + + [super dealloc]; +} + +- (void)testWithHashClass: (Class)hashClass + expectedDigest: (const unsigned char *)expectedDigest +{ + OFHMAC *HMAC = [OFHMAC HMACWithHashClass: hashClass + allowsSwappableMemory: true]; + + OTAssertNotNil(HMAC); + + OTAssertThrowsSpecific([HMAC updateWithBuffer: "" length: 0], + OFInvalidArgumentException); + + [HMAC setKey: key length: keyLength]; + + while (!_stream.atEndOfStream) { + char buffer[64]; + size_t length = [_stream readIntoBuffer: buffer length: 64]; + [HMAC updateWithBuffer: buffer length: length]; + } + + [HMAC calculate]; + + OTAssertEqual(memcmp(HMAC.digest, expectedDigest, HMAC.digestSize), 0); +} + +- (void)testHMACWithMD5 +{ + [self testWithHashClass: [OFMD5Hash class] expectedDigest: MD5Digest]; +} + +- (void)testHMACWithRIPEMD160 +{ + [self testWithHashClass: [OFRIPEMD160Hash class] + expectedDigest: RIPEMD160Digest]; +} + +- (void)testHMACWithSHA1 +{ + [self testWithHashClass: [OFSHA1Hash class] expectedDigest: SHA1Digest]; +} + +- (void)testHMACWithSHA256 +{ + [self testWithHashClass: [OFSHA256Hash class] + expectedDigest: SHA256Digest]; +} + +- (void)testHMACWithSHA384 +{ + [self testWithHashClass: [OFSHA384Hash class] + expectedDigest: SHA384Digest]; +} + +- (void)testHMACWithSHA512 +{ + [self testWithHashClass: [OFSHA512Hash class] + expectedDigest: SHA512Digest]; +} +@end ADDED tests/OFHTTPClientTests.m Index: tests/OFHTTPClientTests.m ================================================================== --- /dev/null +++ tests/OFHTTPClientTests.m @@ -0,0 +1,200 @@ +/* + * 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" + +#include +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFHTTPClientTests: OTTestCase +{ + OFHTTPResponse *_response; +} +@end + +@interface HTTPClientTestsServer: OFThread +{ + OFCondition *_condition; + uint16_t _port; +} + +@property (readonly, nonatomic) OFCondition *condition; +@property (readonly) uint16_t port; +@end + +@implementation OFHTTPClientTests +- (void)dealloc +{ + [_response release]; + + [super dealloc]; +} + +- (void)client: (OFHTTPClient *)client + wantsRequestBody: (OFStream *)body + request: (OFHTTPRequest *)request +{ + [body writeString: @"Hello"]; +} + +- (void)client: (OFHTTPClient *)client + didPerformRequest: (OFHTTPRequest *)request + response: (OFHTTPResponse *)response_ + exception: (id)exception +{ + OTAssertNil(exception); + + [_response release]; + _response = [response_ retain]; + + [[OFRunLoop mainRunLoop] stop]; +} + +- (void)testClient +{ + HTTPClientTestsServer *server; + OFIRI *IRI; + OFHTTPRequest *request; + OFHTTPClient *client; + OFData *data; + + server = [[[HTTPClientTestsServer alloc] init] autorelease]; + server.supportsSockets = true; + + [server.condition lock]; + + [server start]; + + [server.condition wait]; + [server.condition unlock]; + + IRI = [OFIRI IRIWithString: + [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo", + server.port]]; + + request = [OFHTTPRequest requestWithIRI: IRI]; + request.headers = [OFDictionary + dictionaryWithObject: @"5" + forKey: @"Content-Length"]; + + client = [OFHTTPClient client]; + client.delegate = self; + [client asyncPerformRequest: request]; + + [[OFRunLoop mainRunLoop] runUntilDate: + [OFDate dateWithTimeIntervalSinceNow: 2]]; + + OTAssertNotNil(_response); + OTAssertNotNil([_response.headers objectForKey: @"Content-Length"]); + + data = [_response readDataUntilEndOfStream]; + OTAssertEqual(data.count, 7); + OTAssertEqual(data.itemSize, 1); + OTAssertEqual(memcmp(data.items, "foo\nbar", 7), 0); + + OTAssertNil([server join]); +} +@end + +@implementation HTTPClientTestsServer +@synthesize condition = _condition, port = _port; + +- (instancetype)init +{ + self = [super init]; + + @try { + _condition = [[OFCondition alloc] init]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_condition release]; + + [super dealloc]; +} + +- (id)main +{ + OFTCPSocket *listener, *client; + OFSocketAddress address; + bool sawHost = false, sawContentLength = false, sawContentType = false; + bool sawUserAgent = false; + char buffer[5]; + + [_condition lock]; + + listener = [OFTCPSocket socket]; + address = [listener bindToHost: @"127.0.0.1" port: 0]; + _port = OFSocketAddressIPPort(&address); + [listener listen]; + + [_condition signal]; + [_condition unlock]; + client = [listener accept]; + + if (![[client readLine] isEqual: @"GET /foo HTTP/1.1"]) + return @"Wrong request"; + + for (size_t i = 0; i < 4; i++) { + OFString *line = [client readLine]; + + if ([line isEqual: [OFString stringWithFormat: + @"Host: 127.0.0.1:%" @PRIu16, _port]]) + sawHost = true; + else if ([line isEqual: @"Content-Length: 5"]) + sawContentLength = true; + if ([line isEqual: @"Content-Type: application/" + @"x-www-form-urlencoded; charset=UTF-8"]) + sawContentType = true; + else if ([line hasPrefix: @"User-Agent:"]) + sawUserAgent = true; + } + + if (!sawHost) + return @"Missing host"; + if (!sawContentLength) + return @"Missing content length"; + if (!sawContentType) + return @"Missing content type"; + if (!sawUserAgent) + return @"Missing user agent"; + + if (![[client readLine] isEqual: @""]) + return @"Missing empty line"; + + [client readIntoBuffer: buffer exactLength: 5]; + if (memcmp(buffer, "Hello", 5) != 0) + return @"Missing body"; + + [client writeString: @"HTTP/1.0 200 OK\r\n" + @"cONTeNT-lENgTH: 7\r\n" + @"\r\n" + @"foo\n" + @"bar"]; + [client close]; + + return nil; +} +@end ADDED tests/OFHTTPCookieManagerTests.m Index: tests/OFHTTPCookieManagerTests.m ================================================================== --- /dev/null +++ tests/OFHTTPCookieManagerTests.m @@ -0,0 +1,86 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFHTTPCookieManagerTests: OTTestCase +@end + +@implementation OFHTTPCookieManagerTests +- (void)testCookieManager +{ + OFHTTPCookieManager *manager = [OFHTTPCookieManager manager]; + OFIRI *IRI1, *IRI2, *IRI3, *IRI4; + OFHTTPCookie *cookie1, *cookie2, *cookie3, *cookie4, *cookie5; + + IRI1 = [OFIRI IRIWithString: @"http://nil.im/foo"]; + IRI2 = [OFIRI IRIWithString: @"https://nil.im/foo/bar"]; + IRI3 = [OFIRI IRIWithString: @"https://test.nil.im/foo/bar"]; + IRI4 = [OFIRI IRIWithString: @"http://webkeks.org/foo/bar"]; + + cookie1 = [OFHTTPCookie cookieWithName: @"test" + value: @"1" + domain: @"nil.im"]; + [manager addCookie: cookie1 forIRI: IRI1]; + OTAssertEqualObjects([manager cookiesForIRI: IRI1], + [OFArray arrayWithObject: cookie1]); + + cookie2 = [OFHTTPCookie cookieWithName: @"test" + value: @"2" + domain: @"webkeks.org"]; + [manager addCookie: cookie2 forIRI: IRI1]; + OTAssertEqualObjects([manager cookiesForIRI: IRI1], + [OFArray arrayWithObject: cookie1]); + OTAssertEqualObjects([manager cookiesForIRI: IRI4], [OFArray array]); + + cookie3 = [OFHTTPCookie cookieWithName: @"test" + value: @"3" + domain: @"nil.im"]; + cookie3.secure = true; + [manager addCookie: cookie3 forIRI: IRI2]; + OTAssertEqualObjects([manager cookiesForIRI: IRI2], + [OFArray arrayWithObject: cookie3]); + OTAssertEqualObjects([manager cookiesForIRI: IRI1], [OFArray array]); + + cookie3.expires = [OFDate dateWithTimeIntervalSinceNow: -1]; + cookie4 = [OFHTTPCookie cookieWithName: @"test" + value: @"4" + domain: @"nil.im"]; + cookie4.domain = @".nil.im"; + [manager addCookie: cookie4 forIRI: IRI2]; + OTAssertEqualObjects([manager cookiesForIRI: IRI2], + [OFArray arrayWithObject: cookie4]); + OTAssertEqualObjects([manager cookiesForIRI: IRI3], + [OFArray arrayWithObject: cookie4]); + + cookie5 = [OFHTTPCookie cookieWithName: @"bar" + value: @"5" + domain: @"test.nil.im"]; + [manager addCookie: cookie5 forIRI: IRI1]; + OTAssertEqualObjects([manager cookiesForIRI: IRI1], + [OFArray arrayWithObject: cookie4]); + OTAssertEqualObjects([manager cookiesForIRI: IRI3], + ([OFArray arrayWithObjects: cookie4, cookie5, nil])); + + OTAssertEqualObjects(manager.cookies, + ([OFArray arrayWithObjects: cookie3, cookie4, cookie5, nil])); + [manager purgeExpiredCookies]; + OTAssertEqualObjects(manager.cookies, + ([OFArray arrayWithObjects: cookie4, cookie5, nil])); +} +@end ADDED tests/OFHTTPCookieTests.m Index: tests/OFHTTPCookieTests.m ================================================================== --- /dev/null +++ tests/OFHTTPCookieTests.m @@ -0,0 +1,90 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFHTTPCookieTests: OTTestCase +@end + +@implementation OFHTTPCookieTests +- (void)testCookiesWithResponseHeaderFieldsForIRI +{ + OFIRI *IRI = [OFIRI IRIWithString: @"http://nil.im"]; + OFHTTPCookie *cookie1 = [OFHTTPCookie cookieWithName: @"foo" + value: @"bar" + domain: @"nil.im"]; + OFHTTPCookie *cookie2 = [OFHTTPCookie cookieWithName: @"qux" + value: @"cookie" + domain: @"nil.im"]; + OFDictionary *headers; + + headers = [OFDictionary dictionaryWithObject: @"foo=bar" + forKey: @"Set-Cookie"]; + OTAssertEqualObjects( + [OFHTTPCookie cookiesWithResponseHeaderFields: headers forIRI: IRI], + [OFArray arrayWithObject: cookie1]); + + headers = [OFDictionary dictionaryWithObject: @"foo=bar,qux=cookie" + forKey: @"Set-Cookie"]; + OTAssertEqualObjects( + [OFHTTPCookie cookiesWithResponseHeaderFields: headers forIRI: IRI], + ([OFArray arrayWithObjects: cookie1, cookie2, nil])); + + cookie1.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890]; + cookie2.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890]; + cookie1.path = @"/x"; + cookie2.domain = @"webkeks.org"; + cookie2.path = @"/objfw"; + cookie2.secure = true; + cookie2.HTTPOnly = true; + [cookie2.extensions addObject: @"foo"]; + [cookie2.extensions addObject: @"bar"]; + + headers = [OFDictionary + dictionaryWithObject: @"foo=bar; " + @"Expires=Fri, 13 Feb 2009 23:31:30 GMT; " + @"Path=/x," + @"qux=cookie; " + @"Expires=Fri, 13 Feb 2009 23:31:30 GMT; " + @"Domain=webkeks.org; " + @"Path=/objfw; " + @"Secure; " + @"HTTPOnly; " + @"foo; " + @"bar" + forKey: @"Set-Cookie"]; + OTAssertEqualObjects( + [OFHTTPCookie cookiesWithResponseHeaderFields: headers forIRI: IRI], + ([OFArray arrayWithObjects: cookie1, cookie2, nil])); +} + +- (void)testRequestHeaderFieldsWithCookies +{ + OFHTTPCookie *cookie1 = [OFHTTPCookie cookieWithName: @"foo" + value: @"bar" + domain: @"nil.im"]; + OFHTTPCookie *cookie2 = [OFHTTPCookie cookieWithName: @"qux" + value: @"cookie" + domain: @"nil.im"]; + + OTAssertEqualObjects([OFHTTPCookie requestHeaderFieldsWithCookies: + ([OFArray arrayWithObjects: cookie1, cookie2, nil])], + [OFDictionary dictionaryWithObject: @"foo=bar; qux=cookie" + forKey: @"Cookie"]); +} +@end ADDED tests/OFINIFileTests.m Index: tests/OFINIFileTests.m ================================================================== --- /dev/null +++ tests/OFINIFileTests.m @@ -0,0 +1,171 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFINIFileTests: OTTestCase +{ + OFINIFile *_file; +} +@end + +@implementation OFINIFileTests +- (void)setUp +{ + OFIRI *IRI; + + [super setUp]; + + IRI = [OFIRI IRIWithString: @"embedded:testfile.ini"]; + _file = [[OFINIFile alloc] initWithIRI: IRI + encoding: OFStringEncodingISO8859_1]; +} + +- (void)dealloc +{ + [_file release]; + + [super dealloc]; +} + +- (void)testCategoryForName +{ + OTAssertNotNil([_file categoryForName: @"tests"]); + OTAssertNotNil([_file categoryForName: @"foobar"]); + OTAssertNotNil([_file categoryForName: @"types"]); +} + +- (void)testStringValueForKey +{ + OTAssertEqualObjects( + [[_file categoryForName: @"tests"] stringValueForKey: @"foo"], + @"bar"); + + OTAssertEqualObjects([[_file categoryForName: @"foobar"] + stringValueForKey: @"quxquxqux"], + @"hello\"wörld"); +} + +- (void)testLongLongValueForKeyDefaultValue +{ + OTAssertEqual([[_file categoryForName: @"types"] + longLongValueForKey: @"integer" + defaultValue: 2], + 0x20); +} + +- (void)testBoolValueForKeyDefaultValue +{ + OTAssertTrue([[_file categoryForName: @"types"] + boolValueForKey: @"bool" + defaultValue: false]); +} + +- (void)testFloatValueForKeyDefaultValue +{ + OTAssertEqual([[_file categoryForName: @"types"] + floatValueForKey: @"float" + defaultValue: 1], + 0.5f); +} + +- (void)testDoubleValueForKeyDefaultValue +{ + OTAssertEqual([[_file categoryForName: @"types"] + doubleValueForKey: @"double" + defaultValue: 3], + 0.25); +} + +- (void)testArrayValueForKey +{ + OFINICategory *types = [_file categoryForName: @"types"]; + OFArray *array = [OFArray arrayWithObjects: @"1", @"2", nil]; + + OTAssertEqualObjects([types arrayValueForKey: @"array1"], array); + OTAssertEqualObjects([types arrayValueForKey: @"array2"], array); + OTAssertEqualObjects([types arrayValueForKey: @"array3"], + [OFArray array]); +} + +- (void)testWriteToIRIEncoding +{ + OFString *expectedOutput = @"[tests]\r\n" + @"foo=baz\r\n" + @"foobar=baz\r\n" + @";comment\r\n" + @"new=new\r\n" + @"\r\n" + @"[foobar]\r\n" + @";foobarcomment\r\n" + @"qux=\" asd\"\r\n" + @"quxquxqux=\"hello\\\"wörld\"\r\n" + @"qux2=\"a\\f\"\r\n" + @"qux3=a\fb\r\n" + @"\r\n" + @"[types]\r\n" + @"integer=16\r\n" + @"bool=false\r\n" + @"float=0.25\r\n" + @"array1=foo\r\n" + @"array1=bar\r\n" + @"double=0.75\r\n"; + OFINICategory *tests = [_file categoryForName: @"tests"]; + OFINICategory *foobar = [_file categoryForName: @"foobar"]; + OFINICategory *types = [_file categoryForName: @"types"]; + OFArray *array = [OFArray arrayWithObjects: @"foo", @"bar", nil]; +#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS) + OFIRI *writeIRI; +#endif + + [tests setStringValue: @"baz" forKey: @"foo"]; + [tests setStringValue: @"new" forKey: @"new"]; + [foobar setStringValue: @"a\fb" forKey: @"qux3"]; + [types setLongLongValue: 0x10 forKey: @"integer"]; + [types setBoolValue: false forKey: @"bool"]; + [types setFloatValue: 0.25f forKey: @"float"]; + [types setDoubleValue: 0.75 forKey: @"double"]; + [types setArrayValue: array forKey: @"array1"]; + + [foobar removeValueForKey: @"quxqux "]; + [types removeValueForKey: @"array2"]; + + /* FIXME: Find a way to write files on Nintendo DS */ +#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS) + writeIRI = [OFSystemInfo temporaryDirectoryIRI]; + if (writeIRI == nil) + writeIRI = [[OFFileManager defaultManager] currentDirectoryIRI]; + writeIRI = [writeIRI IRIByAppendingPathComponent: @"objfw-tests.ini" + isDirectory: false]; + + [_file writeToIRI: writeIRI + encoding: OFStringEncodingISO8859_1]; + + @try { + OTAssertEqualObjects([OFString + stringWithContentsOfIRI: writeIRI + encoding: OFStringEncodingISO8859_1], + expectedOutput); + } @finally { + [[OFFileManager defaultManager] removeItemAtIRI: writeIRI]; + } +#else + (void)expectedOutput; +#endif +} +@end ADDED tests/OFIPXSocketTests.m Index: tests/OFIPXSocketTests.m ================================================================== --- /dev/null +++ tests/OFIPXSocketTests.m @@ -0,0 +1,91 @@ +/* + * 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" + +#include +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFIPXSocketTests: OTTestCase +@end + +@implementation OFIPXSocketTests +- (void)testIPXSocket +{ + OFIPXSocket *sock = [OFIPXSocket socket]; + const unsigned char zeroNode[IPX_NODE_LEN] = { 0 }; + OFSocketAddress address1, address2; + OFDictionary *networkInterfaces; + char buffer[5]; + unsigned char node1[IPX_NODE_LEN], node2[IPX_NODE_LEN]; + unsigned char node[IPX_NODE_LEN]; + + @try { + address1 = [sock bindToNetwork: 0 + node: zeroNode + port: 0 + packetType: 0]; + } @catch (OFBindSocketFailedException *e) { + switch (e.errNo) { + case EAFNOSUPPORT: + OTSkip(@"IPX unsupported"); + case EADDRNOTAVAIL: + OTSkip(@"IPX not configured"); + default: + @throw e; + } + } + + /* + * Find any network interface with IPX and send to it. Any should be + * fine since we bound to 0.0. + */ + networkInterfaces = [OFSystemInfo networkInterfaces]; + for (OFString *name in networkInterfaces) { + OFNetworkInterface interface = [networkInterfaces + objectForKey: name]; + OFData *addresses = [interface + objectForKey: OFNetworkInterfaceIPXAddresses]; + + if (addresses.count == 0) + continue; + + OFSocketAddressSetIPXNetwork(&address1, + OFSocketAddressIPXNetwork([addresses itemAtIndex: 0])); + OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); + OFSocketAddressSetIPXNode(&address1, node); + } + + OFSocketAddressGetIPXNode(&address1, node); + if (OFSocketAddressIPXNetwork(&address1) == 0 && + memcmp(node, zeroNode, 6) == 0) + OTSkip(@"Could not determine own IPX address"); + + [sock sendBuffer: "Hello" length: 5 receiver: &address1]; + + OTAssertEqual([sock receiveIntoBuffer: buffer + length: 5 + sender: &address2], 5); + OTAssertEqual(memcmp(buffer, "Hello", 5), 0); + OFSocketAddressGetIPXNode(&address1, node1); + OFSocketAddressGetIPXNode(&address2, node2); + OTAssertEqual(memcmp(node1, node2, IPX_NODE_LEN), 0); + OTAssertEqual(OFSocketAddressIPXPort(&address1), + OFSocketAddressIPXPort(&address2)); +} +@end ADDED tests/OFIRITests.m Index: tests/OFIRITests.m ================================================================== --- /dev/null +++ tests/OFIRITests.m @@ -0,0 +1,539 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFIRITests: OTTestCase +{ + OFIRI *_IRI[11]; + OFMutableIRI *_mutableIRI; +} +@end + +static OFString *IRI0String = @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/" + @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment"; + +@implementation OFIRITests +- (void)setUp +{ + [super setUp]; + + _IRI[0] = [[OFIRI alloc] initWithString: IRI0String]; + _IRI[1] = [[OFIRI alloc] initWithString: @"http://foo:80"]; + _IRI[2] = [[OFIRI alloc] initWithString: @"http://bar/"]; + _IRI[3] = [[OFIRI alloc] initWithString: @"file:///etc/passwd"]; + _IRI[4] = [[OFIRI alloc] + initWithString: @"http://foo/bar/qux/foo%2fbar"]; + _IRI[5] = [[OFIRI alloc] initWithString: @"https://[12:34::56:abcd]/"]; + _IRI[6] = [[OFIRI alloc] + initWithString: @"https://[12:34::56:abcd]:234/"]; + _IRI[7] = [[OFIRI alloc] initWithString: @"urn:qux:foo"]; + _IRI[8] = [[OFIRI alloc] initWithString: @"file:/foo?query#frag"]; + _IRI[9] = [[OFIRI alloc] + initWithString: @"file:foo@bar/qux?query#frag"]; + _IRI[10] = [[OFIRI alloc] initWithString: @"http://ä/ö?ü"]; + + _mutableIRI = [[OFMutableIRI alloc] initWithScheme: @"dummy"]; +} + +- (void)dealloc +{ + for (uint_fast8_t i = 0; i < 11; i++) + [_IRI[i] release]; + + [_mutableIRI release]; + + [super dealloc]; +} + +- (void)testIRIWithStringFailsWithInvalidCharacters +{ + OTAssertThrowsSpecific([OFIRI IRIWithString: @"ht,tp://foo"], + OFInvalidFormatException); + + OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://f`oo"], + OFInvalidFormatException); + + OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://foo/`"], + OFInvalidFormatException); + + OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://foo/foo?`"], + OFInvalidFormatException); + + OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://foo/foo?foo#`"], + OFInvalidFormatException); + + OTAssertThrowsSpecific([OFIRI IRIWithString: @"https://[g]/"], + OFInvalidFormatException); + + OTAssertThrowsSpecific([OFIRI IRIWithString: @"https://[f]:/"], + OFInvalidFormatException); + + OTAssertThrowsSpecific([OFIRI IRIWithString: @"https://[f]:f/"], + OFInvalidFormatException); + + OTAssertThrowsSpecific([OFIRI IRIWithString: @"foo:"], + OFInvalidFormatException); +} + +- (void)testIRIWithStringRelativeToIRI +{ + OTAssertEqualObjects([[OFIRI IRIWithString: @"/foo" + relativeToIRI: _IRI[0]] string], + @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/foo"); + + OTAssertEqualObjects( + [[OFIRI IRIWithString: @"foo/bar?q" + relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/quux"]] + string], + @"http://h/qux/foo/bar?q"); + + OTAssertEqualObjects( + [[OFIRI IRIWithString: @"foo/bar" + relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/?x"]] + string], + @"http://h/qux/foo/bar"); + + OTAssertEqualObjects([[OFIRI IRIWithString: @"http://foo/?q" + relativeToIRI: _IRI[0]] string], + @"http://foo/?q"); + + OTAssertEqualObjects( + [[OFIRI IRIWithString: @"foo" + relativeToIRI: [OFIRI IRIWithString: @"http://foo/bar"]] + string], + @"http://foo/foo"); + + OTAssertEqualObjects( + [[OFIRI IRIWithString: @"foo" + relativeToIRI: [OFIRI IRIWithString: @"http://foo"]] + string], + @"http://foo/foo"); +} + +- (void)testIRIWithStringRelativeToIRIFailsWithInvalidCharacters +{ + OTAssertThrowsSpecific( + [OFIRI IRIWithString: @"`" relativeToIRI: _IRI[0]], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [OFIRI IRIWithString: @"/`" relativeToIRI: _IRI[0]], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [OFIRI IRIWithString: @"?`" relativeToIRI: _IRI[0]], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [OFIRI IRIWithString: @"#`" relativeToIRI: _IRI[0]], + OFInvalidFormatException); +} + +#ifdef OF_HAVE_FILES +- (void)testFileIRIWithPath +{ + OTAssertEqualObjects( + [[OFIRI fileIRIWithPath: @"testfile.txt"] fileSystemRepresentation], + [[OFFileManager defaultManager].currentDirectoryPath + stringByAppendingPathComponent: @"testfile.txt"]); +} + +# if defined(OF_WINDOWS) || defined(OF_MSDOS) +- (void)testFileIRWithPathC +{ + OFIRI *IRI = [OFIRI fileIRIWithPath: @"c:\\"]; + OTAssertEqualObjects(IRI.string, @"file:/c:/"); + OTAssertEqualObjects(IRI.fileSystemRepresentation, @"c:\\"); +} +# endif + +# ifdef OF_WINDOWS +- (void)testFileIRIWithPathUNC +{ + OFIRI *IRI; + + IRI = [OFIRI fileIRIWithPath: @"\\\\foo\\bar" isDirectory: false]; + OTAssertEqualObjects(IRI.host, @"foo"); + OTAssertEqualObjects(IRI.path, @"/bar"); + OTAssertEqualObjects(IRI.string, @"file://foo/bar"); + OTAssertEqualObjects(IRI.fileSystemRepresentation, @"\\\\foo\\bar"); + + IRI = [OFIRI fileIRIWithPath: @"\\\\test" isDirectory: true]; + OTAssertEqualObjects(IRI.host, @"test"); + OTAssertEqualObjects(IRI.path, @"/"); + OTAssertEqualObjects(IRI.string, @"file://test/"); + OTAssertEqualObjects(IRI.fileSystemRepresentation, @"\\\\test"); +} +# endif +#endif + +- (void)testString +{ + OTAssertEqualObjects(_IRI[0].string, IRI0String); + OTAssertEqualObjects(_IRI[1].string, @"http://foo:80"); + OTAssertEqualObjects(_IRI[2].string, @"http://bar/"); + OTAssertEqualObjects(_IRI[3].string, @"file:///etc/passwd"); + OTAssertEqualObjects(_IRI[4].string, @"http://foo/bar/qux/foo%2fbar"); + OTAssertEqualObjects(_IRI[5].string, @"https://[12:34::56:abcd]/"); + OTAssertEqualObjects(_IRI[6].string, @"https://[12:34::56:abcd]:234/"); + OTAssertEqualObjects(_IRI[7].string, @"urn:qux:foo"); + OTAssertEqualObjects(_IRI[8].string, @"file:/foo?query#frag"); + OTAssertEqualObjects(_IRI[9].string, @"file:foo@bar/qux?query#frag"); + OTAssertEqualObjects(_IRI[10].string, @"http://ä/ö?ü"); +} + +- (void)testScheme +{ + OTAssertEqualObjects(_IRI[0].scheme, @"ht+tp"); + OTAssertEqualObjects(_IRI[3].scheme, @"file"); + OTAssertEqualObjects(_IRI[8].scheme, @"file"); + OTAssertEqualObjects(_IRI[9].scheme, @"file"); + OTAssertEqualObjects(_IRI[10].scheme, @"http"); +} + +- (void)testUser +{ + OTAssertEqualObjects(_IRI[0].user, @"us:er"); + OTAssertNil(_IRI[3].user); + OTAssertNil(_IRI[9].user); + OTAssertNil(_IRI[10].user); +} + +- (void)testPassword +{ + OTAssertEqualObjects(_IRI[0].password, @"p@w"); + OTAssertNil(_IRI[3].password); + OTAssertNil(_IRI[9].password); + OTAssertNil(_IRI[10].password); +} + +- (void)testHost +{ + OTAssertEqualObjects(_IRI[0].host, @"ho:st"); + OTAssertEqualObjects(_IRI[5].host, @"12:34::56:abcd"); + OTAssertEqualObjects(_IRI[6].host, @"12:34::56:abcd"); + OTAssertNil(_IRI[7].host); + OTAssertNil(_IRI[8].host); + OTAssertNil(_IRI[9].host); + OTAssertEqualObjects(_IRI[10].host, @"ä"); +} + +- (void)testPort +{ + OTAssertEqual(_IRI[0].port.unsignedShortValue, 1234); + OTAssertNil(_IRI[3].port); + OTAssertEqual(_IRI[6].port.unsignedShortValue, 234); + OTAssertNil(_IRI[7].port); + OTAssertNil(_IRI[8].port); + OTAssertNil(_IRI[9].port); + OTAssertNil(_IRI[10].port); +} + +- (void)testPath +{ + OTAssertEqualObjects(_IRI[0].path, @"/pa?th"); + OTAssertEqualObjects(_IRI[3].path, @"/etc/passwd"); + OTAssertEqualObjects(_IRI[7].path, @"qux:foo"); + OTAssertEqualObjects(_IRI[8].path, @"/foo"); + OTAssertEqualObjects(_IRI[9].path, @"foo@bar/qux"); + OTAssertEqualObjects(_IRI[10].path, @"/ö"); +} + +- (void)testPathComponents +{ + OTAssertEqualObjects(_IRI[0].pathComponents, + ([OFArray arrayWithObjects: @"/", @"pa?th", nil])); + + OTAssertEqualObjects(_IRI[3].pathComponents, + ([OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil])); + + OTAssertEqualObjects(_IRI[4].pathComponents, + ([OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", + nil])); +} + +- (void)testLastPathComponent +{ + OTAssertEqualObjects([[OFIRI IRIWithString: @"http://host/foo//bar/baz"] + lastPathComponent], + @"baz"); + + OTAssertEqualObjects( + [[OFIRI IRIWithString: @"http://host/foo//bar/baz/"] + lastPathComponent], + @"baz"); + + OTAssertEqualObjects([[OFIRI IRIWithString: @"http://host/foo/"] + lastPathComponent], + @"foo"); + + OTAssertEqualObjects([[OFIRI IRIWithString: @"http://host/"] + lastPathComponent], + @"/"); + + OTAssertEqualObjects(_IRI[4].lastPathComponent, @"foo/bar"); +} + +- (void)testQuery +{ + OTAssertEqualObjects(_IRI[0].query, @"que#ry=1&f&oo=b=ar"); + OTAssertNil(_IRI[3].query); + OTAssertEqualObjects(_IRI[8].query, @"query"); + OTAssertEqualObjects(_IRI[9].query, @"query"); + OTAssertEqualObjects(_IRI[10].query, @"ü"); +} + +- (void)testQueryItems +{ + OTAssertEqualObjects(_IRI[0].queryItems, + ([OFArray arrayWithObjects: + [OFPair pairWithFirstObject: @"que#ry" secondObject: @"1"], + [OFPair pairWithFirstObject: @"f&oo" secondObject: @"b=ar"], nil])); +} + +- (void)testFragment +{ + OTAssertEqualObjects(_IRI[0].fragment, @"frag#ment"); + OTAssertNil(_IRI[3].fragment); + OTAssertEqualObjects(_IRI[8].fragment, @"frag"); + OTAssertEqualObjects(_IRI[9].fragment, @"frag"); +} + +- (void)testCopy +{ + OTAssertEqualObjects([[_IRI[0] copy] autorelease], _IRI[0]); +} + +- (void)testIsEqual +{ + OTAssertEqualObjects(_IRI[0], [OFIRI IRIWithString: IRI0String]); + OTAssertNotEqualObjects(_IRI[1], _IRI[2]); + OTAssertEqualObjects([OFIRI IRIWithString: @"HTTP://bar/"], _IRI[2]); +} + +- (void)testHash +{ + OTAssertEqual(_IRI[0].hash, [[OFIRI IRIWithString: IRI0String] hash]); + OTAssertNotEqual(_IRI[1].hash, _IRI[2].hash); +} + +- (void)testIRIWithStringFailsWithInvalidFormat +{ + OTAssertThrowsSpecific([OFIRI IRIWithString: @"http"], + OFInvalidFormatException); +} + +- (void)testIRIByAddingPercentEncodingForUnicodeCharacters +{ + OTAssertEqualObjects( + _IRI[10].IRIByAddingPercentEncodingForUnicodeCharacters, + [OFIRI IRIWithString: @"http://%C3%A4/%C3%B6?%C3%BC"]); +} + +- (void)testSetPercentEncodedSchemeFailsWithInvalidCharacters +{ + OTAssertThrowsSpecific(_mutableIRI.scheme = @"%20", + OFInvalidFormatException); +} + +- (void)testSetHost +{ + _mutableIRI.host = @"ho:st"; + OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"ho%3Ast"); + + _mutableIRI.host = @"12:34:ab"; + OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"[12:34:ab]"); + + _mutableIRI.host = @"12:34:aB"; + OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"[12:34:aB]"); + + _mutableIRI.host = @"12:34:g"; + OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"12%3A34%3Ag"); +} + +- (void)testSetPercentEncodedHost +{ + _mutableIRI.percentEncodedHost = @"ho%3Ast"; + OTAssertEqualObjects(_mutableIRI.host, @"ho:st"); + + _mutableIRI.percentEncodedHost = @"[12:34]"; + OTAssertEqualObjects(_mutableIRI.host, @"12:34"); + + _mutableIRI.percentEncodedHost = @"[12::ab]"; + OTAssertEqualObjects(_mutableIRI.host, @"12::ab"); +} + +- (void)testSetPercentEncodedHostFailsWithInvalidCharacters +{ + OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"/", + OFInvalidFormatException); + + OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"[12:34", + OFInvalidFormatException); + + OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"[a::g]", + OFInvalidFormatException); +} + +- (void)testSetUser +{ + _mutableIRI.user = @"us:er"; + OTAssertEqualObjects(_mutableIRI.percentEncodedUser, @"us%3Aer"); +} + +- (void)testSetPercentEncodedUser +{ + _mutableIRI.percentEncodedUser = @"us%3Aer"; + OTAssertEqualObjects(_mutableIRI.user, @"us:er"); +} + +- (void)testSetPercentEncodedUserFailsWithInvalidCharacters +{ + OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"/", + OFInvalidFormatException); +} + +- (void)testSetPassword +{ + _mutableIRI.password = @"pass:word"; + OTAssertEqualObjects(_mutableIRI.percentEncodedPassword, + @"pass%3Aword"); +} + +- (void)testSetPercentEncodedPassword +{ + _mutableIRI.percentEncodedPassword = @"pass%3Aword"; + OTAssertEqualObjects(_mutableIRI.password, @"pass:word"); +} + +- (void)testSetPercentEncodedPasswordFailsWithInvalidCharacters +{ + OTAssertThrowsSpecific(_mutableIRI.percentEncodedPassword = @"/", + OFInvalidFormatException); +} + +- (void)testSetPath +{ + _mutableIRI.path = @"pa/th@?"; + OTAssertEqualObjects(_mutableIRI.percentEncodedPath, @"pa/th@%3F"); +} + +- (void)testSetPercentEncodedPath +{ + _mutableIRI.percentEncodedPath = @"pa/th@%3F"; + OTAssertEqualObjects(_mutableIRI.path, @"pa/th@?"); +} + +- (void)testSetPercentEncodedPathFailsWithInvalidCharacters +{ + OTAssertThrowsSpecific(_mutableIRI.percentEncodedPath = @"?", + OFInvalidFormatException); +} + +- (void)testSetQuery +{ + _mutableIRI.query = @"que/ry?#"; + OTAssertEqualObjects(_mutableIRI.percentEncodedQuery, @"que/ry?%23"); +} + +- (void)testSetPercentEncodedQuery +{ + _mutableIRI.percentEncodedQuery = @"que/ry?%23"; + OTAssertEqualObjects(_mutableIRI.query, @"que/ry?#"); +} + +- (void)testSetPercentEncodedQueryFailsWithInvalidCharacters +{ + OTAssertThrowsSpecific(_mutableIRI.percentEncodedQuery = @"`", + OFInvalidFormatException); +} + +- (void)testSetQueryItems +{ + _mutableIRI.queryItems = [OFArray arrayWithObjects: + [OFPair pairWithFirstObject: @"foo&bar" secondObject: @"baz=qux"], + [OFPair pairWithFirstObject: @"f=oobar" secondObject: @"b&azqux"], + nil]; + OTAssertEqualObjects(_mutableIRI.percentEncodedQuery, + @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"); +} + +- (void)testSetFragment +{ + _mutableIRI.fragment = @"frag/ment?#"; + OTAssertEqualObjects(_mutableIRI.percentEncodedFragment, + @"frag/ment?%23"); +} + +- (void)testSetPercentEncodedFragment +{ + _mutableIRI.percentEncodedFragment = @"frag/ment?%23"; + OTAssertEqualObjects(_mutableIRI.fragment, @"frag/ment?#"); +} + +- (void)testSetPercentEncodedFragmentFailsWithInvalidCharacters +{ + OTAssertThrowsSpecific(_mutableIRI.percentEncodedFragment = @"`", + OFInvalidFormatException); +} + +-(void)testIRIByAppendingPathComponentIsDirectory +{ + OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar"] + IRIByAppendingPathComponent: @"qux" + isDirectory: false], + [OFIRI IRIWithString: @"file:///foo/bar/qux"]); + + OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar/"] + IRIByAppendingPathComponent: @"qux" + isDirectory: false], + [OFIRI IRIWithString: @"file:///foo/bar/qux"]); + + OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar/"] + IRIByAppendingPathComponent: @"qu?x" + isDirectory: false], + [OFIRI IRIWithString: @"file:///foo/bar/qu%3Fx"]); + + OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar/"] + IRIByAppendingPathComponent: @"qu?x" + isDirectory: true], + [OFIRI IRIWithString: @"file:///foo/bar/qu%3Fx/"]); +} + +- (void)testIRIByStandardizingPath +{ + OTAssertEqualObjects([[OFIRI IRIWithString: @"http://foo/bar/.."] + IRIByStandardizingPath], + [OFIRI IRIWithString: @"http://foo/"]); + + OTAssertEqualObjects( + [[OFIRI IRIWithString: @"http://foo/bar/%2E%2E/../qux/"] + IRIByStandardizingPath], + [OFIRI IRIWithString: @"http://foo/bar/qux/"]); + + OTAssertEqualObjects( + [[OFIRI IRIWithString: @"http://foo/bar/./././qux/./"] + IRIByStandardizingPath], + [OFIRI IRIWithString: @"http://foo/bar/qux/"]); + + OTAssertEqualObjects([[OFIRI IRIWithString: @"http://foo/bar/../../qux"] + IRIByStandardizingPath], + [OFIRI IRIWithString: @"http://foo/../qux"]); +} +@end ADDED tests/OFInvocationTests.m Index: tests/OFInvocationTests.m ================================================================== --- /dev/null +++ tests/OFInvocationTests.m @@ -0,0 +1,110 @@ +/* + * 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" + +#include + +#if defined(HAVE_COMPLEX_H) && !defined(__STDC_NO_COMPLEX__) +# include +#endif + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFInvocationTests: OTTestCase +{ + OFInvocation *_invocation; +} +@end + +struct TestStruct { + unsigned char c; + unsigned int i; +}; + +@implementation OFInvocationTests +- (struct TestStruct)invocationTestMethod1: (unsigned char)c + : (unsigned int)i + : (struct TestStruct *)testStructPtr + : (struct TestStruct)testStruct +{ + return testStruct; +} + +- (void)setUp +{ + [super setUp]; + + SEL selector = @selector(invocationTestMethod1::::); + OFMethodSignature *signature = + [self methodSignatureForSelector: selector]; + + _invocation = [[OFInvocation alloc] initWithMethodSignature: signature]; +} + +- (void)dealloc +{ + [_invocation release]; + + [super dealloc]; +} + +- (void)testSetAndGetReturnValue +{ + struct TestStruct testStruct, testStruct2; + + memset(&testStruct, 0xFF, sizeof(testStruct)); + testStruct.c = 0x55; + testStruct.i = 0xAAAAAAAA; + + [_invocation setReturnValue: &testStruct]; + [_invocation getReturnValue: &testStruct2]; + OTAssertEqual(memcmp(&testStruct, &testStruct2, sizeof(testStruct)), 0); +} + +- (void)testSetAndGetArgumentAtIndex +{ + struct TestStruct testStruct, testStruct2; + struct TestStruct *testStructPtr = &testStruct, *testStructPtr2; + unsigned const char c = 0xAA; + unsigned char c2; + const unsigned int i = 0x55555555; + unsigned int i2; + + memset(&testStruct, 0xFF, sizeof(testStruct)); + testStruct.c = 0x55; + testStruct.i = 0xAAAAAAAA; + + memset(&testStruct2, 0, sizeof(testStruct2)); + + [_invocation setArgument: &c atIndex: 2]; + [_invocation setArgument: &i atIndex: 3]; + [_invocation setArgument: &testStructPtr atIndex: 4]; + [_invocation setArgument: &testStruct atIndex: 5]; + + [_invocation getArgument: &c2 atIndex: 2]; + OTAssertEqual(c, c2); + + [_invocation getArgument: &i2 atIndex: 3]; + OTAssertEqual(i, i2); + + [_invocation getArgument: &testStructPtr2 atIndex: 4]; + OTAssertEqual(testStructPtr, testStructPtr2); + + [_invocation getArgument: &testStruct2 atIndex: 5]; + OTAssertEqual(memcmp(&testStruct, &testStruct2, sizeof(testStruct)), 0); +} +@end ADDED tests/OFJSONTests.m Index: tests/OFJSONTests.m ================================================================== --- /dev/null +++ tests/OFJSONTests.m @@ -0,0 +1,126 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFJSONTests: OTTestCase +{ + OFDictionary *_dictionary; +} +@end + +static OFString *string = @"{\"foo\"\t:'b\\na\\r', \"x\":/*foo*/ [.5\r,0xF," + @"null//bar\n,\"foo\",false]}"; + +@implementation OFJSONTests +- (void)setUp +{ + [super setUp]; + + _dictionary = [[OTOrderedDictionary alloc] initWithKeysAndObjects: + @"foo", @"b\na\r", + @"x", [OFArray arrayWithObjects: + [OFNumber numberWithFloat: .5f], + [OFNumber numberWithInt: 0xF], + [OFNull null], + @"foo", + [OFNumber numberWithBool: false], + nil], + nil]; +} + +- (void)dealloc +{ + [_dictionary release]; + + [super dealloc]; +} + +- (void)testObjectByParsingJSON +{ + OTAssertEqualObjects(string.objectByParsingJSON, _dictionary); +} + +- (void)testJSONRepresentation +{ + OTAssert(_dictionary.JSONRepresentation, + @"{\"foo\":\"b\\na\\r\",\"x\":[0.5,15,null,\"foo\",false]}"); +} + +- (void)testPrettyJSONRepresentation +{ + OTAssertEqualObjects([_dictionary JSONRepresentationWithOptions: + OFJSONRepresentationOptionPretty], + @"{\n\t\"foo\": \"b\\na\\r\",\n\t\"x\": [\n\t\t0.5,\n\t\t15," + @"\n\t\tnull,\n\t\t\"foo\",\n\t\tfalse\n\t]\n}"); +} + +- (void)testJSON5Representation +{ + OTAssertEqualObjects([_dictionary JSONRepresentationWithOptions: + OFJSONRepresentationOptionJSON5], + @"{foo:\"b\\\na\\r\",x:[0.5,15,null,\"foo\",false]}"); +} + +- (void)testObjectByParsingJSONFailsWithInvalidJSON +{ + OTAssertThrowsSpecific([@"{" objectByParsingJSON], + OFInvalidJSONException); + + OTAssertThrowsSpecific([@"]" objectByParsingJSON], + OFInvalidJSONException); + + OTAssertThrowsSpecific([@"bar" objectByParsingJSON], + OFInvalidJSONException); + + OTAssertThrowsSpecific([@"[\"a\" \"b\"]" objectByParsingJSON], + OFInvalidJSONException); +} + +- (void)testObjectByParsingJSONWithDeepNesting +{ + OTAssertEqualObjects( + @"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" + .objectByParsingJSON, + [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: [OFArray arrayWithObject: + [OFArray arrayWithObject: + [OFDictionary dictionary]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]); +} + +- (void)testObjectByParsingJSONFailsWithTooDeepNesting +{ + OTAssertThrowsSpecific( + [@"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" + objectByParsingJSON], + OFInvalidJSONException); +} +@end ADDED tests/OFKernelEventObserverTests.m Index: tests/OFKernelEventObserverTests.m ================================================================== --- /dev/null +++ tests/OFKernelEventObserverTests.m @@ -0,0 +1,155 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +#ifdef HAVE_KQUEUE +# import "OFKqueueKernelEventObserver.h" +#endif +#ifdef HAVE_EPOLL +# import "OFEpollKernelEventObserver.h" +#endif +#ifdef HAVE_POLL +# import "OFPollKernelEventObserver.h" +#endif +#ifdef HAVE_SELECT +# import "OFSelectKernelEventObserver.h" +#endif + +@interface OFKernelEventObserverTests: OTTestCase + +{ + OFTCPSocket *_server, *_client, *_accepted; + OFKernelEventObserver *_observer; + size_t _events; +} +@end + +static const size_t numExpectedEvents = 3; + +@implementation OFKernelEventObserverTests +- (void)setUp +{ + OFSocketAddress address; + + [super setUp]; + + _server = [[OFTCPSocket alloc] init]; + address = [_server bindToHost: @"127.0.0.1" port: 0]; + [_server listen]; + + _client = [[OFTCPSocket alloc] init]; + [_client connectToHost: @"127.0.0.1" + port: OFSocketAddressIPPort(&address)]; + [_client writeBuffer: "0" length: 1]; +} + +- (void)dealloc +{ + [_client release]; + [_server release]; + [_accepted release]; + + [super dealloc]; +} + +- (void)testKernelEventObserverWithClass: (Class)class +{ + bool deadlineExceeded = false; + OFDate *deadline; + + _observer = [[class alloc] init]; + _observer.delegate = self; + [_observer addObjectForReading: _server]; + + deadline = [OFDate dateWithTimeIntervalSinceNow: 1]; + + while (_events < numExpectedEvents) { + if (deadline.timeIntervalSinceNow < 0) { + deadlineExceeded = true; + break; + } + + [_observer observeForTimeInterval: 0.01]; + } + + OTAssertFalse(deadlineExceeded); + OTAssertEqual(_events, numExpectedEvents); +} + +- (void)objectIsReadyForReading: (id)object +{ + char buffer; + + switch (_events++) { + case 0: + OTAssertEqual(object, _server); + + _accepted = [[object accept] retain]; + [_observer addObjectForReading: _accepted]; + break; + case 1: + OTAssert(object, _accepted); + + OTAssertEqual([object readIntoBuffer: &buffer length: 1], 1); + OTAssertEqual(buffer, '0'); + + [_client close]; + break; + case 2: + OTAssertEqual(object, _accepted); + + OTAssertEqual([object readIntoBuffer: &buffer length: 1], 0); + break; + default: + OTAssert(false); + } +} + +#ifdef HAVE_SELECT +- (void)testSelectKernelEventObserver +{ + [self testKernelEventObserverWithClass: + [OFSelectKernelEventObserver class]]; +} +#endif + +#ifdef HAVE_POLL +- (void)testPollKernelEventObserver +{ + [self testKernelEventObserverWithClass: + [OFPollKernelEventObserver class]]; +} +#endif + +#ifdef HAVE_EPOLL +- (void)testEpollKernelEventObserver +{ + [self testKernelEventObserverWithClass: + [OFEpollKernelEventObserver class]]; +} +#endif + +#ifdef HAVE_KQUEUE +- (void)testKqueueKernelEventObserver +{ + [self testKernelEventObserverWithClass: + [OFKqueueKernelEventObserver class]]; +} +#endif +@end ADDED tests/OFListTests.m Index: tests/OFListTests.m ================================================================== --- /dev/null +++ tests/OFListTests.m @@ -0,0 +1,277 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFListTests: OTTestCase +{ + OFList *_list; +} +@end + +@implementation OFListTests +- (void)setUp +{ + [super setUp]; + + _list = [[OFList alloc] init]; + [_list appendObject: @"Foo"]; + [_list appendObject: @"Bar"]; + [_list appendObject: @"Baz"]; +} + +- (void)dealloc +{ + [_list release]; + + [super dealloc]; +} + +- (void)testCount +{ + OTAssertEqual(_list.count, 3); +} + +- (void)testAppendObject +{ + OFListItem item; + + [_list appendObject: @"Qux"]; + + item = _list.firstListItem; + OTAssertEqualObjects(OFListItemObject(item), @"Foo"); + + item = OFListItemNext(item); + OTAssertEqualObjects(OFListItemObject(item), @"Bar"); + + item = OFListItemNext(item); + OTAssertEqualObjects(OFListItemObject(item), @"Baz"); + + item = OFListItemNext(item); + OTAssertEqualObjects(OFListItemObject(item), @"Qux"); + + item = OFListItemNext(item); + OTAssertEqual(item, NULL); +} + +- (void)testFirstListItem +{ + OTAssertEqualObjects(OFListItemObject(_list.firstListItem), @"Foo"); +} + +- (void)testFirstObject +{ + OTAssertEqualObjects(_list.firstObject, @"Foo"); +} + +- (void)testLastListItem +{ + OTAssertEqualObjects(OFListItemObject(_list.lastListItem), @"Baz"); +} + +- (void)testLastObject +{ + OTAssertEqualObjects(_list.lastObject, @"Baz"); +} + +- (void)testListItemNext +{ + OTAssertEqualObjects( + OFListItemObject(OFListItemNext(_list.firstListItem)), @"Bar"); +} + +- (void)testListItemPrevious +{ + OTAssertEqualObjects( + OFListItemObject(OFListItemPrevious(_list.lastListItem)), @"Bar"); +} + +- (void)testRemoveListItem +{ + OFListItem item; + + [_list removeListItem: OFListItemNext(_list.firstListItem)]; + + item = _list.firstListItem; + OTAssertEqualObjects(OFListItemObject(item), @"Foo"); + + item = OFListItemNext(item); + OTAssertEqualObjects(OFListItemObject(item), @"Baz"); + + item = OFListItemNext(item); + OTAssertEqual(item, NULL); +} + +- (void)testInsertObjectBeforeListItem +{ + OFListItem item; + + [_list insertObject: @"Qux" beforeListItem: _list.lastListItem]; + + item = _list.firstListItem; + OTAssertEqualObjects(OFListItemObject(item), @"Foo"); + + item = OFListItemNext(item); + OTAssertEqualObjects(OFListItemObject(item), @"Bar"); + + item = OFListItemNext(item); + OTAssertEqualObjects(OFListItemObject(item), @"Qux"); + + item = OFListItemNext(item); + OTAssertEqualObjects(OFListItemObject(item), @"Baz"); + + item = OFListItemNext(item); + OTAssertEqual(item, NULL); +} + +- (void)testInsertObjectAfterListItem +{ + OFListItem item; + + [_list insertObject: @"Qux" afterListItem: _list.firstListItem]; + + item = _list.firstListItem; + OTAssertEqualObjects(OFListItemObject(item), @"Foo"); + + item = OFListItemNext(item); + OTAssertEqualObjects(OFListItemObject(item), @"Qux"); + + item = OFListItemNext(item); + OTAssertEqualObjects(OFListItemObject(item), @"Bar"); + + item = OFListItemNext(item); + OTAssertEqualObjects(OFListItemObject(item), @"Baz"); + + item = OFListItemNext(item); + OTAssertEqual(item, NULL); +} + +- (void)testContainsObject +{ + OTAssertTrue([_list containsObject: @"Foo"]); + OTAssertFalse([_list containsObject: @"Qux"]); +} + +- (void)testContainsObjectIdenticalTo +{ + OFString *foo = _list.firstObject; + + OTAssertTrue([_list containsObjectIdenticalTo: foo]); + OTAssertFalse( + [_list containsObjectIdenticalTo: [[foo mutableCopy] autorelease]]); +} + +- (void)testIsEqual +{ + OFList *list = [OFList list]; + + [list appendObject: @"Foo"]; + [list appendObject: @"Bar"]; + [list appendObject: @"Baz"]; + + OTAssertEqualObjects(list, _list); + + [list appendObject: @"Qux"]; + + OTAssertNotEqualObjects(list, _list); +} + +- (void)testHash +{ + OFList *list = [OFList list]; + + [list appendObject: @"Foo"]; + [list appendObject: @"Bar"]; + [list appendObject: @"Baz"]; + + OTAssertEqual(list.hash, _list.hash); + + [list appendObject: @"Qux"]; + + OTAssertNotEqual(list.hash, _list.hash); +} + +- (void)testCopy +{ + OTAssertEqualObjects([[_list copy] autorelease], _list); +} + +- (void)testDescription +{ + OTAssertEqualObjects(_list.description, @"[\n\tFoo,\n\tBar,\n\tBaz\n]"); +} + +- (void)testEnumerator +{ + OFEnumerator *enumerator = [_list objectEnumerator]; + + OTAssertEqualObjects([enumerator nextObject], @"Foo"); + OTAssertEqualObjects([enumerator nextObject], @"Bar"); + OTAssertEqualObjects([enumerator nextObject], @"Baz"); + OTAssertNil([enumerator nextObject]); +} + +- (void)testDetectMutationDuringEnumeration +{ + OFEnumerator *enumerator = [_list objectEnumerator]; + + [_list removeListItem: _list.firstListItem]; + + OTAssertThrowsSpecific([enumerator nextObject], + OFEnumerationMutationException); +} + +- (void)testFastEnumeration +{ + size_t i = 0; + + for (OFString *object in _list) { + OTAssertLessThan(i, 3); + + switch (i++) { + case 0: + OTAssertEqualObjects(object, @"Foo"); + break; + case 1: + OTAssertEqualObjects(object, @"Bar"); + break; + case 2: + OTAssertEqualObjects(object, @"Baz"); + break; + } + } + + OTAssertEqual(i, 3); +} + +- (void)testDetectMutationDuringFastEnumeration +{ + bool detected = false; + + @try { + for (OFString *object in _list) { + (void)object; + [_list removeListItem: _list.firstListItem]; + } + } @catch (OFEnumerationMutationException *e) { + detected = true; + } + + OTAssertTrue(detected); +} +@end ADDED tests/OFLocaleTests.m Index: tests/OFLocaleTests.m ================================================================== --- /dev/null +++ tests/OFLocaleTests.m @@ -0,0 +1,42 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFLocaleTests: OTTestCase +@end + +@implementation OFLocaleTests ++ (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, id) *) *)summary +{ + OFMutableArray *summary = [OFMutableArray array]; + +#define ADD(name, value) \ + [summary addObject: [OFPair pairWithFirstObject: name \ + secondObject: value]]; + + ADD(@"Language code", [OFLocale languageCode]) + ADD(@"Country code", [OFLocale countryCode]) + ADD(@"Encoding", OFStringEncodingName([OFLocale encoding])) + ADD(@"Decimal separator", [OFLocale decimalSeparator]) + +#undef ADD + + return summary; +} +@end ADDED tests/OFMatrix4x4Tests.m Index: tests/OFMatrix4x4Tests.m ================================================================== --- /dev/null +++ tests/OFMatrix4x4Tests.m @@ -0,0 +1,165 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFMatrix4x4Tests: OTTestCase +{ + OFMatrix4x4 *_matrix; +} +@end + +@implementation OFMatrix4x4Tests +- (void)setUp +{ + [super setUp]; + + _matrix = [[OFMatrix4x4 alloc] initWithValues: (const float [4][4]){ + { 1, 2, 3, 4 }, + { 5, 6, 7, 8 }, + { 9, 10, 11, 12 }, + { 13, 14, 15, 16 } + }]; +} + +- (void)dealloc +{ + [_matrix release]; + + [super dealloc]; +} + +- (void)testIdentityMatrix +{ + OTAssertEqual(memcmp([[OFMatrix4x4 identityMatrix] values], + (const float [4][4]){ + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } + }, 16 * sizeof(float)), + 0); +} + +- (void)testDescription +{ + OTAssertEqualObjects(_matrix.description, + @""); +} + +- (void)testIsEqual +{ + OTAssertEqualObjects([OFMatrix4x4 identityMatrix], + ([OFMatrix4x4 matrixWithValues: (const float [4][4]){ + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } + }])); +} + +- (void)testHash +{ + OTAssertEqual([[OFMatrix4x4 identityMatrix] hash], + [([OFMatrix4x4 matrixWithValues: (const float [4][4]){ + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } + }]) hash]); +} + +- (void)testCopy +{ + OTAssertEqualObjects([[_matrix copy] autorelease], _matrix); +} + +- (void)testMultiplyWithMatrix +{ + OFMatrix4x4 *matrix; + + matrix = [[_matrix copy] autorelease]; + [matrix multiplyWithMatrix: [OFMatrix4x4 identityMatrix]]; + OTAssertEqualObjects(matrix, _matrix); + + matrix = [OFMatrix4x4 matrixWithValues: (const float [4][4]){ + { 100, 200, 300, 400 }, + { 500, 600, 700, 800 }, + { 900, 1000, 1100, 1200 }, + { 1300, 1400, 1500, 1600 } + }]; + [matrix multiplyWithMatrix: _matrix]; + OTAssertEqualObjects(matrix, + ([OFMatrix4x4 matrixWithValues: (const float [4][4]){ + { 9000, 10000, 11000, 12000 }, + { 20200, 22800, 25400, 28000 }, + { 31400, 35600, 39800, 44000 }, + { 42600, 48400, 54200, 60000 } + }])); +} + +- (void)testTranslateWithVector +{ + OFMatrix4x4 *matrix = [OFMatrix4x4 identityMatrix]; + OFVector4D point; + + [matrix translateWithVector: OFMakeVector3D(1, 2, 3)]; + + point = [matrix transformedVector: OFMakeVector4D(2, 3, 4, 1)]; + OTAssertEqual(point.x, 3); + OTAssertEqual(point.y, 5); + OTAssertEqual(point.z, 7); + OTAssertEqual(point.w, 1); +} + +- (void)testScaleWithVector +{ + OFMatrix4x4 *matrix = [OFMatrix4x4 identityMatrix]; + OFVector4D point; + + [matrix translateWithVector: OFMakeVector3D(1, 2, 3)]; + [matrix scaleWithVector: OFMakeVector3D(-1, 0.5f, 2)]; + + point = [matrix transformedVector: OFMakeVector4D(2, 3, 4, 1)]; + OTAssertEqual(point.x, -3); + OTAssertEqual(point.y, 2.5); + OTAssertEqual(point.z, 14); + OTAssertEqual(point.w, 1); +} + +- (void)testTransformVectorsCount +{ + OFVector4D points[2] = {{ 1, 2, 3, 1 }, { 7, 8, 9, 2 }}; + + [_matrix transformVectors: points count: 2]; + + OTAssertEqual(points[0].x, 18); + OTAssertEqual(points[0].y, 46); + OTAssertEqual(points[0].z, 74); + OTAssertEqual(points[0].w, 102); + OTAssertEqual(points[1].x, 58); + OTAssertEqual(points[1].y, 162); + OTAssertEqual(points[1].z, 266); + OTAssertEqual(points[1].w, 370); +} +@end ADDED tests/OFMemoryStreamTests.m Index: tests/OFMemoryStreamTests.m ================================================================== --- /dev/null +++ tests/OFMemoryStreamTests.m @@ -0,0 +1,85 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFMemoryStreamTests: OTTestCase +@end + +static const char string[] = "abcdefghijkl"; + +@implementation OFMemoryStreamTests +- (void)testReadOnlyMemoryStream +{ + OFMemoryStream *stream = [OFMemoryStream + streamWithMemoryAddress: (char *)string + size: sizeof(string) + writable: false]; + char buffer[10]; + + /* + * Test the lowlevel methods, as otherwise OFStream will do one big + * read and we will not test OFMemoryStream. + */ + + OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 5], 5); + OTAssertEqual(memcmp(buffer, "abcde", 5), 0); + OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 3], 3); + OTAssertEqual(memcmp(buffer, "fgh", 3), 0); + OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 10], 5); + OTAssertEqual(memcmp(buffer, "ijkl", 5), 0); + OTAssertTrue([stream lowlevelIsAtEndOfStream]); + + OTAssertEqual([stream lowlevelSeekToOffset: 0 whence: OFSeekCurrent], + sizeof(string)); + OTAssertTrue([stream lowlevelIsAtEndOfStream]); + + OTAssertEqual([stream lowlevelSeekToOffset: 4 whence: OFSeekSet], 4); + OTAssertFalse([stream lowlevelIsAtEndOfStream]); + OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 10], 9); + OTAssertEqual(memcmp(buffer, "efghijkl", 9), 0); + + OTAssertEqual([stream lowlevelSeekToOffset: -2 whence: OFSeekEnd], 11); + OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 10], 2); + OTAssertEqual(memcmp(buffer, "l", 2), 0); + OTAssertEqual([stream lowlevelReadIntoBuffer: buffer length: 10], 0); + + OTAssertThrowsSpecific([stream lowlevelWriteBuffer: "" length: 1], + OFWriteFailedException); +} + +- (void)testReadWriteMemoryStream +{ + OFMutableData *data = [OFMutableData dataWithCapacity: 13]; + OFMemoryStream *stream; + + [data increaseCountBy: 13]; + stream = [OFMemoryStream streamWithMemoryAddress: data.mutableItems + size: data.count + writable: true]; + + OTAssertEqual([stream lowlevelWriteBuffer: "abcde" length: 5], 5); + OTAssertEqual([stream lowlevelWriteBuffer: "fgh" length: 3], 3); + OTAssertEqual([stream lowlevelWriteBuffer: "ijkl" length: 5], 5); + OTAssertEqual(memcmp(data.items, string, data.count), 0); + OTAssertEqual([stream lowlevelSeekToOffset: -3 whence: OFSeekEnd], 10); + + OTAssertThrowsSpecific([stream lowlevelWriteBuffer: "xyz" length: 4], + OFWriteFailedException); +} +@end ADDED tests/OFMethodSignatureTests.m Index: tests/OFMethodSignatureTests.m ================================================================== --- /dev/null +++ tests/OFMethodSignatureTests.m @@ -0,0 +1,174 @@ +/* + * 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" + +#include + +#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) +# include +#endif + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFMethodSignatureTests: OTTestCase +@end + +struct Test1Struct { + char c; + int i; + char d; +}; + +struct Test2Struct { + char c; + struct { + short s; + int i; + } st; + union { + char c; + int i; + } u; + double d; +}; + +#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) +struct Test3Struct { + char c; + complex double cd; +}; +#endif + +union Test3Union { + char c; + int i; + double d; +}; + +union Test4Union { + char c; + struct { + short x, y; + } st; + int i; + union { + float f; + double d; + } u; +}; + +@implementation OFMethodSignatureTests +- (void)testSignatureWithObjCTypes +{ + OFMethodSignature *methodSignature; + + methodSignature = + [OFMethodSignature signatureWithObjCTypes: "i28@0:8S16*20"]; + OTAssertEqual(methodSignature.numberOfArguments, 4); + OTAssertEqual(strcmp(methodSignature.methodReturnType, "i"), 0); + OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 0], "@"), 0); + OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 1], ":"), 0); + OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 2], "S"), 0); + OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 3], "*"), 0); + OTAssertEqual(methodSignature.frameLength, 28); + OTAssertEqual([methodSignature argumentOffsetAtIndex: 0], 0); + OTAssertEqual([methodSignature argumentOffsetAtIndex: 1], 8); + OTAssertEqual([methodSignature argumentOffsetAtIndex: 2], 16); + OTAssertEqual([methodSignature argumentOffsetAtIndex: 3], 20); + + methodSignature = [OFMethodSignature signatureWithObjCTypes: + "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}24@0:8" + "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}16"]; + OTAssertEqual(methodSignature.numberOfArguments, 3); + OTAssertEqual(strcmp(methodSignature.methodReturnType, + "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}"), 0); + OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 0], "@"), 0); + OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 1], ":"), 0); + OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 2], + "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}"), 0); + OTAssertEqual(methodSignature.frameLength, 24); + OTAssertEqual([methodSignature argumentOffsetAtIndex: 0], 0); + OTAssertEqual([methodSignature argumentOffsetAtIndex: 1], 8); + OTAssertEqual([methodSignature argumentOffsetAtIndex: 2], 16); +} + +- (void)testSignatureWithObjCTypesFailsWithInvalidFormat +{ + OTAssertThrowsSpecific( + [OFMethodSignature signatureWithObjCTypes: "{ii"], + OFInvalidFormatException); + + OTAssertThrowsSpecific([OFMethodSignature signatureWithObjCTypes: ""], + OFInvalidFormatException); + + OTAssertThrowsSpecific([OFMethodSignature signatureWithObjCTypes: "0"], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [OFMethodSignature signatureWithObjCTypes: "{{}0"], + OFInvalidFormatException); +} + +- (void)testSizeOfTypeEncoding +{ + OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test1Struct)), + sizeof(struct Test1Struct)); + + OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test2Struct)), + sizeof(struct Test2Struct)); + +#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \ + OF_GCC_VERSION >= 402 + OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test3Struct)), + sizeof(struct Test3Struct)); +#endif + + OTAssertEqual(OFSizeOfTypeEncoding(@encode(union Test3Union)), + sizeof(union Test3Union)); + + OTAssertEqual(OFSizeOfTypeEncoding(@encode(union Test4Union)), + sizeof(union Test4Union)); + + OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test1Struct [5])), + sizeof(struct Test1Struct [5])); +} + +- (void)testAlignmentOfTypeEncoding +{ + OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test1Struct)), + OF_ALIGNOF(struct Test1Struct)); + + OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test2Struct)), + OF_ALIGNOF(struct Test2Struct)); + +#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \ + OF_GCC_VERSION >= 402 + OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test3Struct)), + OF_ALIGNOF(struct Test3Struct)); +#endif + + OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(union Test3Union)), + OF_ALIGNOF(union Test3Union)); + + OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(union Test4Union)), + OF_ALIGNOF(union Test4Union)); + + OTAssertEqual( + OFAlignmentOfTypeEncoding(@encode(struct Test1Struct [5])), + OF_ALIGNOF(struct Test1Struct [5])); +} +@end ADDED tests/OFMutableArrayTests.h Index: tests/OFMutableArrayTests.h ================================================================== --- /dev/null +++ tests/OFMutableArrayTests.h @@ -0,0 +1,22 @@ +/* + * 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 "OFArrayTests.h" + +@interface OFMutableArrayTests: OFArrayTests +{ + OFMutableArray *_mutableArray; +} +@end ADDED tests/OFMutableArrayTests.m Index: tests/OFMutableArrayTests.m ================================================================== --- /dev/null +++ tests/OFMutableArrayTests.m @@ -0,0 +1,223 @@ +/* + * 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 "OFMutableArrayTests.h" + +#import "OFArray+Private.h" + +@interface CustomMutableArray: OFMutableArray +{ + OFMutableArray *_array; +} +@end + +static OFString *const cArray[] = { + @"Foo", + @"Bar", + @"Baz" +}; + +@implementation OFMutableArrayTests +- (Class)arrayClass +{ + return [CustomMutableArray class]; +} + +- (void)setUp +{ + [super setUp]; + + _mutableArray = [[self.arrayClass alloc] + initWithObjects: cArray + count: sizeof(cArray) / sizeof(*cArray)]; +} + +- (void)dealloc +{ + [_mutableArray release]; + + [super dealloc]; +} + +- (void)testAddObject +{ + [_mutableArray addObject: cArray[0]]; + [_mutableArray addObject: cArray[2]]; + + OTAssertEqualObjects(_mutableArray, + ([OFArray arrayWithObjects: @"Foo", @"Bar", @"Baz", @"Foo", @"Baz", + nil])); +} + +- (void)testInsertObjectAtIndex +{ + [_mutableArray insertObject: cArray[1] atIndex: 1]; + + OTAssertEqualObjects(_mutableArray, + ([OFArray arrayWithObjects: @"Foo", @"Bar", @"Bar", @"Baz", nil])); +} + +- (void)testReplaceObjectWithObject +{ + [_mutableArray insertObject: cArray[1] atIndex: 1]; + [_mutableArray replaceObject: cArray[1] withObject: cArray[0]]; + + OTAssertEqualObjects(_mutableArray, + ([OFArray arrayWithObjects: @"Foo", @"Foo", @"Foo", @"Baz", nil])); +} + +- (void)testReplaceObjectIdenticalToWithObject +{ + [_mutableArray insertObject: [[cArray[1] mutableCopy] autorelease] + atIndex: 1]; + [_mutableArray replaceObjectIdenticalTo: cArray[1] + withObject: cArray[0]]; + + OTAssertEqualObjects(_mutableArray, + ([OFArray arrayWithObjects: @"Foo", @"Bar", @"Foo", @"Baz", nil])); +} + +- (void)testReplaceObjectAtIndexWithObject +{ + [_mutableArray replaceObjectAtIndex: 1 + withObject: cArray[0]]; + + OTAssertEqualObjects(_mutableArray, + ([OFArray arrayWithObjects: @"Foo", @"Foo", @"Baz", nil])); +} + +- (void)testRemoveObject +{ + [_mutableArray removeObject: cArray[1]]; + + OTAssertEqualObjects(_mutableArray, + ([OFArray arrayWithObjects: @"Foo", @"Baz", nil])); +} + +- (void)testRemoveObjectIdenticalTo +{ + [_mutableArray removeObjectIdenticalTo: cArray[1]]; + + OTAssertEqualObjects(_mutableArray, + ([OFArray arrayWithObjects: @"Foo", @"Baz", nil])); +} + +- (void)testRemoveObjectAtIndex +{ + [_mutableArray removeObjectAtIndex: 1]; + + OTAssertEqualObjects(_mutableArray, + ([OFArray arrayWithObjects: @"Foo", @"Baz", nil])); +} + +- (void)testRemoveObjectsInRange +{ + [_mutableArray removeObjectsInRange: OFMakeRange(1, 2)]; + + OTAssertEqualObjects(_mutableArray, [OFArray arrayWithObject: @"Foo"]); +} + +- (void)testRemoveObjectsInRangeFailsWhenOutOfRange +{ + OTAssertThrowsSpecific([_mutableArray removeObjectsInRange: + OFMakeRange(0, _mutableArray.count + 1)], OFOutOfRangeException); +} + +- (void)testReverse +{ + [_mutableArray reverse]; + + OTAssertEqualObjects(_mutableArray, + ([OFArray arrayWithObjects: @"Baz", @"Bar", @"Foo", nil])); +} + +#ifdef OF_HAVE_BLOCKS +- (void)testReplaceObjectsUsingBlock +{ + [_mutableArray replaceObjectsUsingBlock: ^ id (id object, size_t idx) { + return [object lowercaseString]; + }]; + + OTAssertEqualObjects(_mutableArray, + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); +} +#endif + +- (void)testSetValueForKey +{ + OFMutableArray *array = [self.arrayClass arrayWithObjects: + [OFMutableIRI IRIWithString: @"http://foo.bar/"], + [OFMutableIRI IRIWithString: @"http://bar.qux/"], + [OFMutableIRI IRIWithString: @"http://qux.quxqux/"], nil]; + + [array setValue: [OFNumber numberWithShort: 1234] + forKey: @"port"]; + OTAssertEqualObjects(array, ([OFArray arrayWithObjects: + [OFIRI IRIWithString: @"http://foo.bar:1234/"], + [OFIRI IRIWithString: @"http://bar.qux:1234/"], + [OFIRI IRIWithString: @"http://qux.quxqux:1234/"], nil])); +} +@end + +@implementation CustomMutableArray +- (instancetype)initWithObjects: (id const *)objects count: (size_t)count +{ + self = [super init]; + + @try { + _array = [[OFMutableArray alloc] initWithObjects: objects + count: count]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_array release]; + + [super dealloc]; +} + +- (id)objectAtIndex: (size_t)idx +{ + return [_array objectAtIndex: idx]; +} + +- (size_t)count +{ + return [_array count]; +} + +- (void)insertObject: (id)object atIndex: (size_t)idx +{ + [_array insertObject: object atIndex: idx]; +} + +- (void)replaceObjectAtIndex: (size_t)idx withObject: (id)object +{ + [_array replaceObjectAtIndex: idx withObject: object]; +} + +- (void)removeObjectAtIndex: (size_t)idx +{ + [_array removeObjectAtIndex: idx]; +} +@end ADDED tests/OFMutableDataTests.m Index: tests/OFMutableDataTests.m ================================================================== --- /dev/null +++ tests/OFMutableDataTests.m @@ -0,0 +1,117 @@ +/* + * 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" + +#include + +#import "OFDataTests.h" + +@interface OFMutableDataTests: OFDataTests +{ + OFMutableData *_mutableData; +} +@end + +@implementation OFMutableDataTests +- (Class)dataClass +{ + return [OFMutableData class]; +} + +- (void)setUp +{ + [super setUp]; + + _mutableData = [[OFMutableData alloc] initWithItems: "abcdef" count: 6]; +} + +- (void)dealloc +{ + [_mutableData release]; + + [super dealloc]; +} + +- (void)testMutableCopy +{ + OTAssertEqualObjects([[_data mutableCopy] autorelease], _data); + OTAssertNotEqual([[_data mutableCopy] autorelease], _data); +} + +- (void)testAddItem +{ + [_mutableData addItem: "g"]; + + OTAssertEqualObjects(_mutableData, + [OFData dataWithItems: "abcdefg" count: 7]); +} + +- (void)testAddItemsCount +{ + [_mutableData addItems: "gh" count: 2]; + + OTAssertEqualObjects(_mutableData, + [OFData dataWithItems: "abcdefgh" count: 8]); +} + +- (void)testAddItemsCountThrowsOnOutOfRange +{ + OTAssertThrowsSpecific([_mutableData addItems: "" count: SIZE_MAX], + OFOutOfRangeException); +} + +- (void)testRemoveLastItem +{ + [_mutableData removeLastItem]; + + OTAssertEqualObjects(_mutableData, + [OFData dataWithItems: "abcde" count: 5]); +} + +- (void)testRemoveItemsInRange +{ + [_mutableData removeItemsInRange: OFMakeRange(1, 2)]; + + OTAssertEqualObjects(_mutableData, + [OFData dataWithItems: "adef" count: 4]); +} + +- (void)testRemoveItemsInRangeThrowsOnOutOfRangeRange +{ + OTAssertThrowsSpecific( + [_mutableData removeItemsInRange: OFMakeRange(6, 1)], + OFOutOfRangeException); + + OTAssertThrowsSpecific( + [_mutableData removeItemsInRange: OFMakeRange(7, 0)], + OFOutOfRangeException); +} + +- (void)testInsertItemsAtIndexCount +{ + [_mutableData insertItems: "BC" atIndex: 1 count: 2]; + + OTAssertEqualObjects(_mutableData, + [OFData dataWithItems: "aBCbcdef" count: 8]); +} + +- (void)testInsertItemsAtIndexCountThrowsOnOutOfRangeIndex +{ + OTAssertThrowsSpecific( + [_mutableData insertItems: "a" atIndex: 7 count: 1], + OFOutOfRangeException); +} +@end ADDED tests/OFMutableDictionaryTests.h Index: tests/OFMutableDictionaryTests.h ================================================================== --- /dev/null +++ tests/OFMutableDictionaryTests.h @@ -0,0 +1,25 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +#import "OFDictionaryTests.h" + +@interface OFMutableDictionaryTests: OFDictionaryTests +{ + OFMutableDictionary *_mutableDictionary; +} +@end ADDED tests/OFMutableDictionaryTests.m Index: tests/OFMutableDictionaryTests.m ================================================================== --- /dev/null +++ tests/OFMutableDictionaryTests.m @@ -0,0 +1,174 @@ +/* + * 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 "OFMutableDictionaryTests.h" + +@interface CustomMutableDictionary: OFMutableDictionary +{ + OFMutableDictionary *_dictionary; +} +@end + +@implementation OFMutableDictionaryTests +- (Class)dictionaryClass +{ + return [CustomMutableDictionary class]; +} + +- (void)setUp +{ + [super setUp]; + + _mutableDictionary = [[self.dictionaryClass alloc] init]; +} + +- (void)dealloc +{ + [_mutableDictionary release]; + + [super dealloc]; +} + +- (void)testSetObjectForKey +{ + [_mutableDictionary setObject: @"bar" forKey: @"foo"]; + OTAssertEqualObjects([_mutableDictionary objectForKey: @"foo"], @"bar"); + + [_mutableDictionary setObject: @"qux" forKey: @"baz"]; + OTAssertEqualObjects(_mutableDictionary, + ([OFDictionary dictionaryWithKeysAndObjects: + @"foo", @"bar", @"baz", @"qux", nil])); +} + +- (void)testSetValueForKey +{ + [_mutableDictionary setValue: @"bar" forKey: @"foo"]; + OTAssertEqualObjects([_mutableDictionary objectForKey: @"foo"], @"bar"); + + [_mutableDictionary setValue: @"qux" forKey: @"baz"]; + OTAssertEqualObjects(_mutableDictionary, + ([OFDictionary dictionaryWithKeysAndObjects: + @"foo", @"bar", @"baz", @"qux", nil])); +} + +- (void)testRemoveObjectForKey +{ + [_mutableDictionary addEntriesFromDictionary: _dictionary]; + OTAssertEqual(_mutableDictionary.count, 2); + + [_mutableDictionary removeObjectForKey: @"key2"]; + OTAssertEqual(_mutableDictionary.count, 1); + OTAssertEqualObjects(_mutableDictionary, + [OFDictionary dictionaryWithObject: @"value1" forKey: @"key1"]); +} + +- (void)testMutableCopy +{ + OFMutableDictionary *copy = [[_dictionary mutableCopy] autorelease]; + + OTAssertEqualObjects(copy, _dictionary); + OTAssertNotEqual(copy, _dictionary); +} + +#ifdef OF_HAVE_BLOCKS +- (void)testReplaceObjectsUsingBlock +{ + OFMutableDictionary *mutableDictionary = + [[_dictionary mutableCopy] autorelease]; + + [mutableDictionary replaceObjectsUsingBlock: ^ id (id key, id object) { + if ([key isEqual: @"key1"]) + return @"value_1"; + if ([key isEqual: @"key2"]) + return @"value_2"; + + return nil; + }]; + + OTAssertEqualObjects(mutableDictionary, + ([OFDictionary dictionaryWithKeysAndObjects: + @"key1", @"value_1", @"key2", @"value_2", nil])); +} +#endif +@end + +@implementation CustomMutableDictionary +- (instancetype)init +{ + self = [super init]; + + @try { + _dictionary = [[OFMutableDictionary alloc] init]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithObjects: (const id *)objects_ + forKeys: (const id *)keys_ + count: (size_t)count +{ + self = [super init]; + + @try { + _dictionary = [[OFMutableDictionary alloc] + initWithObjects: objects_ + forKeys: keys_ + count: count]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_dictionary release]; + + [super dealloc]; +} + +- (id)objectForKey: (id)key +{ + return [_dictionary objectForKey: key]; +} + +- (size_t)count +{ + return _dictionary.count; +} + +- (OFEnumerator *)keyEnumerator +{ + return [_dictionary keyEnumerator]; +} + +- (void)setObject: (id)object forKey: (id)key +{ + [_dictionary setObject: object forKey: key]; +} + +- (void)removeObjectForKey: (id)key +{ + [_dictionary removeObjectForKey: key]; +} +@end ADDED tests/OFMutableSetTests.h Index: tests/OFMutableSetTests.h ================================================================== --- /dev/null +++ tests/OFMutableSetTests.h @@ -0,0 +1,22 @@ +/* + * 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 "OFSetTests.h" + +@interface OFMutableSetTests: OFSetTests +{ + OFMutableSet *_mutableSet; +} +@end ADDED tests/OFMutableSetTests.m Index: tests/OFMutableSetTests.m ================================================================== --- /dev/null +++ tests/OFMutableSetTests.m @@ -0,0 +1,142 @@ +/* + * 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 "OFMutableSetTests.h" + +@interface CustomMutableSet: OFMutableSet +{ + OFMutableSet *_set; +} +@end + +@implementation OFMutableSetTests +- (Class)setClass +{ + return [CustomMutableSet class]; +} + +- (void)setUp +{ + [super setUp]; + + _mutableSet = [[OFMutableSet alloc] + initWithObjects: @"foo", @"bar", @"baz", nil]; +} + +- (void)dealloc +{ + [_mutableSet release]; + + [super dealloc]; +} + +- (void)testAddObject +{ + [_mutableSet addObject: @"x"]; + + OTAssertEqualObjects(_mutableSet, + ([OFSet setWithObjects: @"foo", @"bar", @"baz", @"x", nil])); +} + +- (void)testRemoveObject +{ + [_mutableSet removeObject: @"foo"]; + + OTAssertEqualObjects(_mutableSet, + ([OFSet setWithObjects: @"bar", @"baz", nil])); +} + +- (void)testMinusSet +{ + [_mutableSet minusSet: [OFSet setWithObjects: @"foo", @"bar", nil]]; + + OTAssertEqualObjects(_mutableSet, + ([OFSet setWithObjects: @"baz", nil])); +} + +- (void)testIntersectSet +{ + [_mutableSet intersectSet: [OFSet setWithObjects: @"foo", @"qux", nil]]; + + OTAssertEqualObjects(_mutableSet, + ([OFSet setWithObjects: @"foo", nil])); +} + +- (void)testUnionSet +{ + [_mutableSet unionSet: [OFSet setWithObjects: @"x", @"y", nil]]; + + OTAssertEqualObjects(_mutableSet, + ([OFSet setWithObjects: @"foo", @"bar", @"baz", @"x", @"y", nil])); +} + +- (void)testRemoveAllObjects +{ + [_mutableSet removeAllObjects]; + + OTAssertEqual(_mutableSet.count, 0); +} +@end + +@implementation CustomMutableSet +- (instancetype)initWithObjects: (id const *)objects count: (size_t)count +{ + self = [super init]; + + @try { + _set = [[OFMutableSet alloc] initWithObjects: objects + count: count]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_set release]; + + [super dealloc]; +} + +- (size_t)count +{ + return _set.count; +} + +- (bool)containsObject: (id)object +{ + return [_set containsObject: object]; +} + +- (OFEnumerator *)objectEnumerator +{ + return [_set objectEnumerator]; +} + +- (void)addObject: (id)object +{ + [_set addObject: object]; +} + +- (void)removeObject: (id)object +{ + [_set removeObject: object]; +} +@end ADDED tests/OFMutableStringTests.h Index: tests/OFMutableStringTests.h ================================================================== --- /dev/null +++ tests/OFMutableStringTests.h @@ -0,0 +1,25 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +#import "OFStringTests.h" + +@interface OFMutableStringTests: OFStringTests +{ + OFMutableString *_mutableString; +} +@end ADDED tests/OFMutableStringTests.m Index: tests/OFMutableStringTests.m ================================================================== --- /dev/null +++ tests/OFMutableStringTests.m @@ -0,0 +1,408 @@ +/* + * 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" + +#include + +#import "OFMutableStringTests.h" + +@interface CustomMutableString: OFMutableString +{ + OFMutableString *_string; +} +@end + +static OFString *const whitespace[] = { + @" \r \t\n\t \tasd \t \t\t\r\n", + @" \t\t \t\t \t \t" +}; + +@implementation OFMutableStringTests +- (Class)stringClass +{ + return [CustomMutableString class]; +} + +- (void)setUp +{ + [super setUp]; + + _mutableString = [[self.stringClass alloc] initWithString: @"täṠ€🤔"]; +} + +- (void)dealloc +{ + [_mutableString release]; + + [super dealloc]; +} + +- (void)testAppendString +{ + [_mutableString appendString: @"ö"]; + + OTAssertEqualObjects(_mutableString, @"täṠ€🤔ö"); +} + +- (void)testAppendUTF8String +{ + [_mutableString appendUTF8String: "ö"]; + + OTAssertEqualObjects(_mutableString, @"täṠ€🤔ö"); +} + +- (void)testAppendUTF8StringLength +{ + [_mutableString appendUTF8String: "\xEF\xBB\xBF" "öÖ" length: 7]; + + OTAssertEqualObjects(_mutableString, @"täṠ€🤔öÖ"); +} + +- (void)testAppendFormat +{ + [_mutableString appendFormat: @"%02X", 15]; + + OTAssertEqualObjects(_mutableString, @"täṠ€🤔0F"); +} + +- (void)testAppendCharactersLength +{ + [_mutableString appendCharacters: (OFUnichar []){ 0xF6, 0xD6 } + length: 2]; + + OTAssertEqualObjects(_mutableString, @"täṠ€🤔öÖ"); +} + +- (void)testUppercase +{ + [_mutableString uppercase]; + +#ifdef OF_HAVE_UNICODE_TABLES + OTAssertEqualObjects(_mutableString, @"TÄṠ€🤔"); +#else + OTAssertEqualObjects(_mutableString, @"TäṠ€🤔"); +#endif +} + +- (void)testLowercase +{ + [_mutableString lowercase]; + +#ifdef OF_HAVE_UNICODE_TABLES + OTAssertEqualObjects(_mutableString, @"täṡ€🤔"); +#else + OTAssertEqualObjects(_mutableString, @"täṠ€🤔"); +#endif +} + +- (void)testCapitalize +{ + OFMutableString *string = + [self.stringClass stringWithString: @"täṠ€🤔täṠ€🤔 täṠ€🤔"]; + + [string capitalize]; + +#ifdef OF_HAVE_UNICODE_TABLES + OTAssertEqualObjects(string, @"Täṡ€🤔täṡ€🤔 Täṡ€🤔"); +#else + OTAssertEqualObjects(string, @"TäṠ€🤔täṠ€🤔 TäṠ€🤔"); +#endif +} + +- (void)testInsertStringAtIndex +{ + [_mutableString insertString: @"fööbär" atIndex: 2]; + + OTAssertEqualObjects(_mutableString, @"täfööbärṠ€🤔"); +} + +- (void)testSetCharacterAtIndex +{ + [_mutableString setCharacter: 0x1F600 atIndex: 2]; + + OTAssertEqualObjects(_mutableString, @"tä😀€🤔"); +} + +- (void)testDeleteCharactersInRange +{ + [_mutableString deleteCharactersInRange: OFMakeRange(2, 2)]; + + OTAssertEqualObjects(_mutableString, @"tä🤔"); +} + +- (void)testDeleteCharactersInRangeThrowsWithOutOfRangeRange +{ + OTAssertThrowsSpecific( + [_mutableString deleteCharactersInRange: OFMakeRange(4, 2)], + OFOutOfRangeException); + + OTAssertThrowsSpecific( + [_mutableString deleteCharactersInRange: OFMakeRange(5, 1)], + OFOutOfRangeException); + + OTAssertThrowsSpecific( + [_mutableString deleteCharactersInRange: OFMakeRange(6, 0)], + OFOutOfRangeException); +} + +- (void)testReplaceCharactersInRangeWithString +{ + OFMutableString *string = + [self.stringClass stringWithString: @"𝄞öööbä€"]; + + [string replaceCharactersInRange: OFMakeRange(1, 3) + withString: @"äöüß"]; + OTAssertEqualObjects(string, @"𝄞äöüßbä€"); + + [string replaceCharactersInRange: OFMakeRange(4, 2) withString: @"b"]; + OTAssertEqualObjects(string, @"𝄞äöübä€"); + + [string replaceCharactersInRange: OFMakeRange(0, 7) withString: @""]; + OTAssertEqualObjects(string, @""); +} + +- (void)testReplaceCharactersInRangeWithStringFailsWithOutOfRangeRange +{ + OTAssertThrowsSpecific( + [_mutableString replaceCharactersInRange: OFMakeRange(4, 2) + withString: @"abc"], + OFOutOfRangeException); + + OTAssertThrowsSpecific( + [_mutableString replaceCharactersInRange: OFMakeRange(5, 1) + withString: @"abc"], + OFOutOfRangeException); + + OTAssertThrowsSpecific( + [_mutableString replaceCharactersInRange: OFMakeRange(6, 0) + withString: @""], + OFOutOfRangeException); +} + +- (void)testReplaceOccurrencesOfStringWithString +{ + OFMutableString *string; + + string = [self.stringClass stringWithString: @"asd fo asd fofo asd"]; + [string replaceOccurrencesOfString: @"fo" withString: @"foo"]; + OTAssertEqualObjects(string, @"asd foo asd foofoo asd"); + + string = [self.stringClass stringWithString: @"XX"]; + [string replaceOccurrencesOfString: @"X" withString: @"XX"]; + OTAssertEqualObjects(string, @"XXXX"); +} + +- (void)testReplaceOccurrencesOfStringWithStringOptionsRange +{ + OFMutableString *string = + [self.stringClass stringWithString: @"foofoobarfoobarfoo"]; + + [string replaceOccurrencesOfString: @"oo" + withString: @"óò" + options: 0 + range: OFMakeRange(2, 15)]; + OTAssertEqualObjects(string, @"foofóòbarfóòbarfoo"); +} + +- (void) + testReplaceOccurrencesOfStringWithStringOptionsRangeThrowsWithOutOfRangeRange +{ + OTAssertThrowsSpecific( + [_mutableString replaceOccurrencesOfString: @"t" + withString: @"abc" + options: 0 + range: OFMakeRange(4, 2)], + OFOutOfRangeException); + + OTAssertThrowsSpecific( + [_mutableString replaceOccurrencesOfString: @"t" + withString: @"abc" + options: 0 + range: OFMakeRange(5, 1)], + OFOutOfRangeException); + + OTAssertThrowsSpecific( + [_mutableString replaceOccurrencesOfString: @"t" + withString: @"" + options: 0 + range: OFMakeRange(6, 0)], + OFOutOfRangeException); +} + +- (void)deleteLeadingWhitespaces +{ + OFMutableString *string; + + string = [self.stringClass stringWithString: whitespace[0]]; + [string deleteLeadingWhitespaces]; + OTAssertEqualObjects(string, @"asd \t \t\t\r\n"); + + string = [self.stringClass stringWithString: whitespace[1]]; + [string deleteLeadingWhitespaces]; + OTAssertEqualObjects(string, @""); +} + +- (void)deleteTrailingWhitespaces +{ + OFMutableString *string; + + string = [self.stringClass stringWithString: whitespace[0]]; + [string deleteTrailingWhitespaces]; + OTAssertEqualObjects(string, @" \r \t\n\t \tasd"); + + string = [self.stringClass stringWithString: whitespace[1]]; + [string deleteTrailingWhitespaces]; + OTAssertEqualObjects(string, @""); +} + +- (void)deleteEnclosingWhitespaces +{ + OFMutableString *string; + + string = [self.stringClass stringWithString: whitespace[0]]; + [string deleteEnclosingWhitespaces]; + OTAssertEqualObjects(string, @"asd"); + + string = [self.stringClass stringWithString: whitespace[1]]; + [string deleteEnclosingWhitespaces]; + OTAssertEqualObjects(string, @""); +} +@end + +@implementation CustomMutableString +- (instancetype)init +{ + self = [super init]; + + @try { + _string = [[OFMutableString alloc] init]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithString: (OFString *)string +{ + self = [super init]; + + @try { + _string = [string mutableCopy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithCString: (const char *)cString + encoding: (OFStringEncoding)encoding + length: (size_t)length +{ + self = [super init]; + + @try { + _string = [[OFMutableString alloc] initWithCString: cString + encoding: encoding + length: length]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithUTF16String: (const OFChar16 *)UTF16String + length: (size_t)length + byteOrder: (OFByteOrder)byteOrder +{ + self = [super init]; + + @try { + _string = [[OFMutableString alloc] + initWithUTF16String: UTF16String + length: length + byteOrder: byteOrder]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithUTF32String: (const OFChar32 *)UTF32String + length: (size_t)length + byteOrder: (OFByteOrder)byteOrder +{ + self = [super init]; + + @try { + _string = [[OFMutableString alloc] + initWithUTF32String: UTF32String + length: length + byteOrder: byteOrder]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithFormat: (OFConstantString *)format + arguments: (va_list)arguments +{ + self = [super init]; + + @try { + _string = [[OFMutableString alloc] initWithFormat: format + arguments: arguments]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_string release]; + + [super dealloc]; +} + +- (OFUnichar)characterAtIndex: (size_t)idx +{ + return [_string characterAtIndex: idx]; +} + +- (size_t)length +{ + return _string.length; +} + +- (void)replaceCharactersInRange: (OFRange)range + withString: (OFString *)string +{ + [_string replaceCharactersInRange: range withString: string]; +} +@end ADDED tests/OFMutableUTF8StringTests.m Index: tests/OFMutableUTF8StringTests.m ================================================================== --- /dev/null +++ tests/OFMutableUTF8StringTests.m @@ -0,0 +1,30 @@ +/* + * 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 "OFMutableStringTests.h" + +#import "OFMutableUTF8String.h" + +@interface OFMutableUTF8StringTests: OFMutableStringTests +@end + +@implementation OFMutableUTF8StringTests +- (Class)arrayClass +{ + return [OFMutableUTF8String class]; +} +@end ADDED tests/OFNotificationCenterTests.m Index: tests/OFNotificationCenterTests.m ================================================================== --- /dev/null +++ tests/OFNotificationCenterTests.m @@ -0,0 +1,161 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +static const OFNotificationName notificationName = + @"OFNotificationCenterTestName"; +static const OFNotificationName otherNotificationName = + @"OFNotificationCenterTestOtherName"; + +@interface OFNotificationCenterTests: OTTestCase +@end + +@interface OFNotificationCenterTestClass: OFObject +{ +@public + id _expectedObject; + int _received; +} + +- (void)handleNotification: (OFNotification *)notification; +@end + +@implementation OFNotificationCenterTestClass +- (void)handleNotification: (OFNotification *)notification +{ + OFEnsure([notification.name isEqual: notificationName]); + OFEnsure(_expectedObject == nil || + notification.object == _expectedObject); + + _received++; +} +@end + +@implementation OFNotificationCenterTests +- (void)testNotificationCenter +{ + OFNotificationCenter *center = [OFNotificationCenter defaultCenter]; + OFNotificationCenterTestClass *test1, *test2, *test3, *test4; + OFNotification *notification; + + test1 = [[[OFNotificationCenterTestClass alloc] init] autorelease]; + test1->_expectedObject = self; + test2 = [[[OFNotificationCenterTestClass alloc] init] autorelease]; + test3 = [[[OFNotificationCenterTestClass alloc] init] autorelease]; + test3->_expectedObject = self; + test4 = [[[OFNotificationCenterTestClass alloc] init] autorelease]; + + /* First one intentionally added twice to test deduplication. */ + [center addObserver: test1 + selector: @selector(handleNotification:) + name: notificationName + object: self]; + [center addObserver: test1 + selector: @selector(handleNotification:) + name: notificationName + object: self]; + [center addObserver: test2 + selector: @selector(handleNotification:) + name: notificationName + object: nil]; + [center addObserver: test3 + selector: @selector(handleNotification:) + name: otherNotificationName + object: self]; + [center addObserver: test4 + selector: @selector(handleNotification:) + name: otherNotificationName + object: nil]; + + notification = [OFNotification notificationWithName: notificationName + object: nil]; + [center postNotification: notification]; + OTAssertEqual(test1->_received, 0); + OTAssertEqual(test2->_received, 1); + OTAssertEqual(test3->_received, 0); + OTAssertEqual(test4->_received, 0); + + notification = [OFNotification notificationWithName: notificationName + object: self]; + [center postNotification: notification]; + OTAssertEqual(test1->_received, 1); + OTAssertEqual(test2->_received, 2); + OTAssertEqual(test3->_received, 0); + OTAssertEqual(test4->_received, 0); + + notification = [OFNotification notificationWithName: notificationName + object: @"foo"]; + [center postNotification: notification]; + OTAssertEqual(test1->_received, 1); + OTAssertEqual(test2->_received, 3); + OTAssertEqual(test3->_received, 0); + OTAssertEqual(test4->_received, 0); + +#ifdef OF_HAVE_BLOCKS + __block bool received = false; + id handle; + + notification = [OFNotification notificationWithName: notificationName + object: self]; + handle = [center addObserverForName: notificationName + object: self + usingBlock: ^ (OFNotification *notification_) { + OTAssertEqual(notification_, notification); + OTAssertFalse(received); + received = true; + }]; + [center postNotification: notification]; + OTAssertTrue(received); + OTAssertEqual(test1->_received, 2); + OTAssertEqual(test2->_received, 4); + OTAssertEqual(test3->_received, 0); + OTAssertEqual(test4->_received, 0); + + /* Act like the block test didn't happen. */ + [center removeObserver: handle]; + test1->_received--; + test2->_received--; +#endif + + [center removeObserver: test1 + selector: @selector(handleNotification:) + name: notificationName + object: self]; + [center removeObserver: test2 + selector: @selector(handleNotification:) + name: notificationName + object: nil]; + [center removeObserver: test3 + selector: @selector(handleNotification:) + name: otherNotificationName + object: self]; + [center removeObserver: test4 + selector: @selector(handleNotification:) + name: otherNotificationName + object: nil]; + + notification = [OFNotification notificationWithName: notificationName + object: self]; + [center postNotification: notification]; + OTAssertEqual(test1->_received, 1); + OTAssertEqual(test2->_received, 3); + OTAssertEqual(test3->_received, 0); + OTAssertEqual(test4->_received, 0); +} +@end ADDED tests/OFNumberTests.m Index: tests/OFNumberTests.m ================================================================== --- /dev/null +++ tests/OFNumberTests.m @@ -0,0 +1,130 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFNumberTests: OTTestCase +{ + OFNumber *_number; +} +@end + +@implementation OFNumberTests +- (void)setUp +{ + [super setUp]; + + _number = [[OFNumber alloc] initWithLongLong: 123456789]; +} + +- (void)dealloc +{ + [_number release]; + + [super dealloc]; +} + +- (void)testIsEqual +{ + OTAssertEqualObjects(_number, [OFNumber numberWithLong: 123456789]); +} + +- (void)testHash +{ + OTAssertEqual(_number.hash, + [[OFNumber numberWithLong: 123456789] hash]); +} + +- (void)testCharValue +{ + OTAssertEqual(_number.charValue, 21); +} + +- (void)testDoubleValue +{ + OTAssertEqual(_number.doubleValue, 123456789.L); +} + +- (void)testSignedCharMinAndMaxUnmodified +{ + OTAssertEqual([[OFNumber numberWithChar: SCHAR_MIN] charValue], + SCHAR_MIN); + OTAssertEqual([[OFNumber numberWithChar: SCHAR_MAX] charValue], + SCHAR_MAX); +} + +- (void)testShortMinAndMaxUnmodified +{ + OTAssertEqual([[OFNumber numberWithShort: SHRT_MIN] shortValue], + SHRT_MIN); + OTAssertEqual([[OFNumber numberWithShort: SHRT_MAX] shortValue], + SHRT_MAX); +} + +- (void)testIntMinAndMaxUnmodified +{ + OTAssertEqual([[OFNumber numberWithInt: INT_MIN] intValue], INT_MIN); + OTAssertEqual([[OFNumber numberWithInt: INT_MAX] intValue], INT_MAX); +} + +- (void)testLongMinAndMaxUnmodified +{ + OTAssertEqual([[OFNumber numberWithLong: LONG_MIN] longValue], + LONG_MIN); + OTAssertEqual([[OFNumber numberWithLong: LONG_MAX] longValue], + LONG_MAX);; +} + +- (void)testLongLongMinAndMaxUnmodified +{ + OTAssertEqual([[OFNumber numberWithLongLong: LLONG_MIN] longLongValue], + LLONG_MIN); + OTAssertEqual([[OFNumber numberWithLongLong: LLONG_MAX] longLongValue], + LLONG_MAX); +} + +- (void)testUnsignedCharMaxUnmodified +{ + OTAssertEqual([[OFNumber numberWithUnsignedChar: UCHAR_MAX] + unsignedCharValue], UCHAR_MAX); +} + +- (void)testUnsignedShortMaxUnmodified +{ + OTAssertEqual([[OFNumber numberWithUnsignedShort: USHRT_MAX] + unsignedShortValue], USHRT_MAX); +} + +- (void)testUnsignedIntMaxUnmodified +{ + OTAssertEqual([[OFNumber numberWithUnsignedInt: UINT_MAX] + unsignedIntValue], UINT_MAX); +} + +- (void)testUnsignedLongMaxUnmodified +{ + OTAssertEqual([[OFNumber numberWithUnsignedLong: ULONG_MAX] + unsignedLongValue], ULONG_MAX); +} + +- (void)testUnsignedLongLongMaxUnmodified +{ + OTAssertEqual([[OFNumber numberWithUnsignedLongLong: ULLONG_MAX] + unsignedLongLongValue], ULLONG_MAX); +} +@end ADDED tests/OFObjectTests.m Index: tests/OFObjectTests.m ================================================================== --- /dev/null +++ tests/OFObjectTests.m @@ -0,0 +1,261 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface MyObject: 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 + +@interface OFObjectTests: OTTestCase +{ + MyObject *_myObject; +} +@end + +@implementation OFObjectTests +- (void)setUp +{ + [super setUp]; + + _myObject = [[MyObject alloc] init]; +} + +- (void)dealloc +{ + [_myObject release]; + + [super dealloc]; +} + +- (void)testClassDescription +{ + OTAssertEqualObjects([OFObject description], @"OFObject"); + OTAssertEqualObjects([MyObject description], @"MyObject"); +} + +- (void)testInstanceDescription +{ + OFObject *object = [[[OFObject alloc] init] autorelease]; + + OTAssertEqualObjects(object.description, @""); + OTAssertEqualObjects(_myObject.description, @""); +} + +- (void)testValueForKey +{ + _myObject.objectValue = @"Hello"; + _myObject.classValue = _myObject.class; + + OTAssertEqualObjects([_myObject valueForKey: @"objectValue"], @"Hello"); + OTAssertEqualObjects([_myObject valueForKey: @"classValue"], + _myObject.class); + OTAssertEqualObjects([_myObject valueForKey: @"class"], + _myObject.class); +} + +- (void)testValueForKeyWithUndefinedKeyThrows +{ + OTAssertThrowsSpecific([_myObject valueForKey: @"undefined"], + OFUndefinedKeyException); +} + +- (void)testSetValueForKey +{ + [_myObject setValue: @"World" forKey: @"objectValue"]; + [_myObject setValue: [OFObject class] forKey: @"classValue"]; + + OTAssertEqualObjects(_myObject.objectValue, @"World"); + OTAssertEqualObjects(_myObject.classValue, [OFObject class]); +} + +- (void)testSetValueWithUndefinedKeyThrows +{ + OTAssertThrowsSpecific([_myObject setValue: @"x" forKey: @"undefined"], + OFUndefinedKeyException); +} + +- (void)testAutoWrappingOfValueForKey +{ + _myObject.boolValue = 1; + _myObject.charValue = 2; + _myObject.shortValue = 3; + _myObject.intValue = 4; + _myObject.longValue = 5; + _myObject.longLongValue = 6; + _myObject.unsignedCharValue = 7; + _myObject.unsignedShortValue = 8; + _myObject.unsignedIntValue = 9; + _myObject.unsignedLongValue = 10; + _myObject.unsignedLongLongValue = 11; + _myObject.floatValue = 12; + _myObject.doubleValue = 13; + + OTAssertEqualObjects([_myObject valueForKey: @"boolValue"], + [OFNumber numberWithBool: 1]); + OTAssertEqualObjects([_myObject valueForKey: @"charValue"], + [OFNumber numberWithChar: 2]); + OTAssertEqualObjects([_myObject valueForKey: @"shortValue"], + [OFNumber numberWithShort: 3]); + OTAssertEqualObjects([_myObject valueForKey: @"intValue"], + [OFNumber numberWithInt: 4]); + OTAssertEqualObjects([_myObject valueForKey: @"longValue"], + [OFNumber numberWithLong: 5]); + OTAssertEqualObjects([_myObject valueForKey: @"longLongValue"], + [OFNumber numberWithLongLong: 6]); + OTAssertEqualObjects([_myObject valueForKey: @"unsignedCharValue"], + [OFNumber numberWithUnsignedChar: 7]); + OTAssertEqualObjects([_myObject valueForKey: @"unsignedShortValue"], + [OFNumber numberWithUnsignedShort: 8]); + OTAssertEqualObjects([_myObject valueForKey: @"unsignedIntValue"], + [OFNumber numberWithUnsignedInt: 9]); + OTAssertEqualObjects([_myObject valueForKey: @"unsignedLongValue"], + [OFNumber numberWithUnsignedLong: 10]); + OTAssertEqualObjects([_myObject valueForKey: @"unsignedLongLongValue"], + [OFNumber numberWithUnsignedLongLong: 11]); + OTAssertEqualObjects([_myObject valueForKey: @"floatValue"], + [OFNumber numberWithFloat: 12]); + OTAssertEqualObjects([_myObject valueForKey: @"doubleValue"], + [OFNumber numberWithDouble: 13]); +} + +- (void)testAutoWrappingOfSetValueForKey +{ + [_myObject setValue: [OFNumber numberWithBool: 0] + forKey: @"boolValue"]; + [_myObject setValue: [OFNumber numberWithChar: 10] + forKey: @"charValue"]; + [_myObject setValue: [OFNumber numberWithShort: 20] + forKey: @"shortValue"]; + [_myObject setValue: [OFNumber numberWithInt: 30] + forKey: @"intValue"]; + [_myObject setValue: [OFNumber numberWithLong: 40] + forKey: @"longValue"]; + [_myObject setValue: [OFNumber numberWithLongLong: 50] + forKey: @"longLongValue"]; + [_myObject setValue: [OFNumber numberWithUnsignedChar: 60] + forKey: @"unsignedCharValue"]; + [_myObject setValue: [OFNumber numberWithUnsignedShort: 70] + forKey: @"unsignedShortValue"]; + [_myObject setValue: [OFNumber numberWithUnsignedInt: 80] + forKey: @"unsignedIntValue"]; + [_myObject setValue: [OFNumber numberWithUnsignedLong: 90] + forKey: @"unsignedLongValue"]; + [_myObject setValue: [OFNumber numberWithUnsignedLongLong: 100] + forKey: @"unsignedLongLongValue"]; + [_myObject setValue: [OFNumber numberWithFloat: 110] + forKey: @"floatValue"]; + [_myObject setValue: [OFNumber numberWithDouble: 120] + forKey: @"doubleValue"]; + + OTAssertEqual(_myObject.isBoolValue, 0); + OTAssertEqual(_myObject.charValue, 10); + OTAssertEqual(_myObject.shortValue, 20); + OTAssertEqual(_myObject.intValue, 30); + OTAssertEqual(_myObject.longValue, 40); + OTAssertEqual(_myObject.longLongValue, 50); + OTAssertEqual(_myObject.unsignedCharValue, 60); + OTAssertEqual(_myObject.unsignedShortValue, 70); + OTAssertEqual(_myObject.unsignedIntValue, 80); + OTAssertEqual(_myObject.unsignedLongValue, 90); + OTAssertEqual(_myObject.unsignedLongLongValue, 100); + OTAssertEqual(_myObject.floatValue, 110); + OTAssertEqual(_myObject.doubleValue, 120); +} + +- (void)testSetValueForKeyWithNilThrows +{ + OTAssertThrowsSpecific( + [_myObject setValue: (id _Nonnull)nil forKey: @"intValue"], + OFInvalidArgumentException); +} + +- (void)testValueForKeyPath +{ + _myObject.objectValue = [[[MyObject alloc] init] autorelease]; + [_myObject.objectValue setObjectValue: + [[[MyObject alloc] init] autorelease]]; + [[_myObject.objectValue objectValue] setDoubleValue: 0.5]; + + OTAssertEqual([[_myObject valueForKeyPath: + @"objectValue.objectValue.doubleValue"] doubleValue], 0.5); +} + +- (void)testSetValueForKeyPath +{ + _myObject.objectValue = [[[MyObject alloc] init] autorelease]; + [_myObject.objectValue setObjectValue: + [[[MyObject alloc] init] autorelease]]; + [_myObject setValue: [OFNumber numberWithDouble: 0.75] + forKeyPath: @"objectValue.objectValue.doubleValue"]; + + OTAssertEqual([[_myObject.objectValue objectValue] doubleValue], 0.75); +} +@end + +@implementation MyObject +@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 ADDED tests/OFPBKDF2Tests.m Index: tests/OFPBKDF2Tests.m ================================================================== --- /dev/null +++ tests/OFPBKDF2Tests.m @@ -0,0 +1,170 @@ +/* + * 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" + +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFPBKDF2Tests: OTTestCase +{ + OFHMAC *_HMAC; +} +@end + +@implementation OFPBKDF2Tests +- (void)setUp +{ + [super setUp]; + + _HMAC = [[OFHMAC alloc] initWithHashClass: [OFSHA1Hash class] + allowsSwappableMemory: true]; +} + +- (void)dealloc +{ + [_HMAC release]; + + [super dealloc]; +} + +/* Test vectors from RFC 6070 */ + +- (void)testRFC6070TestVector1 +{ + unsigned char key[25]; + + OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = _HMAC, + .iterations = 1, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + }); + + OTAssertEqual(memcmp(key, "\x0C\x60\xC8\x0F\x96\x1F\x0E\x71\xF3\xA9\xB5" + "\x24\xAF\x60\x12\x06\x2F\xE0\x37\xA6", 20), 0); +} + +- (void)testRFC6070TestVector2 +{ + unsigned char key[25]; + + OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = _HMAC, + .iterations = 2, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + }); + + OTAssertEqual(memcmp(key, "\xEA\x6C\x01\x4D\xC7\x2D\x6F\x8C\xCD\x1E\xD9" + "\x2A\xCE\x1D\x41\xF0\xD8\xDE\x89\x57", 20), 0); +} + +- (void)testRFC6070TestVector3 +{ + unsigned char key[25]; + + OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = _HMAC, + .iterations = 4096, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + }); + + OTAssertEqual(memcmp(key, "\x4B\x00\x79\x01\xB7\x65\x48\x9A\xBE\xAD\x49" + "\xD9\x26\xF7\x21\xD0\x65\xA4\x29\xC1", 20), 0); +} + +#if 0 +/* This test takes too long, even on a fast machine. */ +- (void)testRFC6070TestVector4 +{ + unsigned char key[25]; + + OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = _HMAC, + .iterations = 16777216, + .salt = (unsigned char *)"salt", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = key, + .keyLength = 20, + .allowsSwappableMemory = true + }); + + OTAssertEqual(memcmp(key, "\xEE\xFE\x3D\x61\xCD\x4D\xA4\xE4\xE9\x94\x5B" + "\x3D\x6B\xA2\x15\x8C\x26\x34\xE9\x84", 20), 0); +} +#endif + +- (void)testRFC6070TestVector5 +{ + unsigned char key[25]; + + OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = _HMAC, + .iterations = 4096, + .salt = (unsigned char *)"saltSALTsaltSALTsalt" + "SALTsaltSALTsalt", + .saltLength = 36, + .password = "passwordPASSWORDpassword", + .passwordLength = 24, + .key = key, + .keyLength = 25, + .allowsSwappableMemory = true + }); + + OTAssertEqual(memcmp(key, "\x3D\x2E\xEC\x4F\xE4\x1C\x84\x9B\x80\xC8\xD8" + "\x36\x62\xC0\xE4\x4A\x8B\x29\x1A\x96\x4C\xF2\xF0\x70\x38", 25), 0); +} + +- (void)testRFC6070TestVector6 +{ + unsigned char key[25]; + + OFPBKDF2((OFPBKDF2Parameters){ + .HMAC = _HMAC, + .iterations = 4096, + .salt = (unsigned char *)"sa\0lt", + .saltLength = 5, + .password = "pass\0word", + .passwordLength = 9, + .key = key, + .keyLength = 16, + .allowsSwappableMemory = true + }); + + OTAssertEqual(memcmp(key, "\x56\xFA\x6A\xA7\x55\x48\x09\x9D\xCC\x37\xD7" + "\xF0\x34\x25\xE0\xC3", 16), 0); +} +@end ADDED tests/OFPluginTests.m Index: tests/OFPluginTests.m ================================================================== --- /dev/null +++ tests/OFPluginTests.m @@ -0,0 +1,54 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +#import "plugin/TestPlugin.h" + +@interface OFPluginTests: OTTestCase +@end + +@implementation OFPluginTests +- (void)testPlugin +{ + TestPlugin *test = nil; + OFString *path; + OFPlugin *plugin; + Class (*class)(void); + +#ifndef OF_IOS + path = [OFPlugin pathForName: @"plugin/TestPlugin"]; +#else + path = [OFPlugin pathForName: @"PlugIns/TestPlugin"]; +#endif + OTAssertNotNil(path); + + plugin = [OFPlugin pluginWithPath: path]; + OTAssertNotNil(plugin); + + class = (Class (*)(void))(uintptr_t)[plugin addressForSymbol: @"class"]; + OTAssert(class != NULL); + + @try { + test = [[class() alloc] init]; + OTAssertEqual([test test: 1234], 2468); + } @finally { + [test release]; + } +} +@end ADDED tests/OFPropertyListTests.m Index: tests/OFPropertyListTests.m ================================================================== --- /dev/null +++ tests/OFPropertyListTests.m @@ -0,0 +1,114 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFPropertyListTests: OTTestCase +@end + +#define PLIST(x) \ + @"" \ + @"" \ + @"\n" \ + x @"\n" \ + @"" + +@implementation OFPropertyListTests +- (void)testObjectByParsingPropertyList +{ + OFArray *array = [OFArray arrayWithObjects: + @"Hello", + [OFData dataWithItems: "World!" count: 6], + [OFDate dateWithTimeIntervalSince1970: 1521030896], + [OFNumber numberWithBool: true], + [OFNumber numberWithBool: false], + [OFNumber numberWithFloat: 12.25f], + [OFNumber numberWithInt: -10], + nil]; + + OTAssertEqualObjects([PLIST( + @"Hello") objectByParsingPropertyList], + @"Hello"); + OTAssertEqualObjects([PLIST( + @"" + @" Hello" + @" V29ybGQh" + @" 2018-03-14T12:34:56Z" + @" " + @" " + @" 12.25" + @" -10" + @"") objectByParsingPropertyList], + array); + OTAssertEqualObjects([PLIST( + @"" + @" array" + @" " + @" Hello" + @" V29ybGQh" + @" 2018-03-14T12:34:56Z" + @" " + @" " + @" 12.25" + @" -10" + @" " + @" foo" + @" bar" + @"") objectByParsingPropertyList], + ([OFDictionary dictionaryWithKeysAndObjects: + @"array", array, + @"foo", @"bar", + nil])); +} + +- (void)testDetectUnsupportedVersion +{ + OTAssertThrowsSpecific( + [[PLIST(@"") + stringByReplacingOccurrencesOfString: @"1.0" + withString: @"1.1"] + objectByParsingPropertyList], + OFUnsupportedVersionException); +} + +- (void)testDetectInvalidFormat +{ + OTAssertThrowsSpecific( + [PLIST(@"") objectByParsingPropertyList], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [PLIST(@"") objectByParsingPropertyList], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [PLIST(@"") objectByParsingPropertyList], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [PLIST(@"") + objectByParsingPropertyList], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [PLIST(@"") + objectByParsingPropertyList], + OFInvalidFormatException); +} +@end ADDED tests/OFSPXSocketTests.m Index: tests/OFSPXSocketTests.m ================================================================== --- /dev/null +++ tests/OFSPXSocketTests.m @@ -0,0 +1,233 @@ +/* + * 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" + +#include +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFSPXSocketTests: OTTestCase +{ + OFSPXSocket *_sockServer; + OFSocketAddress _addrServer; +} +@end + +@interface SPXSocketDelegate: OFObject +{ +@public + OFSequencedPacketSocket *_expectedServerSocket; + OFSPXSocket *_expectedClientSocket; + unsigned char _expectedNode[IPX_NODE_LEN]; + uint32_t _expectedNetwork; + uint16_t _expectedPort; + bool _accepted; + bool _connected; +} +@end + +@implementation OFSPXSocketTests +- (void)setUp +{ + const unsigned char zeroNode[IPX_NODE_LEN] = { 0 }; + + _sockServer = [[OFSPXSocket alloc] init]; + + @try { + _addrServer = [_sockServer bindToNetwork: 0 + node: zeroNode + port: 0]; + } @catch (OFBindSocketFailedException *e) { + switch (e.errNo) { + case EAFNOSUPPORT: + OTSkip(@"IPX unsupported"); + case ESOCKTNOSUPPORT: + OTSkip(@"SPX unsupported"); + case EADDRNOTAVAIL: + OTSkip(@"IPX not configured"); + default: + @throw e; + } + } +} + +- (void)dealloc +{ + [_sockServer release]; + + [super dealloc]; +} + +- (void)testSPXSocket +{ + OFSPXSocket *sockClient, *sockAccepted; + const OFSocketAddress *addrAccepted; + uint32_t network; + unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN]; + uint16_t port; + OFDictionary *networkInterfaces; + char buffer[5]; + + sockClient = [OFSPXSocket socket]; + + network = OFSocketAddressIPXNetwork(&_addrServer); + OFSocketAddressGetIPXNode(&_addrServer, node); + port = OFSocketAddressIPXPort(&_addrServer); + + [_sockServer listen]; + + /* + * Find any network interface with IPX and send to it. Any should be + * fine since we bound to 0.0. + */ + networkInterfaces = [OFSystemInfo networkInterfaces]; + for (OFString *name in networkInterfaces) { + OFNetworkInterface interface = [networkInterfaces + objectForKey: name]; + OFData *addresses = [interface + objectForKey: OFNetworkInterfaceIPXAddresses]; + + if (addresses.count == 0) + continue; + + network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]); + OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); + } + + [sockClient connectToNetwork: network node: node port: port]; + + sockAccepted = [_sockServer accept]; + [sockAccepted sendBuffer: "Hello" length: 5]; + + OTAssertEqual([sockClient receiveIntoBuffer: buffer length: 5], 5); + OTAssertEqual(memcmp(buffer, "Hello", 5), 0); + + addrAccepted = sockAccepted.remoteAddress; + OFSocketAddressGetIPXNode(addrAccepted, node2); + OTAssertEqual(memcmp(node, node2, IPX_NODE_LEN), 0); +} + +- (void)testAsyncSPXSocket +{ + SPXSocketDelegate *delegate = + [[[SPXSocketDelegate alloc] init] autorelease]; + uint32_t network; + unsigned char node[IPX_NODE_LEN]; + uint16_t port; + OFDictionary *networkInterfaces; + OFSPXSocket *sockClient; + + delegate->_expectedServerSocket = _sockServer; + _sockServer.delegate = delegate; + + sockClient = [OFSPXSocket socket]; + delegate->_expectedClientSocket = sockClient; + sockClient.delegate = delegate; + + [_sockServer listen]; + [_sockServer asyncAccept]; + + network = OFSocketAddressIPXNetwork(&_addrServer); + OFSocketAddressGetIPXNode(&_addrServer, node); + port = OFSocketAddressIPXPort(&_addrServer); + + /* + * Find any network interface with IPX and send to it. Any should be + * fine since we bound to 0.0. + */ + networkInterfaces = [OFSystemInfo networkInterfaces]; + for (OFString *name in networkInterfaces) { + OFNetworkInterface interface = [networkInterfaces + objectForKey: name]; + OFData *addresses = [interface + objectForKey: OFNetworkInterfaceIPXAddresses]; + + if (addresses.count == 0) + continue; + + network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]); + OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); + } + + delegate->_expectedNetwork = network = + OFSocketAddressIPXNetwork(&_addrServer); + OFSocketAddressGetIPXNode(&_addrServer, node); + memcpy(delegate->_expectedNode, node, IPX_NODE_LEN); + delegate->_expectedPort = port = OFSocketAddressIPXPort(&_addrServer); + + @try { + [sockClient asyncConnectToNetwork: network + node: node + port: port]; + + [[OFRunLoop mainRunLoop] runUntilDate: + [OFDate dateWithTimeIntervalSinceNow: 2]]; + + OTAssertTrue(delegate->_accepted); + OTAssertTrue(delegate->_connected); + } @catch (OFObserveKernelEventsFailedException *e) { + /* + * Make sure it doesn't stay in the run loop and throws again + * next time we run the run loop. + */ + [sockClient cancelAsyncRequests]; + [_sockServer cancelAsyncRequests]; + + switch (e.errNo) { + case ENOTSOCK: + OTSkip(@"select() not supported for SPX"); + default: + @throw e; + } + } +} +@end + +@implementation SPXSocketDelegate +- (bool)socket: (OFSequencedPacketSocket *)sock + didAcceptSocket: (OFSequencedPacketSocket *)accepted + exception: (id)exception +{ + OFEnsure(!_accepted); + + _accepted = (sock == _expectedServerSocket && accepted != nil && + exception == nil); + + if (_accepted && _connected) + [[OFRunLoop mainRunLoop] stop]; + + return false; +} + +- (void)socket: (OFSPXSocket *)sock + didConnectToNetwork: (uint32_t)network + node: (const unsigned char [IPX_NODE_LEN])node + port: (uint16_t)port + exception: (id)exception +{ + OFEnsure(!_connected); + + _connected = (sock == _expectedClientSocket && + network == _expectedNetwork && + memcmp(node, _expectedNode, IPX_NODE_LEN) == 0 && + port == _expectedPort && exception == nil); + + if (_accepted && _connected) + [[OFRunLoop mainRunLoop] stop]; +} +@end ADDED tests/OFSPXStreamSocketTests.m Index: tests/OFSPXStreamSocketTests.m ================================================================== --- /dev/null +++ tests/OFSPXStreamSocketTests.m @@ -0,0 +1,236 @@ +/* + * 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" + +#include +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFSPXStreamSocketTests: OTTestCase +{ + OFSPXStreamSocket *_sockServer; + OFSocketAddress _addrServer; +} +@end + +@interface SPXStreamSocketDelegate: OFObject +{ +@public + OFStreamSocket *_expectedServerSocket; + OFSPXStreamSocket *_expectedClientSocket; + uint32_t _expectedNetwork; + unsigned char _expectedNode[IPX_NODE_LEN]; + uint16_t _expectedPort; + bool _accepted; + bool _connected; +} +@end + +@implementation OFSPXStreamSocketTests +- (void)setUp +{ + const unsigned char zeroNode[IPX_NODE_LEN] = { 0 }; + + _sockServer = [[OFSPXStreamSocket alloc] init]; + + @try { + _addrServer = [_sockServer bindToNetwork: 0 + node: zeroNode + port: 0]; + } @catch (OFBindSocketFailedException *e) { + switch (e.errNo) { + case EAFNOSUPPORT: + OTSkip(@"IPX unsupported"); + case ESOCKTNOSUPPORT: + case EPROTONOSUPPORT: + OTSkip(@"SPX unsupported"); + case EADDRNOTAVAIL: + OTSkip(@"IPX not configured"); + default: + @throw e; + } + } +} + +- (void)dealloc +{ + [_sockServer release]; + + [super dealloc]; +} + +- (void)testSPXStreamSocket +{ + OFSPXStreamSocket *sockClient, *sockAccepted; + const OFSocketAddress *addrAccepted; + uint32_t network; + unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN]; + uint16_t port; + OFDictionary *networkInterfaces; + char buffer[5]; + + sockClient = [OFSPXStreamSocket socket]; + + network = OFSocketAddressIPXNetwork(&_addrServer); + OFSocketAddressGetIPXNode(&_addrServer, node); + port = OFSocketAddressIPXPort(&_addrServer); + + [_sockServer listen]; + + /* + * Find any network interface with IPX and send to it. Any should be + * fine since we bound to 0.0. + */ + networkInterfaces = [OFSystemInfo networkInterfaces]; + for (OFString *name in networkInterfaces) { + OFNetworkInterface interface = [networkInterfaces + objectForKey: name]; + OFData *addresses = [interface + objectForKey: OFNetworkInterfaceIPXAddresses]; + + if (addresses.count == 0) + continue; + + network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]); + OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); + } + + [sockClient connectToNetwork: network node: node port: port]; + + sockAccepted = [_sockServer accept]; + [sockAccepted writeBuffer: "Hello" length: 5]; + + /* Test reassembly (this would not work with OFSPXSocket) */ + OTAssertEqual([sockClient readIntoBuffer: buffer length: 2], 2); + OTAssertEqual([sockClient readIntoBuffer: buffer + 2 length: 3], 3); + OTAssertEqual(memcmp(buffer, "Hello", 5), 0); + + addrAccepted = sockAccepted.remoteAddress; + OFSocketAddressGetIPXNode(addrAccepted, node2); + OTAssertEqual(memcmp(node, node2, IPX_NODE_LEN), 0); +} + +- (void)testAsyncSPXStreamSocket +{ + SPXStreamSocketDelegate *delegate = + [[[SPXStreamSocketDelegate alloc] init] autorelease]; + uint32_t network; + unsigned char node[IPX_NODE_LEN]; + uint16_t port; + OFDictionary *networkInterfaces; + OFSPXStreamSocket *sockClient; + + delegate->_expectedServerSocket = _sockServer; + _sockServer.delegate = delegate; + + sockClient = [OFSPXStreamSocket socket]; + delegate->_expectedClientSocket = sockClient; + sockClient.delegate = delegate; + + [_sockServer listen]; + [_sockServer asyncAccept]; + + network = OFSocketAddressIPXNetwork(&_addrServer); + OFSocketAddressGetIPXNode(&_addrServer, node); + port = OFSocketAddressIPXPort(&_addrServer); + + /* + * Find any network interface with IPX and send to it. Any should be + * fine since we bound to 0.0. + */ + networkInterfaces = [OFSystemInfo networkInterfaces]; + for (OFString *name in networkInterfaces) { + OFNetworkInterface interface = [networkInterfaces + objectForKey: name]; + OFData *addresses = [interface + objectForKey: OFNetworkInterfaceIPXAddresses]; + + if (addresses.count == 0) + continue; + + network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]); + OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); + } + + delegate->_expectedNetwork = network = + OFSocketAddressIPXNetwork(&_addrServer); + OFSocketAddressGetIPXNode(&_addrServer, node); + memcpy(delegate->_expectedNode, node, IPX_NODE_LEN); + delegate->_expectedPort = port = OFSocketAddressIPXPort(&_addrServer); + + @try { + [sockClient asyncConnectToNetwork: network + node: node + port: port]; + + [[OFRunLoop mainRunLoop] runUntilDate: + [OFDate dateWithTimeIntervalSinceNow: 2]]; + + OTAssertTrue(delegate->_accepted); + OTAssertTrue(delegate->_connected); + } @catch (OFObserveKernelEventsFailedException *e) { + /* + * Make sure it doesn't stay in the run loop and throws again + * next time we run the run loop. + */ + [sockClient cancelAsyncRequests]; + [_sockServer cancelAsyncRequests]; + + switch (e.errNo) { + case ENOTSOCK: + OTSkip(@"select() not supported for SPX"); + default: + @throw e; + } + } +} +@end + +@implementation SPXStreamSocketDelegate +- (bool)socket: (OFStreamSocket *)sock + didAcceptSocket: (OFStreamSocket *)accepted + exception: (id)exception +{ + OFEnsure(!_accepted); + + _accepted = (sock == _expectedServerSocket && accepted != nil && + exception == nil); + + if (_accepted && _connected) + [[OFRunLoop mainRunLoop] stop]; + + return false; +} + +- (void)socket: (OFSPXStreamSocket *)sock + didConnectToNetwork: (uint32_t)network + node: (const unsigned char [IPX_NODE_LEN])node + port: (uint16_t)port + exception: (id)exception +{ + OFEnsure(!_connected); + + _connected = (sock == _expectedClientSocket && + network == _expectedNetwork && + memcmp(node, _expectedNode, IPX_NODE_LEN) == 0 && + port == _expectedPort && exception == nil); + + if (_accepted && _connected) + [[OFRunLoop mainRunLoop] stop]; +} +@end ADDED tests/OFScryptTests.m Index: tests/OFScryptTests.m ================================================================== --- /dev/null +++ tests/OFScryptTests.m @@ -0,0 +1,263 @@ +/* + * 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" + +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFScryptTests: OTTestCase +@end + +/* Test vectors form RFC 7914 */ +static const unsigned char salsa20Input[64] = { + 0x7E, 0x87, 0x9A, 0x21, 0x4F, 0x3E, 0xC9, 0x86, 0x7C, 0xA9, 0x40, 0xE6, + 0x41, 0x71, 0x8F, 0x26, 0xBA, 0xEE, 0x55, 0x5B, 0x8C, 0x61, 0xC1, 0xB5, + 0x0D, 0xF8, 0x46, 0x11, 0x6D, 0xCD, 0x3B, 0x1D, 0xEE, 0x24, 0xF3, 0x19, + 0xDF, 0x9B, 0x3D, 0x85, 0x14, 0x12, 0x1E, 0x4B, 0x5A, 0xC5, 0xAA, 0x32, + 0x76, 0x02, 0x1D, 0x29, 0x09, 0xC7, 0x48, 0x29, 0xED, 0xEB, 0xC6, 0x8D, + 0xB8, 0xB8, 0xC2, 0x5E +}; +static const unsigned char salsa20Output[64] = { + 0xA4, 0x1F, 0x85, 0x9C, 0x66, 0x08, 0xCC, 0x99, 0x3B, 0x81, 0xCA, 0xCB, + 0x02, 0x0C, 0xEF, 0x05, 0x04, 0x4B, 0x21, 0x81, 0xA2, 0xFD, 0x33, 0x7D, + 0xFD, 0x7B, 0x1C, 0x63, 0x96, 0x68, 0x2F, 0x29, 0xB4, 0x39, 0x31, 0x68, + 0xE3, 0xC9, 0xE6, 0xBC, 0xFE, 0x6B, 0xC5, 0xB7, 0xA0, 0x6D, 0x96, 0xBA, + 0xE4, 0x24, 0xCC, 0x10, 0x2C, 0x91, 0x74, 0x5C, 0x24, 0xAD, 0x67, 0x3D, + 0xC7, 0x61, 0x8F, 0x81 +}; +static const union { + unsigned char uc[128]; + uint32_t u32[32]; +} blockMixInput = { .uc = { + 0xF7, 0xCE, 0x0B, 0x65, 0x3D, 0x2D, 0x72, 0xA4, 0x10, 0x8C, 0xF5, 0xAB, + 0xE9, 0x12, 0xFF, 0xDD, 0x77, 0x76, 0x16, 0xDB, 0xBB, 0x27, 0xA7, 0x0E, + 0x82, 0x04, 0xF3, 0xAE, 0x2D, 0x0F, 0x6F, 0xAD, 0x89, 0xF6, 0x8F, 0x48, + 0x11, 0xD1, 0xE8, 0x7B, 0xCC, 0x3B, 0xD7, 0x40, 0x0A, 0x9F, 0xFD, 0x29, + 0x09, 0x4F, 0x01, 0x84, 0x63, 0x95, 0x74, 0xF3, 0x9A, 0xE5, 0xA1, 0x31, + 0x52, 0x17, 0xBC, 0xD7, + 0x89, 0x49, 0x91, 0x44, 0x72, 0x13, 0xBB, 0x22, 0x6C, 0x25, 0xB5, 0x4D, + 0xA8, 0x63, 0x70, 0xFB, 0xCD, 0x98, 0x43, 0x80, 0x37, 0x46, 0x66, 0xBB, + 0x8F, 0xFC, 0xB5, 0xBF, 0x40, 0xC2, 0x54, 0xB0, 0x67, 0xD2, 0x7C, 0x51, + 0xCE, 0x4A, 0xD5, 0xFE, 0xD8, 0x29, 0xC9, 0x0B, 0x50, 0x5A, 0x57, 0x1B, + 0x7F, 0x4D, 0x1C, 0xAD, 0x6A, 0x52, 0x3C, 0xDA, 0x77, 0x0E, 0x67, 0xBC, + 0xEA, 0xAF, 0x7E, 0x89 +}}; +static const unsigned char blockMixOutput[128] = { + 0xA4, 0x1F, 0x85, 0x9C, 0x66, 0x08, 0xCC, 0x99, 0x3B, 0x81, 0xCA, 0xCB, + 0x02, 0x0C, 0xEF, 0x05, 0x04, 0x4B, 0x21, 0x81, 0xA2, 0xFD, 0x33, 0x7D, + 0xFD, 0x7B, 0x1C, 0x63, 0x96, 0x68, 0x2F, 0x29, 0xB4, 0x39, 0x31, 0x68, + 0xE3, 0xC9, 0xE6, 0xBC, 0xFE, 0x6B, 0xC5, 0xB7, 0xA0, 0x6D, 0x96, 0xBA, + 0xE4, 0x24, 0xCC, 0x10, 0x2C, 0x91, 0x74, 0x5C, 0x24, 0xAD, 0x67, 0x3D, + 0xC7, 0x61, 0x8F, 0x81, + 0x20, 0xED, 0xC9, 0x75, 0x32, 0x38, 0x81, 0xA8, 0x05, 0x40, 0xF6, 0x4C, + 0x16, 0x2D, 0xCD, 0x3C, 0x21, 0x07, 0x7C, 0xFE, 0x5F, 0x8D, 0x5F, 0xE2, + 0xB1, 0xA4, 0x16, 0x8F, 0x95, 0x36, 0x78, 0xB7, 0x7D, 0x3B, 0x3D, 0x80, + 0x3B, 0x60, 0xE4, 0xAB, 0x92, 0x09, 0x96, 0xE5, 0x9B, 0x4D, 0x53, 0xB6, + 0x5D, 0x2A, 0x22, 0x58, 0x77, 0xD5, 0xED, 0xF5, 0x84, 0x2C, 0xB9, 0xF1, + 0x4E, 0xEF, 0xE4, 0x25 +}; +static const unsigned char ROMixInput[128] = { + 0xF7, 0xCE, 0x0B, 0x65, 0x3D, 0x2D, 0x72, 0xA4, 0x10, 0x8C, 0xF5, 0xAB, + 0xE9, 0x12, 0xFF, 0xDD, 0x77, 0x76, 0x16, 0xDB, 0xBB, 0x27, 0xA7, 0x0E, + 0x82, 0x04, 0xF3, 0xAE, 0x2D, 0x0F, 0x6F, 0xAD, 0x89, 0xF6, 0x8F, 0x48, + 0x11, 0xD1, 0xE8, 0x7B, 0xCC, 0x3B, 0xD7, 0x40, 0x0A, 0x9F, 0xFD, 0x29, + 0x09, 0x4F, 0x01, 0x84, 0x63, 0x95, 0x74, 0xF3, 0x9A, 0xE5, 0xA1, 0x31, + 0x52, 0x17, 0xBC, 0xD7, 0x89, 0x49, 0x91, 0x44, 0x72, 0x13, 0xBB, 0x22, + 0x6C, 0x25, 0xB5, 0x4D, 0xA8, 0x63, 0x70, 0xFB, 0xCD, 0x98, 0x43, 0x80, + 0x37, 0x46, 0x66, 0xBB, 0x8F, 0xFC, 0xB5, 0xBF, 0x40, 0xC2, 0x54, 0xB0, + 0x67, 0xD2, 0x7C, 0x51, 0xCE, 0x4A, 0xD5, 0xFE, 0xD8, 0x29, 0xC9, 0x0B, + 0x50, 0x5A, 0x57, 0x1B, 0x7F, 0x4D, 0x1C, 0xAD, 0x6A, 0x52, 0x3C, 0xDA, + 0x77, 0x0E, 0x67, 0xBC, 0xEA, 0xAF, 0x7E, 0x89 +}; +static const unsigned char ROMixOutput[128] = { + 0x79, 0xCC, 0xC1, 0x93, 0x62, 0x9D, 0xEB, 0xCA, 0x04, 0x7F, 0x0B, 0x70, + 0x60, 0x4B, 0xF6, 0xB6, 0x2C, 0xE3, 0xDD, 0x4A, 0x96, 0x26, 0xE3, 0x55, + 0xFA, 0xFC, 0x61, 0x98, 0xE6, 0xEA, 0x2B, 0x46, 0xD5, 0x84, 0x13, 0x67, + 0x3B, 0x99, 0xB0, 0x29, 0xD6, 0x65, 0xC3, 0x57, 0x60, 0x1F, 0xB4, 0x26, + 0xA0, 0xB2, 0xF4, 0xBB, 0xA2, 0x00, 0xEE, 0x9F, 0x0A, 0x43, 0xD1, 0x9B, + 0x57, 0x1A, 0x9C, 0x71, 0xEF, 0x11, 0x42, 0xE6, 0x5D, 0x5A, 0x26, 0x6F, + 0xDD, 0xCA, 0x83, 0x2C, 0xE5, 0x9F, 0xAA, 0x7C, 0xAC, 0x0B, 0x9C, 0xF1, + 0xBE, 0x2B, 0xFF, 0xCA, 0x30, 0x0D, 0x01, 0xEE, 0x38, 0x76, 0x19, 0xC4, + 0xAE, 0x12, 0xFD, 0x44, 0x38, 0xF2, 0x03, 0xA0, 0xE4, 0xE1, 0xC4, 0x7E, + 0xC3, 0x14, 0x86, 0x1F, 0x4E, 0x90, 0x87, 0xCB, 0x33, 0x39, 0x6A, 0x68, + 0x73, 0xE8, 0xF9, 0xD2, 0x53, 0x9A, 0x4B, 0x8E +}; +static const unsigned char testVector1[64] = { + 0x77, 0xD6, 0x57, 0x62, 0x38, 0x65, 0x7B, 0x20, 0x3B, 0x19, 0xCA, 0x42, + 0xC1, 0x8A, 0x04, 0x97, 0xF1, 0x6B, 0x48, 0x44, 0xE3, 0x07, 0x4A, 0xE8, + 0xDF, 0xDF, 0xFA, 0x3F, 0xED, 0xE2, 0x14, 0x42, 0xFC, 0xD0, 0x06, 0x9D, + 0xED, 0x09, 0x48, 0xF8, 0x32, 0x6A, 0x75, 0x3A, 0x0F, 0xC8, 0x1F, 0x17, + 0xE8, 0xD3, 0xE0, 0xFB, 0x2E, 0x0D, 0x36, 0x28, 0xCF, 0x35, 0xE2, 0x0C, + 0x38, 0xD1, 0x89, 0x06 +}; +/* Nintendo DS does not have enough RAM for the second test vector. */ +#ifndef OF_NINTENDO_DS +static const unsigned char testVector2[64] = { + 0xFD, 0xBA, 0xBE, 0x1C, 0x9D, 0x34, 0x72, 0x00, 0x78, 0x56, 0xE7, 0x19, + 0x0D, 0x01, 0xE9, 0xFE, 0x7C, 0x6A, 0xD7, 0xCB, 0xC8, 0x23, 0x78, 0x30, + 0xE7, 0x73, 0x76, 0x63, 0x4B, 0x37, 0x31, 0x62, 0x2E, 0xAF, 0x30, 0xD9, + 0x2E, 0x22, 0xA3, 0x88, 0x6F, 0xF1, 0x09, 0x27, 0x9D, 0x98, 0x30, 0xDA, + 0xC7, 0x27, 0xAF, 0xB9, 0x4A, 0x83, 0xEE, 0x6D, 0x83, 0x60, 0xCB, 0xDF, + 0xA2, 0xCC, 0x06, 0x40 +}; +#endif +/* + * The third test vector is too expensive for m68k. + * Nintendo DS does not have enough RAM for the third test vector. + */ +#if !defined(OF_M68K) && !defined(OF_NINTENDO_DS) +static const unsigned char testVector3[64] = { + 0x70, 0x23, 0xBD, 0xCB, 0x3A, 0xFD, 0x73, 0x48, 0x46, 0x1C, 0x06, 0xCD, + 0x81, 0xFD, 0x38, 0xEB, 0xFD, 0xA8, 0xFB, 0xBA, 0x90, 0x4F, 0x8E, 0x3E, + 0xA9, 0xB5, 0x43, 0xF6, 0x54, 0x5D, 0xA1, 0xF2, 0xD5, 0x43, 0x29, 0x55, + 0x61, 0x3F, 0x0F, 0xCF, 0x62, 0xD4, 0x97, 0x05, 0x24, 0x2A, 0x9A, 0xF9, + 0xE6, 0x1E, 0x85, 0xDC, 0x0D, 0x65, 0x1E, 0x40, 0xDF, 0xCF, 0x01, 0x7B, + 0x45, 0x57, 0x58, 0x87 +}; +#endif +/* The forth test vector is too expensive to include it in the tests. */ +#if 0 +static const unsigned char testVector4[64] = { + 0x21, 0x01, 0xCB, 0x9B, 0x6A, 0x51, 0x1A, 0xAE, 0xAD, 0xDB, 0xBE, 0x09, + 0xCF, 0x70, 0xF8, 0x81, 0xEC, 0x56, 0x8D, 0x57, 0x4A, 0x2F, 0xFD, 0x4D, + 0xAB, 0xE5, 0xEE, 0x98, 0x20, 0xAD, 0xAA, 0x47, 0x8E, 0x56, 0xFD, 0x8F, + 0x4B, 0xA5, 0xD0, 0x9F, 0xFA, 0x1C, 0x6D, 0x92, 0x7C, 0x40, 0xF4, 0xC3, + 0x37, 0x30, 0x40, 0x49, 0xE8, 0xA9, 0x52, 0xFB, 0xCB, 0xF4, 0x5C, 0x6F, + 0xA7, 0x7A, 0x41, 0xA4 +}; +#endif + +@implementation OFScryptTests +- (void)testSalsa20_8Core +{ + uint32_t salsa20Buffer[16]; + + memcpy(salsa20Buffer, salsa20Input, 64); + OFSalsa20_8Core(salsa20Buffer); + OTAssertEqual(memcmp(salsa20Buffer, salsa20Output, 64), 0); +} + +- (void)testBlockMix +{ + uint32_t blockMixBuffer[32]; + + OFScryptBlockMix(blockMixBuffer, blockMixInput.u32, 1); + OTAssertEqual(memcmp(blockMixBuffer, blockMixOutput, 128), 0); +} + +- (void)testROMix +{ + uint32_t ROMixBuffer[32], ROMixTmp[17 * 32]; + + memcpy(ROMixBuffer, ROMixInput, 128); + OFScryptROMix(ROMixBuffer, 1, 16, ROMixTmp); + OTAssertEqual(memcmp(ROMixBuffer, ROMixOutput, 128), 0); +} + +- (void)testRFC7941TestVector1 +{ + unsigned char output[64]; + + OFScrypt((OFScryptParameters){ + .blockSize = 1, + .costFactor = 16, + .parallelization = 1, + .salt = (unsigned char *)"", + .saltLength = 0, + .password = "", + .passwordLength = 0, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + }); + + OTAssertEqual(memcmp(output, testVector1, 64), 0); +} + +/* Nintendo DS does not have enough RAM for the second test vector. */ +#ifndef OF_NINTENDO_DS +- (void)testRFC7941TestVector2 +{ + unsigned char output[64]; + + OFScrypt((OFScryptParameters){ + .blockSize = 8, + .costFactor = 1024, + .parallelization = 16, + .salt = (unsigned char *)"NaCl", + .saltLength = 4, + .password = "password", + .passwordLength = 8, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + }); + + OTAssertEqual(memcmp(output, testVector2, 64), 0); +} +#endif + +/* + * The third test vector is too expensive for m68k. + * Nintendo DS does not have enough RAM for the third test vector. + */ +#if !defined(OF_M68K) && !defined(OF_NINTENDO_DS) +- (void)testRFC7941TestVector3 +{ + unsigned char output[64]; + + OFScrypt((OFScryptParameters){ + .blockSize = 8, + .costFactor = 16384, + .parallelization = 1, + .salt = (unsigned char *)"SodiumChloride", + .saltLength = 14, + .password = "pleaseletmein", + .passwordLength = 13, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + }); + + OTAssertEqual(memcmp(output, testVector3, 64), 0); +} +#endif + +/* The forth test vector is too expensive to include it in the tests. */ +#if 0 +- (void)testRFC7941TestVector4 +{ + unsigned char output[64]; + + OFScrypt((OFScryptParameters){ + .blockSize = 8, + .costFactor = 1048576, + .parallelization = 1, + .salt = (unsigned char *)"SodiumChloride", + .saltLength = 14, + .password = "pleaseletmein", + .passwordLength = 13, + .key = output, + .keyLength = 64, + .allowsSwappableMemory = true + }); + + OTAssertEqual(memcmp(output, testVector4, 64), 0); +} +#endif +@end ADDED tests/OFSetTests.h Index: tests/OFSetTests.h ================================================================== --- /dev/null +++ tests/OFSetTests.h @@ -0,0 +1,25 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFSetTests: OTTestCase +{ + OFSet *_set; +} + +@property (readonly, nonatomic) Class setClass; +@end ADDED tests/OFSetTests.m Index: tests/OFSetTests.m ================================================================== --- /dev/null +++ tests/OFSetTests.m @@ -0,0 +1,226 @@ +/* + * 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 "OFSetTests.h" + +@interface CustomSet: OFSet +{ + OFSet *_set; +} +@end + +@implementation OFSetTests +- (Class)setClass +{ + return [CustomSet class]; +} + +- (void)setUp +{ + [super setUp]; + + _set = [[OFSet alloc] initWithObjects: @"foo", @"bar", @"baz", nil]; +} + +- (void)dealloc +{ + [_set release]; + + [super dealloc]; +} + +- (void)testSetWithArray +{ + OTAssertEqualObjects([self.setClass setWithArray: + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", @"foo", nil])], + _set); +} + +- (void)testIsEqual +{ + OTAssertEqualObjects(_set, + ([OFSet setWithObjects: @"foo", @"bar", @"baz", nil])); +} + +- (void)testHash +{ + OTAssertEqual(_set.hash, + [([OFSet setWithObjects: @"foo", @"bar", @"baz", nil]) hash]); +} + +- (void)testDescription +{ + OFString *description = _set.description; + + OTAssert( + [description isEqual: @"{(\n\tfoo,\n\tbar,\n\tbaz\n)}"] || + [description isEqual: @"{(\n\tfoo,\n\tbaz,\n\tbar\n)}"] || + [description isEqual: @"{(\n\tbar,\n\tfoo,\n\tbaz\n)}"] || + [description isEqual: @"{(\n\tbar,\n\tbaz,\n\tfoo\n)}"] || + [description isEqual: @"{(\n\tbaz,\n\tfoo,\n\tbar\n)}"] || + [description isEqual: @"{(\n\tbaz,\n\tbar,\n\tfoo\n)}"]); +} + +- (void)testCopy +{ + OTAssertEqualObjects([[_set copy] autorelease], _set); +} + +- (void)testIsSubsetOfSet +{ + OTAssertTrue([([OFSet setWithObjects: @"foo", nil]) + isSubsetOfSet: _set]); + OTAssertFalse([([OFSet setWithObjects: @"foo", @"Foo", nil]) + isSubsetOfSet: _set]); +} + +- (void)testIntersectsSet +{ + OTAssertTrue([([OFSet setWithObjects: @"foo", @"Foo", nil]) + intersectsSet: _set]); + OTAssertFalse([([OFSet setWithObjects: @"Foo", nil]) + intersectsSet: _set]); +} + +- (void)testEnumerator +{ + OFEnumerator *enumerator = [_set objectEnumerator]; + bool seenFoo = false, seenBar = false, seenBaz = false; + OFString *object; + + while ((object = [enumerator nextObject]) != nil) { + if ([object isEqual: @"foo"]) { + OTAssertFalse(seenFoo); + seenFoo = true; + } else if ([object isEqual: @"bar"]) { + OTAssertFalse(seenBar); + seenBar = true; + } else if ([object isEqual: @"baz"]) { + OTAssertFalse(seenBaz); + seenBaz = true; + } else + OTAssert(false, @"Unexpected object seen: %@", object); + } + + OTAssert(seenFoo && seenBar && seenBaz); +} + +- (void)testFastEnumeration +{ + bool seenFoo = false, seenBar = false, seenBaz = false; + + for (OFString *object in _set) { + if ([object isEqual: @"foo"]) { + OTAssertFalse(seenFoo); + seenFoo = true; + } else if ([object isEqual: @"bar"]) { + OTAssertFalse(seenBar); + seenBar = true; + } else if ([object isEqual: @"baz"]) { + OTAssertFalse(seenBaz); + seenBaz = true; + } else + OTAssert(false, @"Unexpected object seen: %@", object); + } + + OTAssert(seenFoo && seenBar && seenBaz); +} + +#ifdef OF_HAVE_BLOCKS +- (void)testEnumerateObjectsUsingBlock +{ + __block bool seenFoo = false, seenBar = false, seenBaz = false; + + [_set enumerateObjectsUsingBlock: ^ (id object, bool *stop) { + if ([object isEqual: @"foo"]) { + OTAssertFalse(seenFoo); + seenFoo = true; + } else if ([object isEqual: @"bar"]) { + OTAssertFalse(seenBar); + seenBar = true; + } else if ([object isEqual: @"baz"]) { + OTAssertFalse(seenBaz); + seenBaz = true; + } else + OTAssert(false, @"Unexpected object seen: %@", object); + }]; + + OTAssert(seenFoo && seenBar && seenBaz); +} + +- (void)testFilteredSetUsingBlock +{ + OFSet *filteredSet = [_set filteredSetUsingBlock: ^ (id object) { + return [object hasPrefix: @"ba"]; + }]; + + OTAssertEqualObjects(filteredSet, + ([OFSet setWithObjects: @"bar", @"baz", nil])); +} +#endif + +- (void)testValueForKey +{ + OFSet *set = [[self.setClass setWithObjects: + @"a", @"ab", @"abc", @"b", nil] valueForKey: @"length"]; + + OTAssertEqualObjects(set, ([OFSet setWithObjects: + [OFNumber numberWithInt: 1], [OFNumber numberWithInt: 2], + [OFNumber numberWithInt: 3], nil])); + + OTAssertEqualObjects([set valueForKey: @"@count"], + [OFNumber numberWithInt: 3]); +} +@end + +@implementation CustomSet +- (instancetype)initWithObjects: (id const *)objects count: (size_t)count +{ + self = [super init]; + + @try { + _set = [[OFSet alloc] initWithObjects: objects count: count]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_set release]; + + [super dealloc]; +} + +- (size_t)count +{ + return _set.count; +} + +- (bool)containsObject: (id)object +{ + return [_set containsObject: object]; +} + +- (OFEnumerator *)objectEnumerator +{ + return [_set objectEnumerator]; +} +@end ADDED tests/OFSocketTests.m Index: tests/OFSocketTests.m ================================================================== --- /dev/null +++ tests/OFSocketTests.m @@ -0,0 +1,252 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFSocketTests: OTTestCase +@end + +#define COMPARE_V6(a, a0, a1, a2, a3, a4, a5, a6, a7) \ + (a.sockaddr.in6.sin6_addr.s6_addr[0] == (a0 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[1] == (a0 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[2] == (a1 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[3] == (a1 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[4] == (a2 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[5] == (a2 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[6] == (a3 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[7] == (a3 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[8] == (a4 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[9] == (a4 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[10] == (a5 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[11] == (a5 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[12] == (a6 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[13] == (a6 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[14] == (a7 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[15] == (a7 & 0xFF)) +#define SET_V6(a, a0, a1, a2, a3, a4, a5, a6, a7) \ + a.sockaddr.in6.sin6_addr.s6_addr[0] = a0 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[1] = a0 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[2] = a1 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[3] = a1 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[4] = a2 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[5] = a2 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[6] = a3 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[7] = a3 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[8] = a4 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[9] = a4 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF; + +@implementation OFSocketTests +- (void)testParseIPv4 +{ + OFSocketAddress address = OFSocketAddressParseIP(@"127.0.0.1", 1234); + + OTAssertEqual(OFFromBigEndian32(address.sockaddr.in.sin_addr.s_addr), + 0x7F000001); + OTAssertEqual(OFFromBigEndian16(address.sockaddr.in.sin_port), 1234); +} + +- (void)testParseRejectsInvalidIPv4 +{ + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.0.0.1", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.0.256", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.0. 1", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@" 127.0.0.1", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.a.1", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0..1", 1234), + OFInvalidFormatException); +} + +- (void)testPortForIPv4 +{ + OFSocketAddress address = OFSocketAddressParseIP(@"127.0.0.1", 1234); + + OTAssertEqual(OFSocketAddressIPPort(&address), 1234); +} + +- (void)testStringForIPv4 +{ + OFSocketAddress address = OFSocketAddressParseIP(@"127.0.0.1", 1234); + + OTAssertEqualObjects(OFSocketAddressString(&address), @"127.0.0.1"); +} + +- (void)testParseIPv6 +{ + OFSocketAddress address; + + address = OFSocketAddressParseIP( + @"1122:3344:5566:7788:99aa:bbCc:ddee:ff00", 1234); + OTAssert(COMPARE_V6(address, + 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00)); + OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); + + address = OFSocketAddressParseIP(@"::", 1234); + OTAssert(COMPARE_V6(address, 0, 0, 0, 0, 0, 0, 0, 0)); + OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); + + address = OFSocketAddressParseIP(@"aaAa::bBbb", 1234); + OTAssert(COMPARE_V6(address, 0xAAAA, 0, 0, 0, 0, 0, 0, 0xBBBB)); + OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); + + address = OFSocketAddressParseIP(@"aaAa::", 1234); + OTAssert(COMPARE_V6(address, 0xAAAA, 0, 0, 0, 0, 0, 0, 0)); + OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); + + address = OFSocketAddressParseIP(@"::aaAa", 1234); + OTAssert(COMPARE_V6(address, 0, 0, 0, 0, 0, 0, 0, 0xAAAA)); + OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); + + address = OFSocketAddressParseIP(@"fd00::1%123", 1234); + OTAssert(COMPARE_V6(address, 0xFD00, 0, 0, 0, 0, 0, 0, 1)); + OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); + OTAssertEqual(address.sockaddr.in6.sin6_scope_id, 123); + + address = OFSocketAddressParseIP(@"::ffff:127.0.0.1", 1234); + OTAssert(COMPARE_V6(address, 0, 0, 0, 0, 0, 0xFFFF, 0x7F00, 1)); + OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); + + address = OFSocketAddressParseIP(@"64:ff9b::127.0.0.1", 1234); + OTAssert(COMPARE_V6(address, 0x64, 0xFF9B, 0, 0, 0, 0, 0x7F00, 1)); + OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234); +} + +- (void)testParseRejectsInvalidIPv6 +{ + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:::2", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1: ::2", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:: :2", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1::2::3", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"10000::1", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"::10000", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"::1::", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:2:3:4:5:6:7:", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:2:3:4:5:6:7::", 1234), + OFInvalidFormatException); + + OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:2", 1234), + OFInvalidFormatException); +} + +- (void)testPortForIPv6 +{ + OFSocketAddress address = OFSocketAddressParseIP(@"::", 1234); + + OTAssertEqual(OFSocketAddressIPPort(&address), 1234); +} + +- (void)testStringForIPv6 +{ + OFSocketAddress address = OFSocketAddressParseIP(@"::", 1234); + + OTAssertEqualObjects(OFSocketAddressString(&address), @"::"); + + SET_V6(address, 0, 0, 0, 0, 0, 0, 0, 1) + OTAssertEqualObjects(OFSocketAddressString(&address), @"::1"); + + SET_V6(address, 1, 0, 0, 0, 0, 0, 0, 0) + OTAssertEqualObjects(OFSocketAddressString(&address), @"1::"); + + SET_V6(address, + 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) + OTAssertEqualObjects(OFSocketAddressString(&address), + @"1122:3344:5566:7788:99aa:bbcc:ddee:ff00"); + + SET_V6(address, + 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0) + OTAssertEqualObjects(OFSocketAddressString(&address), + @"1122:3344:5566:7788:99aa:bbcc:ddee:0"); + + SET_V6(address, 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0) + OTAssertEqualObjects(OFSocketAddressString(&address), + @"1122:3344:5566:7788:99aa:bbcc::"); + + SET_V6(address, + 0, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) + OTAssertEqualObjects(OFSocketAddressString(&address), + @"0:3344:5566:7788:99aa:bbcc:ddee:ff00"); + + SET_V6(address, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) + OTAssertEqualObjects(OFSocketAddressString(&address), + @"::5566:7788:99aa:bbcc:ddee:ff00"); + + SET_V6(address, 0, 0, 0x5566, 0, 0, 0, 0xDDEE, 0xFF00) + OTAssertEqualObjects(OFSocketAddressString(&address), + @"0:0:5566::ddee:ff00"); + + SET_V6(address, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0) + OTAssertEqualObjects(OFSocketAddressString(&address), + @"::5566:7788:99aa:bbcc:0:0"); + + address.sockaddr.in6.sin6_scope_id = 123; + OTAssertEqualObjects(OFSocketAddressString(&address), + @"::5566:7788:99aa:bbcc:0:0%123"); +} + +- (void)testAddressEqual +{ + OFSocketAddress addr1 = OFSocketAddressParseIP(@"127.0.0.1", 1234); + OFSocketAddress addr2 = OFSocketAddressParseIP(@"127.0.0.1", 1234); + OFSocketAddress addr3 = OFSocketAddressParseIP(@"127.0.0.1", 1235); + + OTAssertTrue(OFSocketAddressEqual(&addr1, &addr2)); + OTAssertFalse(OFSocketAddressEqual(&addr1, &addr3)); +} + +- (void)testAddressHash +{ + OFSocketAddress addr1 = OFSocketAddressParseIP(@"127.0.0.1", 1234); + OFSocketAddress addr2 = OFSocketAddressParseIP(@"127.0.0.1", 1234); + OFSocketAddress addr3 = OFSocketAddressParseIP(@"127.0.0.1", 1235); + + OTAssertEqual(OFSocketAddressHash(&addr1), OFSocketAddressHash(&addr2)); + OTAssertNotEqual(OFSocketAddressHash(&addr1), + OFSocketAddressHash(&addr3)); +} +@end ADDED tests/OFStreamTests.m Index: tests/OFStreamTests.m ================================================================== --- /dev/null +++ tests/OFStreamTests.m @@ -0,0 +1,87 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFStreamTests: OTTestCase +@end + +@interface OFTestStream: OFStream +{ + int _state; +} +@end + +@implementation OFStreamTests +- (void)testStream +{ + size_t pageSize = [OFSystemInfo pageSize]; + OFTestStream *stream = [[[OFTestStream alloc] init] autorelease]; + char *cString = OFAllocMemory(pageSize - 2, 1); + + @try { + OFString *string; + + memset(cString, 'X', pageSize - 3); + cString[pageSize - 3] = '\0'; + + OTAssertEqualObjects([stream readLine], @"foo"); + + string = [stream readLine]; + OTAssertNotNil(string); + OTAssertEqual(string.length, pageSize - 3); + OTAssertEqual(strcmp(string.UTF8String, cString), 0); + } @finally { + OFFreeMemory(cString); + } +} +@end + +@implementation OFTestStream +- (bool)lowlevelIsAtEndOfStream +{ + return (_state > 1); +} + +- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)size +{ + size_t pageSize = [OFSystemInfo pageSize]; + + switch (_state) { + case 0: + if (size < 1) + return 0; + + memcpy(buffer, "f", 1); + + _state++; + return 1; + case 1: + if (size < pageSize) + return 0; + + memcpy(buffer, "oo\n", 3); + memset((char *)buffer + 3, 'X', pageSize - 3); + + _state++; + return pageSize; + } + + return 0; +} +@end ADDED tests/OFStringTests.h Index: tests/OFStringTests.h ================================================================== --- /dev/null +++ tests/OFStringTests.h @@ -0,0 +1,25 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFStringTests: OTTestCase +{ + OFString *_string; +} + +@property (readonly, nonatomic) Class stringClass; +@end ADDED tests/OFStringTests.m Index: tests/OFStringTests.m ================================================================== --- /dev/null +++ tests/OFStringTests.m @@ -0,0 +1,1661 @@ +/* + * 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" + +#include +#include +#include + +#import "OFStringTests.h" + +#ifndef INFINITY +# define INFINITY __builtin_inf() +#endif + +static const OFUnichar unicharString[] = { + 0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0x1F03A, 0 +}; +static const OFUnichar swappedUnicharString[] = { + 0xFFFE0000, 0x66000000, 0xF6000000, 0xF6000000, 0x62000000, 0xE4000000, + 0x72000000, 0x3AF00100, 0 +}; +static const OFChar16 char16String[] = { + 0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0xD83C, 0xDC3A, 0 +}; +static const OFChar16 swappedChar16String[] = { + 0xFFFE, 0x6600, 0xF600, 0xF600, 0x6200, 0xE400, 0x7200, 0x3CD8, 0x3ADC, + 0 +}; + +@interface CustomString: OFString +{ + OFMutableString *_string; +} +@end + +@interface CustomMutableString: OFMutableString +{ + OFMutableString *_string; +} +@end + +@interface EntityHandler: OFObject +@end + +@implementation OFStringTests +- (Class)stringClass +{ + return [CustomString class]; +} + +- (void)setUp +{ + [super setUp]; + + _string = [[self.stringClass alloc] initWithString: @"täṠ€🤔"]; +} + +- (void)dealloc +{ + [_string release]; + + [super dealloc]; +} + +- (void)testIsEqual +{ + OTAssertEqualObjects(_string, @"täṠ€🤔"); + OTAssertEqualObjects(@"täṠ€🤔", _string); + OTAssertNotEqualObjects([self.stringClass stringWithString: @"test"], + @"täṠ€🤔"); + OTAssertNotEqualObjects(@"täṠ€🤔", + [self.stringClass stringWithString: @"test"]); +} + +- (void)testHash +{ + OTAssertEqual(_string.hash, @"täṠ€🤔".hash); + OTAssertNotEqual([[self.stringClass stringWithString: @"test"] hash], + @"täṠ€".hash); +} + +- (void)testCompare +{ + OTAssertEqual([_string compare: @"täṠ€🤔"], OFOrderedSame); + OTAssertEqual([[self.stringClass stringWithString: @""] + compare: @"a"], OFOrderedAscending); + OTAssertEqual([[self.stringClass stringWithString: @"a"] + compare: @"b"], OFOrderedAscending); + OTAssertEqual([[self.stringClass stringWithString: @"cd"] + compare: @"bc"], OFOrderedDescending); + OTAssertEqual([[self.stringClass stringWithString: @"ä"] + compare: @"ö"], OFOrderedAscending); + OTAssertEqual([[self.stringClass stringWithString: @"€"] + compare: @"ß"], OFOrderedDescending); + OTAssertEqual([[self.stringClass stringWithString: @"aa"] + compare: @"z"], OFOrderedAscending); + OTAssertEqual([@"aa" compare: + [self.stringClass stringWithString: @"z"]], OFOrderedAscending); +} + +- (void)testCaseInsensitiveCompare +{ +#ifdef OF_HAVE_UNICODE_TABLES + OTAssertEqual([[self.stringClass stringWithString: @"a"] + caseInsensitiveCompare: @"A"], OFOrderedSame); + OTAssertEqual([[self.stringClass stringWithString: @"Ä"] + caseInsensitiveCompare: @"ä"], OFOrderedSame); + OTAssertEqual([[self.stringClass stringWithString: @"я"] + caseInsensitiveCompare: @"Я"], OFOrderedSame); + OTAssertEqual([[self.stringClass stringWithString: @"€"] + caseInsensitiveCompare: @"ß"], OFOrderedDescending); + OTAssertEqual([[self.stringClass stringWithString: @"ß"] + caseInsensitiveCompare: @"→"], OFOrderedAscending); + OTAssertEqual([[self.stringClass stringWithString: @"AA"] + caseInsensitiveCompare: @"z"], OFOrderedAscending); + OTAssertEqual([[self.stringClass stringWithString: @"ABC"] + caseInsensitiveCompare: @"AbD"], OFOrderedAscending); +#else + OTAssertEqual([[self.stringClass stringWithString: @"a"] + caseInsensitiveCompare: @"A"], OFOrderedSame); + OTAssertEqual([[self.stringClass stringWithString: @"AA"] + caseInsensitiveCompare: @"z"], OFOrderedAscending); + OTAssertEqual([[self.stringClass stringWithString: @"ABC"] + caseInsensitiveCompare: @"AbD"], OFOrderedAscending); +#endif +} + +- (void)testDescription +{ + OTAssertEqualObjects(_string.description, @"täṠ€🤔"); +} + +- (void)testLength +{ + OTAssertEqual(_string.length, 5); +} + +- (void)testUTF8StringLength +{ + OTAssertEqual(_string.UTF8StringLength, 13); +} + +- (void)testCharacterAtIndex +{ + OTAssertEqual([_string characterAtIndex: 0], 't'); + OTAssertEqual([_string characterAtIndex: 1], 0xE4); + OTAssertEqual([_string characterAtIndex: 2], 0x1E60); + OTAssertEqual([_string characterAtIndex: 3], 0x20AC); + OTAssertEqual([_string characterAtIndex: 4], 0x1F914); +} + +- (void)testCharacterAtIndexFailsWithOutOfRangeIndex +{ + OTAssertThrowsSpecific([_string characterAtIndex: 5], + OFOutOfRangeException); +} + +- (void)testUppercaseString +{ +#ifdef OF_HAVE_UNICODE_TABLES + OTAssertEqualObjects(_string.uppercaseString, @"TÄṠ€🤔"); +#else + OTAssertEqualObjects(_string.uppercaseString, @"TäṠ€🤔"); +#endif +} + +- (void)testLowercaseString +{ +#ifdef OF_HAVE_UNICODE_TABLES + OTAssertEqualObjects(_string.lowercaseString, @"täṡ€🤔"); +#else + OTAssertEqualObjects(_string.lowercaseString, @"täṠ€🤔"); +#endif +} + +- (void)testCapitalizedString +{ +#ifdef OF_HAVE_UNICODE_TABLES + OTAssertEqualObjects([[self.stringClass stringWithString: + @"täṠ€🤔täṠ€🤔 täṠ€🤔"] capitalizedString], @"Täṡ€🤔täṡ€🤔 Täṡ€🤔"); +#else + OTAssertEqualObjects([[self.stringClass stringWithString: + @"täṠ€🤔täṠ€🤔 täṠ€🤔"] capitalizedString], @"TäṠ€🤔täṠ€🤔 TäṠ€🤔"); +#endif +} + +- (void)testStringWithUTF8StringLength +{ + OTAssertEqualObjects([self.stringClass + stringWithUTF8String: "\xEF\xBB\xBF" "foobar" + length: 6], @"foo"); +} + +- (void)testStringWithUTF16String +{ + OTAssertEqualObjects([self.stringClass + stringWithUTF16String: char16String], @"fööbär🀺"); + OTAssertEqualObjects([self.stringClass + stringWithUTF16String: swappedChar16String], @"fööbär🀺"); +} + +- (void)testStringWithUTF32String +{ + OTAssertEqualObjects([self.stringClass + stringWithUTF32String: unicharString], @"fööbär🀺"); + OTAssertEqualObjects([self.stringClass + stringWithUTF32String: swappedUnicharString], @"fööbär🀺"); +} + +- (void)testStringWithUTF8StringFailsWithInvalidUTF8 +{ + OTAssertThrowsSpecific( + [self.stringClass stringWithUTF8String: "\xE0\x80"], + OFInvalidEncodingException); + + OTAssertThrowsSpecific( + [self.stringClass stringWithUTF8String: "\xF0\x80\x80\xC0"], + OFInvalidEncodingException); +} + +- (void)testStringWithCStringEncodingISO8859_1 +{ + OTAssertEqualObjects([self.stringClass + stringWithCString: "\xE4\xF6\xFC" + encoding: OFStringEncodingISO8859_1], @"äöü"); +} + +#ifdef HAVE_ISO_8859_15 +- (void)testStringWithCStringEncodingISO8859_15 +{ + OTAssertEqualObjects([self.stringClass + stringWithCString: "\xA4\xA6\xA8\xB4\xB8\xBC\xBD\xBE" + encoding: OFStringEncodingISO8859_15], @"€ŠšŽžŒœŸ"); +} +#endif + +#ifdef HAVE_WINDOWS_1252 +- (void)testStringWithCStringEncodingWindows1252 +{ + OTAssertEqualObjects([self.stringClass + stringWithCString: "\x80\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B" + "\x8C\x8E\x91\x92\x93\x94\x95\x96\x97\x98\x99" + "\x9A\x9B\x9C\x9E\x9F" + encoding: OFStringEncodingWindows1252], + @"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ"); +} +#endif + +#ifdef HAVE_CODEPAGE_437 +- (void)testStringWithCStringEncodingCodepage437 +{ + OTAssertEqualObjects([self.stringClass + stringWithCString: "\xB0\xB1\xB2\xDB" + encoding: OFStringEncodingCodepage437], @"░▒▓█"); +} +#endif + +#ifdef OF_HAVE_FILES +- (void)testStringWithContentsOfFileEncoding +{ + OTAssertEqualObjects([self.stringClass + stringWithContentsOfFile: @"testfile.txt" + encoding: OFStringEncodingISO8859_1], @"testäöü"); +} + +- (void)testStringWithContentsOfIRIEncoding +{ + OTAssertEqualObjects([self.stringClass + stringWithContentsOfIRI: [OFIRI fileIRIWithPath: @"testfile.txt"] + encoding: OFStringEncodingISO8859_1], @"testäöü"); +} +#endif + +- (void)testCStringWithEncodingASCII +{ + OTAssertEqual(strcmp([[self.stringClass stringWithString: + @"This is a test"] cStringWithEncoding: OFStringEncodingASCII], + "This is a test"), 0); + + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"This is a tést"] cStringWithEncoding: OFStringEncodingASCII], + OFInvalidEncodingException); +} + +- (void)testCStringWithEncodingISO8859_1 +{ + OTAssertEqual(strcmp([[self.stringClass stringWithString: + @"This is ä test"] cStringWithEncoding: OFStringEncodingISO8859_1], + "This is \xE4 test"), 0); + + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"This is ä t€st"] cStringWithEncoding: OFStringEncodingISO8859_1], + OFInvalidEncodingException); +} + +#ifdef HAVE_ISO_8859_15 +- (void)testCStringWithEncodingISO8859_15 +{ + OTAssertEqual(strcmp([[self.stringClass stringWithString: + @"This is ä t€st"] cStringWithEncoding: OFStringEncodingISO8859_15], + "This is \xE4 t\xA4st"), 0); + + OTAssertThrowsSpecific( + [[self.stringClass stringWithString: @"This is ä t€st…"] + cStringWithEncoding: OFStringEncodingISO8859_15], + OFInvalidEncodingException); +} +#endif + +#ifdef HAVE_WINDOWS_1252 +- (void)testCStringWithEncodingWindows1252 +{ + OTAssertEqual( + strcmp([[self.stringClass stringWithString: @"This is ä t€st…"] + cStringWithEncoding: OFStringEncodingWindows1252], + "This is \xE4 t\x80st\x85"), 0); + + OTAssertThrowsSpecific( + [[self.stringClass stringWithString: @"This is ä t€st…‼"] + cStringWithEncoding: OFStringEncodingWindows1252], + OFInvalidEncodingException); +} +#endif + +#ifdef HAVE_CODEPAGE_437 +- (void)testCStringWithEncodingCodepage437 +{ + OTAssertEqual( + strcmp([[self.stringClass stringWithString: @"Tést strîng ░▒▓"] + cStringWithEncoding: OFStringEncodingCodepage437], + "T\x82st str\x8Cng \xB0\xB1\xB2"), 0); + + OTAssertThrowsSpecific( + [[self.stringClass stringWithString: @"T€st strîng ░▒▓"] + cStringWithEncoding: OFStringEncodingCodepage437], + OFInvalidEncodingException); +} +#endif + +- (void)testLossyCStringWithEncodingASCII +{ + OTAssertEqual(strcmp([[self.stringClass stringWithString: + @"This is a tést"] lossyCStringWithEncoding: OFStringEncodingASCII], + "This is a t?st"), 0); +} + +- (void)testLossyCStringWithEncodingISO8859_1 +{ + OTAssertEqual( + strcmp([[self.stringClass stringWithString: @"This is ä t€st"] + lossyCStringWithEncoding: OFStringEncodingISO8859_1], + "This is \xE4 t?st"), 0); +} + +#ifdef HAVE_ISO_8859_15 +- (void)testLossyCStringWithEncodingISO8859_15 +{ + OTAssertEqual( + strcmp([[self.stringClass stringWithString: @"This is ä t€st…"] + lossyCStringWithEncoding: OFStringEncodingISO8859_15], + "This is \xE4 t\xA4st?"), 0); +} +#endif + +#ifdef HAVE_WINDOWS_1252 +- (void)testLossyCStringWithEncodingWindows1252 +{ + OTAssertEqual( + strcmp([[self.stringClass stringWithString: @"This is ä t€st…‼"] + lossyCStringWithEncoding: OFStringEncodingWindows1252], + "This is \xE4 t\x80st\x85?"), 0); +} +#endif + +#ifdef HAVE_CODEPAGE_437 +- (void)testLossyCStringWithEncodingCodepage437 +{ + OTAssertEqual( + strcmp([[self.stringClass stringWithString: @"T€st strîng ░▒▓"] + lossyCStringWithEncoding: OFStringEncodingCodepage437], + "T?st str\x8Cng \xB0\xB1\xB2"), 0); +} +#endif + +- (void)testStringWithFormat +{ + OTAssertEqualObjects( + ([self.stringClass stringWithFormat: @"%@:%d", @"test", 123]), + @"test:123"); +} + +- (void)testRangeOfString +{ + OFString *string = [self.stringClass stringWithString: @"𝄞öö"]; + + OTAssertEqual([string rangeOfString: @"öö"].location, 1); + OTAssertEqual([string rangeOfString: @"ö"].location, 1); + OTAssertEqual([string rangeOfString: @"𝄞"].location, 0); + OTAssertEqual([string rangeOfString: @"x"].location, OFNotFound); + + OTAssertEqual([string + rangeOfString: @"öö" + options: OFStringSearchBackwards].location, 1); + + OTAssertEqual([string + rangeOfString: @"ö" + options: OFStringSearchBackwards].location, 2); + + OTAssertEqual([string + rangeOfString: @"𝄞" + options: OFStringSearchBackwards].location, 0); + + OTAssertEqual([string + rangeOfString: @"x" + options: OFStringSearchBackwards].location, OFNotFound); +} + +- (void)testRangeOfStringFailsWithOutOfRangeRange +{ + OTAssertThrowsSpecific( + [_string rangeOfString: @"t" options: 0 range: OFMakeRange(6, 1)], + OFOutOfRangeException); +} + +- (void)testIndexOfCharacterFromSet +{ + OFCharacterSet *characterSet = + [OFCharacterSet characterSetWithCharactersInString: @"cđ"]; + + OTAssertEqual([[self.stringClass stringWithString: @"abcđabcđe"] + indexOfCharacterFromSet: characterSet], 2); + + OTAssertEqual([[self.stringClass stringWithString: @"abcđabcđë"] + indexOfCharacterFromSet: characterSet + options: OFStringSearchBackwards], 7); + + OTAssertEqual([[self.stringClass stringWithString: @"abcđabcđë"] + indexOfCharacterFromSet: characterSet + options: 0 + range: OFMakeRange(4, 4)], 6); + + OTAssertEqual([[self.stringClass stringWithString: @"abcđabcđëf"] + indexOfCharacterFromSet: characterSet + options: 0 + range: OFMakeRange(8, 2)], OFNotFound); +} + +- (void)testIndexOfCharacterFromSetFailsWithOutOfRangeRange +{ + OFCharacterSet *characterSet = + [OFCharacterSet characterSetWithCharactersInString: @"cđ"]; + + OTAssertThrowsSpecific([[self.stringClass stringWithString: @"𝄞öö"] + indexOfCharacterFromSet: characterSet + options: 0 + range: OFMakeRange(3, 1)], + OFOutOfRangeException); +} + +- (void)testSubstringWithRange +{ + OTAssertEqualObjects([_string substringWithRange: OFMakeRange(1, 2)], + @"äṠ"); + + OTAssertEqualObjects([_string substringWithRange: OFMakeRange(3, 0)], + @""); +} + +- (void)testSubstringWithRangeFailsWithOutOfRangeRange +{ + OTAssertThrowsSpecific([_string substringWithRange: OFMakeRange(4, 2)], + OFOutOfRangeException); + + OTAssertThrowsSpecific([_string substringWithRange: OFMakeRange(6, 0)], + OFOutOfRangeException); +} + +- (void)testStringByAppendingString +{ + OTAssertEqualObjects([_string stringByAppendingString: @"äöü"], + @"täṠ€🤔äöü"); +} + +- (void)testHasPrefix +{ + OTAssertTrue([_string hasPrefix: @"täṠ"]); + OTAssertFalse([_string hasPrefix: @"🤔"]); +} + +- (void)testHasSuffix +{ + OTAssertTrue([_string hasSuffix: @"🤔"]); + OTAssertFalse([_string hasSuffix: @"täṠ"]); +} + +- (void)testComponentsSeparatedByString +{ + OTAssertEqualObjects([[self.stringClass stringWithString: + @"fooXXbarXXXXbazXXXX"] componentsSeparatedByString: @"XX"], + ([OFArray arrayWithObjects: @"foo", @"bar", @"", @"baz", @"", @"", + nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] componentsSeparatedByString: @""], + [OFArray arrayWithObject: @"foo"]); +} + +- (void)testComponentsSeparatedByStringOptions +{ + OTAssertEqualObjects([[self.stringClass stringWithString: + @"fooXXbarXXXXbazXXXX"] + componentsSeparatedByString: @"XX" + options: OFStringSkipEmptyComponents], + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); +} + +- (void)testComponentsSeparatedByCharactersInSet +{ + OFCharacterSet *characterSet = + [OFCharacterSet characterSetWithCharactersInString: @"XYZ"]; + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"fooXYbarXYZXbazXYXZx"] + componentsSeparatedByCharactersInSet: characterSet], + ([OFArray arrayWithObjects: @"foo", @"", @"bar", @"", @"", @"", + @"baz", @"", @"", @"", @"x", nil])); +} + +- (void)testComponentsSeparatedByCharactersInSetOptions +{ + OFCharacterSet *characterSet = + [OFCharacterSet characterSetWithCharactersInString: @"XYZ"]; + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"fooXYbarXYZXbazXYXZ"] + componentsSeparatedByCharactersInSet: characterSet + options: OFStringSkipEmptyComponents], + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); +} + +- (void)testLongLongValue +{ + OTAssertEqual([[self.stringClass stringWithString: + @"1234"] longLongValue], 1234); + + OTAssertEqual([[self.stringClass stringWithString: + @"\r\n+123 "] longLongValue], 123); + + OTAssertEqual([[self.stringClass stringWithString: + @"-500\t"] longLongValue], -500); + + OTAssertEqual([[self.stringClass stringWithString: + @"-0x10\t"] longLongValueWithBase: 0], -0x10); + + OTAssertEqual([[self.stringClass stringWithString: + @"\t\t\r\n"] longLongValue], 0); + + OTAssertEqual([[self.stringClass stringWithString: + @"123f"] longLongValueWithBase: 16], 0x123f); + + OTAssertEqual([[self.stringClass stringWithString: + @"-1234"] longLongValueWithBase: 0], -1234); + + OTAssertEqual([[self.stringClass stringWithString: + @"\t\n0xABcd\r"] longLongValueWithBase: 0], 0xABCD); + + OTAssertEqual([[self.stringClass stringWithString: + @"1234567"] longLongValueWithBase: 8], 01234567); + + OTAssertEqual([[self.stringClass stringWithString: + @"\r\n0123"] longLongValueWithBase: 0], 0123); + + OTAssertEqual([[self.stringClass stringWithString: + @"765\t"] longLongValueWithBase: 8], 0765); + + OTAssertEqual([[self.stringClass stringWithString: + @"\t\t\r\n"] longLongValueWithBase: 8], 0); +} + +- (void)testLongLongValueThrowsOnInvalidFormat +{ + OTAssertThrowsSpecific( + [[self.stringClass stringWithString: @"abc"] longLongValue], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [[self.stringClass stringWithString: @"0a"] longLongValue], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [[self.stringClass stringWithString: @"0 1"] longLongValue], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [[self.stringClass stringWithString: @"0xABCDEFG"] + longLongValueWithBase: 0], + OFInvalidFormatException); + + OTAssertThrowsSpecific( + [[self.stringClass stringWithString: @"0x"] + longLongValueWithBase: 0], + OFInvalidFormatException); +} + +- (void)testLongLongValueThrowsOnOutOfRange +{ + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"-12345678901234567890123456789012345678901234567890" + @"12345678901234567890123456789012345678901234567890"] + longLongValueWithBase: 16], OFOutOfRangeException) +} + +- (void)testUnsignedLongLongValue +{ + OTAssertEqual([[self.stringClass stringWithString: + @"1234"] unsignedLongLongValue], 1234); + + OTAssertEqual([[self.stringClass stringWithString: + @"\r\n+123 "] unsignedLongLongValue], 123); + + OTAssertEqual([[self.stringClass stringWithString: + @"\t\t\r\n"] unsignedLongLongValue], 0); + + OTAssertEqual([[self.stringClass stringWithString: + @"123f"] unsignedLongLongValueWithBase: 16], 0x123f); + + OTAssertEqual([[self.stringClass stringWithString: + @"1234"] unsignedLongLongValueWithBase: 0], 1234); + + OTAssertEqual([[self.stringClass stringWithString: + @"\t\n0xABcd\r"] unsignedLongLongValueWithBase: 0], 0xABCD); + + OTAssertEqual([[self.stringClass stringWithString: + @"1234567"] unsignedLongLongValueWithBase: 8], 01234567); + + OTAssertEqual([[self.stringClass stringWithString: + @"\r\n0123"] unsignedLongLongValueWithBase: 0], 0123); + + OTAssertEqual([[self.stringClass stringWithString: @"765\t"] + unsignedLongLongValueWithBase: 8], 0765); + + OTAssertEqual([[self.stringClass stringWithString: @"\t\t\r\n"] + unsignedLongLongValueWithBase: 8], 0); +} + +- (void)testUnsignedLongLongValueThrowsOnOutOfRange +{ + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" + @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"] + unsignedLongLongValueWithBase: 16], OFOutOfRangeException); +} + +- (void)testFloatValue +{ + /* + * These test numbers can be generated without rounding if we have IEEE + * floating point numbers, thus we can use OTAssertEqual on them. + */ + + OTAssertEqual([[self.stringClass stringWithString: + @"\t-0.25 "] floatValue], -0.25); + + OTAssertEqual([[self.stringClass stringWithString: + @"\r\n\tINF\t\n"] floatValue], INFINITY); + OTAssertEqual([[self.stringClass stringWithString: + @"\r -INFINITY\n"] floatValue], -INFINITY); + + OTAssertTrue(isnan([[self.stringClass stringWithString: + @" NAN\t\t"] floatValue])); + OTAssertTrue(isnan([[self.stringClass stringWithString: + @" -NaN\t\t"] floatValue])); +} + +- (void)testFloatValueThrowsOnInvalidFormat +{ + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"0.0a"] floatValue], OFInvalidFormatException); + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"0 0"] floatValue], OFInvalidFormatException); + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"0,0"] floatValue], OFInvalidFormatException); +} + +- (void)testDoubleValue +{ +#if (defined(OF_SOLARIS) && defined(OF_X86)) || defined(OF_AMIGAOS_M68K) + /* + * Solaris' strtod() has weird rounding on x86, but not on AMD64. + * AmigaOS 3 with libnix has weird rounding as well. + */ + OTAssertEqual([[self.stringClass stringWithString: + @"\t-0.125 "] doubleValue], -0.125); +#elif defined(OF_ANDROID) || defined(OF_SOLARIS) || defined(OF_HPUX) || \ + defined(OF_DJGPP) || defined(OF_AMIGAOS_M68K) + /* + * Android, Solaris, HP-UX, DJGPP and AmigaOS 3 do not accept 0x for + * strtod(). + */ + OTAssertEqual([[self.stringClass stringWithString: + @"\t-0.123456789 "] doubleValue], -0.123456789); +#else + OTAssertEqual([[self.stringClass stringWithString: + @"\t-0x1.FFFFFFFFFFFFFP-1020 "] doubleValue], + -0x1.FFFFFFFFFFFFFP-1020); +#endif + + OTAssertEqual([[self.stringClass stringWithString: + @"\r\n\tINF\t\n"] doubleValue], INFINITY); + OTAssertEqual([[self.stringClass stringWithString: + @"\r -INFINITY\n"] doubleValue], -INFINITY); + + OTAssert(isnan([[self.stringClass stringWithString: + @" NAN\t\t"] doubleValue])); + OTAssert(isnan([[self.stringClass stringWithString: + @" -NaN\t\t"] doubleValue])); +} + +- (void)testDoubleValueThrowsOnInvalidFormat +{ + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"0.0a"] doubleValue], OFInvalidFormatException); + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"0 0"] doubleValue], OFInvalidFormatException); + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"0,0"] doubleValue], OFInvalidFormatException); +} + +- (void)testCharacters +{ + OTAssertEqual(memcmp([[self.stringClass stringWithString: @"fööbär🀺"] + characters], unicharString + 1, sizeof(unicharString) - 8), 0); +} + +- (void)testUTF16String +{ + OFString *string = [self.stringClass stringWithString: @"fööbär🀺"]; + + OTAssertEqual(memcmp(string.UTF16String, char16String + 1, + OFUTF16StringLength(char16String) * 2), 0); + +#ifdef OF_BIG_ENDIAN + OTAssertEqual(memcmp([string UTF16StringWithByteOrder: + OFByteOrderLittleEndian], swappedChar16String + 1, + OFUTF16StringLength(swappedChar16String) * 2), 0); +#else + OTAssertEqual(memcmp([string UTF16StringWithByteOrder: + OFByteOrderBigEndian], swappedChar16String + 1, + OFUTF16StringLength(swappedChar16String) * 2), 0); +#endif +} + +- (void)testUTF16StringLength +{ + OTAssertEqual(_string.UTF16StringLength, 6); +} + +- (void)testUTF32String +{ + OFString *string = [self.stringClass stringWithString: @"fööbär🀺"]; + + OTAssertEqual(memcmp(string.UTF32String, unicharString + 1, + OFUTF32StringLength(unicharString) * 4), 0); + +#ifdef OF_BIG_ENDIAN + OTAssertEqual(memcmp([string UTF32StringWithByteOrder: + OFByteOrderLittleEndian], swappedUnicharString + 1, + OFUTF32StringLength(swappedUnicharString) * 4), 0); +#else + OTAssertEqual(memcmp([string UTF32StringWithByteOrder: + OFByteOrderBigEndian], swappedUnicharString + 1, + OFUTF32StringLength(swappedUnicharString) * 4), 0); +#endif +} + +- (void)testStringByMD5Hashing +{ + OTAssertEqualObjects(_string.stringByMD5Hashing, + @"7e6bef5fe100d93e808d15b1c6e6145a"); +} + +- (void)testStringByRIPEMD160Hashing +{ + OTAssertEqualObjects(_string.stringByRIPEMD160Hashing, + @"2fd0ec899c55cf2821a2f844b9d80887fc351103"); +} + +- (void)testStringBySHA1Hashing +{ + OTAssertEqualObjects(_string.stringBySHA1Hashing, + @"3f76f9358b372b7147344b7a3ba6d309e4466b3a"); +} + +- (void)testStringBySHA224Hashing +{ + OTAssertEqualObjects(_string.stringBySHA224Hashing, + @"6e57ec72e4da55c46d88a15ce7ce4d8db83d0493a263134a3734259d"); +} + +- (void)testStringBySHA256Hashing +{ + OTAssertEqualObjects(_string.stringBySHA256Hashing, + @"6eac4d3d0b4152c82ff88599482696ca" + @"d6dca0b533e8a2e6963d995b19b0a683"); +} + +- (void)testStringBySHA384Hashing +{ + OTAssertEqualObjects(_string.stringBySHA384Hashing, + @"d9bd6a671407d01cee4022888677040d" + @"108dd0270c38e0ce755d6dcadb4bf9c1" + @"89204dd2a51f954be55ea5d5fe00667b"); +} + +- (void)testStringBySHA512Hashing +{ + OTAssertEqualObjects(_string.stringBySHA512Hashing, + @"64bec66b3633c585da6d32760fa3617a" + @"47ca4c247472bdbbfb452b2dbf5a3612" + @"5629053394a16ecd08f8a21d461537c5" + @"f1224cbb379589e73dcd6763ec4f886c"); +} + +- (void)testStringByAddingPercentEncodingWithAllowedCharacters +{ + OFCharacterSet *characterSet = + [OFCharacterSet characterSetWithCharactersInString: @"abfo'_~$🍏"]; + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo\"ba'_~$]🍏🍌"] + stringByAddingPercentEncodingWithAllowedCharacters: characterSet], + @"foo%22ba'_~$%5D🍏%F0%9F%8D%8C"); +} + +- (void)testStringByRemovingPercentEncoding +{ + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo%20bar%22+%24%F0%9F%8D%8C"] stringByRemovingPercentEncoding], + @"foo bar\"+$🍌"); +} + +- (void)testStringByRemovingPercentEncodingThrowsOnInvalidFormat +{ + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"foo%xbar"] stringByRemovingPercentEncoding], + OFInvalidFormatException); +} + +- (void)testStringByRemovingPercentEncodingThrowsOnInvalidEncoding +{ + OTAssertThrowsSpecific([[self.stringClass stringWithString: + @"foo%FFbar"] stringByRemovingPercentEncoding], + OFInvalidEncodingException); +} + +- (void)testStringByXMLEscaping +{ + OTAssertEqualObjects([[self.stringClass stringWithString: + @" &world'\"!&"] stringByXMLEscaping], + @"<hello> &world'"!&"); +} + +- (void)testStringByXMLUnescaping +{ + OTAssertEqualObjects([[self.stringClass stringWithString: + @"<hello> &world'"!&"] + stringByXMLUnescaping], + @" &world'\"!&"); + + OTAssertEqualObjects([[self.stringClass stringWithString: @"y"] + stringByXMLUnescaping], @"y"); + OTAssertEqualObjects([[self.stringClass stringWithString: @"ä"] + stringByXMLUnescaping], @"ä"); + OTAssertEqualObjects([[self.stringClass stringWithString: @"€"] + stringByXMLUnescaping], @"€"); + OTAssertEqualObjects([[self.stringClass stringWithString: @"𝄞"] + stringByXMLUnescaping], @"𝄞"); +} + +- (void)testStringByXMLUnescapingThrowsOnUnknownEntities +{ + OTAssertThrowsSpecific([[self.stringClass stringWithString: @"&foo;"] + stringByXMLUnescaping], OFUnknownXMLEntityException); +} + +- (void)testStringByXMLUnescapingThrowsOnInvalidFormat +{ + OTAssertThrowsSpecific([[self.stringClass stringWithString: @"x&"] + stringByXMLUnescaping], OFInvalidFormatException); + OTAssertThrowsSpecific([[self.stringClass stringWithString: @"&#;"] + stringByXMLUnescaping], OFInvalidFormatException); + OTAssertThrowsSpecific([[self.stringClass stringWithString: @"&#x;"] + stringByXMLUnescaping], OFInvalidFormatException); + OTAssertThrowsSpecific([[self.stringClass stringWithString: @"&#g;"] + stringByXMLUnescaping], OFInvalidFormatException); + OTAssertThrowsSpecific([[self.stringClass stringWithString: @"&#xg;"] + stringByXMLUnescaping], OFInvalidFormatException); +} + +- (void)testStringByXMLUnescapingWithDelegate +{ + EntityHandler *entityHandler = + [[[EntityHandler alloc] init] autorelease]; + + OTAssertEqualObjects([[self.stringClass stringWithString: @"x&foo;y"] + stringByXMLUnescapingWithDelegate: entityHandler], + @"xbary"); +} + +#ifdef OF_HAVE_BLOCKS +- (void)testStringByXMLUnescapingWithBlock +{ + OTAssertEqualObjects([[self.stringClass stringWithString: @"x&foo;y"] + stringByXMLUnescapingWithBlock: ^ OFString * (OFString *string, + OFString *entity) { + if ([entity isEqual: @"foo"]) + return @"bar"; + + return nil; + }], @"xbary"); +} + +- (void)testEnumerateLinesUsingBlock +{ + __block size_t count = 0; + + [[self.stringClass stringWithString: @"foo\nbar\nbaz"] + enumerateLinesUsingBlock: ^ (OFString *line, bool *stop) { + switch (count++) { + case 0: + OTAssertEqualObjects(line, @"foo"); + break; + case 1: + OTAssertEqualObjects(line, @"bar"); + break; + case 2: + OTAssertEqualObjects(line, @"baz"); + break; + default: + OTAssert(false); + } + }]; + + OTAssertEqual(count, 3); +} +#endif + +#ifdef OF_HAVE_FILES +- (void)testIsAbsolutePath +{ +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + OTAssertTrue( + [[self.stringClass stringWithString: @"C:\\foo"] isAbsolutePath]); + OTAssertTrue( + [[self.stringClass stringWithString: @"a:/foo"] isAbsolutePath]); + OTAssertFalse( + [[self.stringClass stringWithString: @"foo"] isAbsolutePath]); + OTAssertFalse( + [[self.stringClass stringWithString: @"b:foo"] isAbsolutePath]); +# ifdef OF_WINDOWS + OTAssertTrue( + [[self.stringClass stringWithString: @"\\\\foo"] isAbsolutePath]); +# endif +# elif defined(OF_AMIGAOS) + OTAssertTrue( + [[self.stringClass stringWithString: @"dh0:foo"] isAbsolutePath]); + OTAssertTrue( + [[self.stringClass stringWithString: @"dh0:a/b"] isAbsolutePath]); + OTAssertFalse( + [[self.stringClass stringWithString: @"foo/bar"] isAbsolutePath]); + OTAssertFalse( + [[self.stringClass stringWithString: @"foo"] isAbsolutePath]); +# elif defined(OF_NINTENDO_DS) || defined(OF_NINTENDO_3DS) || \ + defined(OF_WII) || defined(OF_NINTENDO_SWITCH) + OTAssertTrue( + [[self.stringClass stringWithString: @"sdmc:/foo"] isAbsolutePath]); + OTAssertFalse( + [[self.stringClass stringWithString: @"sdmc:foo"] isAbsolutePath]); + OTAssertFalse( + [[self.stringClass stringWithString: @"foo/bar"] isAbsolutePath]); + OTAssertFalse( + [[self.stringClass stringWithString: @"foo"] isAbsolutePath]); +# else + OTAssertTrue( + [[self.stringClass stringWithString: @"/foo"] isAbsolutePath]); + OTAssertTrue( + [[self.stringClass stringWithString: @"/foo/bar"] isAbsolutePath]); + OTAssertFalse( + [[self.stringClass stringWithString: @"foo/bar"] isAbsolutePath]); + OTAssertFalse( + [[self.stringClass stringWithString: @"foo"] isAbsolutePath]); +# endif +} + +- (void)testStringByAppendingPathComponent +{ +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + OTAssertEqualObjects([[self.stringClass stringWithString: @"foo\\bar"] + stringByAppendingPathComponent: @"baz"], + @"foo\\bar\\baz"); + + OTAssertEqualObjects([[self.stringClass stringWithString: @"foo\\bar\\"] + stringByAppendingPathComponent: @"baz"], + @"foo\\bar\\baz"); +# else + OTAssertEqualObjects([[self.stringClass stringWithString: @"foo/bar"] + stringByAppendingPathComponent: @"baz"], + @"foo/bar/baz"); + + OTAssertEqualObjects([[self.stringClass stringWithString: @"foo/bar/"] + stringByAppendingPathComponent: @"baz"], + @"foo/bar/baz"); +# endif +} + +- (void)testStringByAppendingPathExtension +{ +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] stringByAppendingPathExtension: @"bar"], + @"foo.bar"); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:\\tmp\\foo"] stringByAppendingPathExtension: @"bar"], + @"c:\\tmp\\foo.bar"); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:\\tmp\\/\\"] stringByAppendingPathExtension: @"bar"], + @"c:\\tmp.bar"); +# elif defined(OF_AMIGAOS) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] stringByAppendingPathExtension: @"bar"], + @"foo.bar"); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] stringByAppendingPathExtension: @"baz"], + @"foo/bar.baz"); +# else + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] stringByAppendingPathExtension: @"bar"], + @"foo.bar"); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] stringByAppendingPathExtension: @"baz"], + @"foo/bar.baz"); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo///"] stringByAppendingPathExtension: @"bar"], + @"foo.bar"); +# endif +} + +- (void)testPathWithComponents +{ +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])], + @"foo\\bar\\baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"c:\\", @"foo", @"bar", @"baz", nil])], + @"c:\\foo\\bar\\baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"c:", @"foo", @"bar", @"baz", nil])], + @"c:foo\\bar\\baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"c:", @"\\", @"foo", @"bar", @"baz", + nil])], @"c:\\foo\\bar\\baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"c:", @"/", @"foo", @"bar", @"baz", + nil])], @"c:/foo\\bar\\baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"foo/", @"bar\\", @"", @"baz", @"\\", + nil])], @"foo/bar\\baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + [OFArray arrayWithObject: @"foo"]], @"foo"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + [OFArray arrayWithObject: @"c:"]], @"c:"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + [OFArray arrayWithObject: @"c:\\"]], @"c:\\"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + [OFArray arrayWithObject: @"\\"]], @"\\"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + [OFArray arrayWithObject: @"/"]], @"/"); + +# ifdef OF_WINDOWS + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"\\\\", @"foo", @"bar", nil])], + @"\\\\foo\\bar"); +# endif +# elif defined(OF_AMIGAOS) + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"dh0:", @"foo", @"bar", @"baz", nil])], + @"dh0:foo/bar/baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])], + @"foo/bar/baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"foo/", @"bar", @"", @"baz", @"/", + nil])], @"foo//bar/baz//"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + [OFArray arrayWithObject: @"foo"]], @"foo"); +# elif defined(OF_WII) || defined(OF_NINTENDO_DS) || \ + defined(OF_NINTENDO_3DS) || defined(OF_NINTENDO_SWITCH) + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])], + @"foo/bar/baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"sdmc:", @"foo", @"bar", @"baz", + nil])], @"sdmc:/foo/bar/baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"foo/", @"bar/", @"", @"baz", @"/", + nil])], @"foo/bar/baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + [OFArray arrayWithObject: @"foo"]], @"foo"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + [OFArray arrayWithObject: @"sdmc:"]], @"sdmc:/"); +# else + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"/", @"foo", @"bar", @"baz", nil])], + @"/foo/bar/baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])], + @"foo/bar/baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + ([OFArray arrayWithObjects: @"foo/", @"bar", @"", @"baz", @"/", + nil])], @"foo/bar/baz"); + + OTAssertEqualObjects([self.stringClass pathWithComponents: + [OFArray arrayWithObject: @"foo"]], @"foo"); +# endif +} + +- (void)testPathComponents +{ +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:/tmp"] pathComponents], + ([OFArray arrayWithObjects: @"c:/", @"tmp", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:\\tmp\\"] pathComponents], + ([OFArray arrayWithObjects: @"c:\\", @"tmp", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:\\"] pathComponents], [OFArray arrayWithObject: @"c:\\"]); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:/"] pathComponents], [OFArray arrayWithObject: @"c:/"]); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:"] pathComponents], [OFArray arrayWithObject: @"c:"]); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo\\bar"] pathComponents], + ([OFArray arrayWithObjects: @"foo", @"bar", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo\\bar/baz/"] pathComponents], + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo\\/"] pathComponents], [OFArray arrayWithObject: @"foo"]); + +# ifdef OF_WINDOWS + OTAssertEqualObjects([[self.stringClass stringWithString: + @"\\\\foo\\bar"] pathComponents], + ([OFArray arrayWithObjects: @"\\\\", @"foo", @"bar", nil])); +# endif + + OTAssertEqualObjects([[self.stringClass stringWithString: @""] + pathComponents], [OFArray array]); +# elif defined(OF_AMIGAOS) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:tmp"] pathComponents], + ([OFArray arrayWithObjects: @"dh0:", @"tmp", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:tmp/"] pathComponents], + ([OFArray arrayWithObjects: @"dh0:", @"tmp", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:/"] pathComponents], + ([OFArray arrayWithObjects: @"dh0:", @"/", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] pathComponents], + ([OFArray arrayWithObjects: @"foo", @"bar", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar/baz/"] pathComponents], + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo//"] pathComponents], + ([OFArray arrayWithObjects: @"foo", @"/", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: @""] + pathComponents], [OFArray array]); +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"sdmc:/tmp"] pathComponents], + ([OFArray arrayWithObjects: @"sdmc:", @"tmp", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"sdmc:/"] pathComponents], [OFArray arrayWithObject: @"sdmc:"]); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] pathComponents], + ([OFArray arrayWithObjects: @"foo", @"bar", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar/baz/"] pathComponents], + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo//"] pathComponents], [OFArray arrayWithObject: @"foo"]); + + OTAssertEqualObjects([[self.stringClass stringWithString: @""] + pathComponents], [OFArray array]); +# else + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/tmp"] pathComponents], + ([OFArray arrayWithObjects: @"/", @"tmp", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/tmp/"] pathComponents], + ([OFArray arrayWithObjects: @"/", @"tmp", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/"] pathComponents], [OFArray arrayWithObject: @"/"]); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] pathComponents], + ([OFArray arrayWithObjects: @"foo", @"bar", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar/baz/"] pathComponents], + ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil])); + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo//"] pathComponents], [OFArray arrayWithObject: @"foo"]); + + OTAssertEqualObjects([[self.stringClass stringWithString: @""] + pathComponents], [OFArray array]); +# endif +} + +- (void)testLastPathComponent +{ +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:/tmp"] lastPathComponent], @"tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:\\tmp\\"] lastPathComponent], @"tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:\\"] lastPathComponent], @"c:\\"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:/"] lastPathComponent], @"c:/"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"\\"] lastPathComponent], @"\\"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] lastPathComponent], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo\\bar"] lastPathComponent], @"bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar/baz/"] lastPathComponent], @"baz"); +# ifdef OF_WINDOWS + OTAssertEqualObjects([[self.stringClass stringWithString: + @"\\\\foo\\bar"] lastPathComponent], @"bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"\\\\"] lastPathComponent], @"\\\\"); +# endif +# elif defined(OF_AMIGAOS) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:tmp"] lastPathComponent], @"tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:tmp/"] lastPathComponent], @"tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:/"] lastPathComponent], @"/"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:"] lastPathComponent], @"dh0:"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] lastPathComponent], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] lastPathComponent], @"bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar/baz/"] lastPathComponent], @"baz"); +# elif defined(OF_WII) || defined(OF_NINTENDO_DS) || \ + defined(OF_NINTENDO_3DS) || defined(OF_NINTENDO_SWITCH) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"sdmc:/tmp"] lastPathComponent], @"tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"sdmc:/tmp/"] lastPathComponent], @"tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"sdmc:/"] lastPathComponent], @"sdmc:/"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"sdmc:"] lastPathComponent], @"sdmc:"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] lastPathComponent], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] lastPathComponent], @"bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar/baz/"] lastPathComponent], @"baz"); +# else + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/tmp"] lastPathComponent], @"tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/tmp/"] lastPathComponent], @"tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/"] lastPathComponent], @"/"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] lastPathComponent], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] lastPathComponent], @"bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar/baz/"] lastPathComponent], @"baz"); +# endif +} + +- (void)testPathExtension +{ + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo.bar"] pathExtension], @"bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/.bar"] pathExtension], @""); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/.bar.baz"] pathExtension], @"baz"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar.baz/"] pathExtension], @"baz"); +} + +- (void)testStringByDeletingLastPathComponent +{ +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"\\tmp"] stringByDeletingLastPathComponent], @"\\"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/tmp/"] stringByDeletingLastPathComponent], @"/"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:\\"] stringByDeletingLastPathComponent], @"c:\\"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:/"] stringByDeletingLastPathComponent], @"c:/"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:\\tmp/foo/"] stringByDeletingLastPathComponent], @"c:\\tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo\\bar"] stringByDeletingLastPathComponent], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"\\"] stringByDeletingLastPathComponent], @"\\"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] stringByDeletingLastPathComponent], @"."); +# ifdef OF_WINDOWS + OTAssertEqualObjects([[self.stringClass stringWithString: + @"\\\\foo\\bar"] stringByDeletingLastPathComponent], @"\\\\foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"\\\\foo"] stringByDeletingLastPathComponent], @"\\\\"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"\\\\"] stringByDeletingLastPathComponent], @"\\\\"); +# endif +# elif defined(OF_AMIGAOS) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:"] stringByDeletingLastPathComponent], @"dh0:"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:tmp"] stringByDeletingLastPathComponent], @"dh0:"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:tmp/"] stringByDeletingLastPathComponent], @"dh0:"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:/"] stringByDeletingLastPathComponent], @"dh0:"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:tmp/foo/"] stringByDeletingLastPathComponent], @"dh0:tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] stringByDeletingLastPathComponent], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] stringByDeletingLastPathComponent], @""); +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/tmp/"] stringByDeletingLastPathComponent], @""); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"sdmc:/tmp/foo/"] stringByDeletingLastPathComponent], + @"sdmc:/tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"sdmc:/"] stringByDeletingLastPathComponent], @"sdmc:/"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] stringByDeletingLastPathComponent], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/"] stringByDeletingLastPathComponent], @""); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] stringByDeletingLastPathComponent], @"."); +# else + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/tmp"] stringByDeletingLastPathComponent], @"/"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/tmp/"] stringByDeletingLastPathComponent], @"/"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/tmp/foo/"] stringByDeletingLastPathComponent], @"/tmp"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo/bar"] stringByDeletingLastPathComponent], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/"] stringByDeletingLastPathComponent], @"/"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo"] stringByDeletingLastPathComponent], @"."); +# endif +} + +- (void)testStringByDeletingPathExtension +{ +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo.bar"] stringByDeletingPathExtension], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo..bar"] stringByDeletingPathExtension], @"foo."); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:/foo.\\bar"] stringByDeletingPathExtension], @"c:/foo.\\bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:\\foo./bar.baz"] stringByDeletingPathExtension], + @"c:\\foo.\\bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo.bar/"] stringByDeletingPathExtension], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @".foo"] stringByDeletingPathExtension], @".foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @".foo.bar"] stringByDeletingPathExtension], @".foo"); +# elif defined(OF_AMIGAOS) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo.bar"] stringByDeletingPathExtension], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo..bar"] stringByDeletingPathExtension], @"foo."); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:foo.bar"] stringByDeletingPathExtension], @"dh0:foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:foo./bar"] stringByDeletingPathExtension], @"dh0:foo./bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"dh0:foo./bar.baz"] stringByDeletingPathExtension], + @"dh0:foo./bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo.bar/"] stringByDeletingPathExtension], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @".foo"] stringByDeletingPathExtension], @".foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @".foo\\bar"] stringByDeletingPathExtension], @".foo\\bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @".foo.bar"] stringByDeletingPathExtension], @".foo"); +# elif defined(OF_WII) || defined(OF_NINTENDO_DS) || \ + defined(OF_NINTENDO_3DS) || defined(OF_NINTENDO_SWITCH) + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo.bar"] stringByDeletingPathExtension], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo..bar"] stringByDeletingPathExtension], @"foo."); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"sdmc:/foo./bar"] stringByDeletingPathExtension], + @"sdmc:/foo./bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"sdmc:/foo./bar.baz"] stringByDeletingPathExtension], + @"sdmc:/foo./bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo.bar/"] stringByDeletingPathExtension], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @".foo"] stringByDeletingPathExtension], @".foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @".foo.bar"] stringByDeletingPathExtension], @".foo"); +# else + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo.bar"] stringByDeletingPathExtension], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo..bar"] stringByDeletingPathExtension], @"foo."); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/foo./bar"] stringByDeletingPathExtension], @"/foo./bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"/foo./bar.baz"] stringByDeletingPathExtension], @"/foo./bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @"foo.bar/"] stringByDeletingPathExtension], @"foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @".foo"] stringByDeletingPathExtension], @".foo"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @".foo\\bar"] stringByDeletingPathExtension], @".foo\\bar"); + OTAssertEqualObjects([[self.stringClass stringWithString: + @".foo.bar"] stringByDeletingPathExtension], @".foo"); +# endif +} + +# if defined(OF_WINDOWS) || defined(OF_MSDOS) +- (void)testStringByStandardizingPath +{ + /* TODO: Add more tests */ + + OTAssertEqualObjects([[self.stringClass stringWithString: + @"c:\\..\\asd"] stringByStandardizingPath], + @"c:\\..\\asd"); + +# ifndef OF_MSDOS + OTAssertEqualObjects([[self.stringClass stringWithString: + @"\\\\foo\\..\\bar\\qux"] stringByStandardizingPath], + @"\\\\bar\\qux"); +# endif +} +# endif +#endif +@end + +@implementation CustomString +- (instancetype)init +{ + self = [super init]; + + @try { + _string = [[OFMutableString alloc] init]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithString: (OFString *)string +{ + self = [super init]; + + @try { + _string = [string mutableCopy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithCString: (const char *)cString + encoding: (OFStringEncoding)encoding + length: (size_t)length +{ + self = [super init]; + + @try { + _string = [[OFMutableString alloc] initWithCString: cString + encoding: encoding + length: length]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithUTF16String: (const OFChar16 *)UTF16String + length: (size_t)length + byteOrder: (OFByteOrder)byteOrder +{ + self = [super init]; + + @try { + _string = [[OFMutableString alloc] + initWithUTF16String: UTF16String + length: length + byteOrder: byteOrder]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithUTF32String: (const OFChar32 *)UTF32String + length: (size_t)length + byteOrder: (OFByteOrder)byteOrder +{ + self = [super init]; + + @try { + _string = [[OFMutableString alloc] + initWithUTF32String: UTF32String + length: length + byteOrder: byteOrder]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithFormat: (OFConstantString *)format + arguments: (va_list)arguments +{ + self = [super init]; + + @try { + _string = [[OFMutableString alloc] initWithFormat: format + arguments: arguments]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_string release]; + + [super dealloc]; +} + +- (OFUnichar)characterAtIndex: (size_t)idx +{ + return [_string characterAtIndex: idx]; +} + +- (size_t)length +{ + return _string.length; +} +@end + +@implementation EntityHandler +- (OFString *)string: (OFString *)string + containsUnknownEntityNamed: (OFString *)entity +{ + if ([entity isEqual: @"foo"]) + return @"bar"; + + return nil; +} +@end ADDED tests/OFSubprocessTests.m Index: tests/OFSubprocessTests.m ================================================================== --- /dev/null +++ tests/OFSubprocessTests.m @@ -0,0 +1,56 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFSubprocessTests: OTTestCase +@end + +@implementation OFSubprocessTests +- (void)testSubprocess +{ +#ifdef OF_HAVE_FILES + OFString *program = [@"subprocess" stringByAppendingPathComponent: + @"subprocess" @PROG_SUFFIX]; +#else + OFString *program = @"subprocess/subprocess" @PROG_SUFFIX; +#endif + OFArray *arguments = [OFArray arrayWithObjects: @"tést", @"123", nil]; + OFMutableDictionary *environment = + [[[OFApplication environment] mutableCopy] autorelease]; + OFSubprocess *subprocess; + + [environment setObject: @"yés" forKey: @"tëst"]; + + subprocess = [OFSubprocess subprocessWithProgram: program + programName: program + arguments: arguments + environment: environment]; + + [subprocess writeLine: @"Hellö world!"]; +#ifdef OF_HAVE_UNICODE_TABLES + OTAssertEqualObjects([subprocess readLine], @"HELLÖ WORLD!"); +#else + OTAssertEqualObjects([subprocess readLine], @"HELLö WORLD!"); +#endif + + [subprocess closeForWriting]; + + OTAssertEqual([subprocess waitForTermination], 0); +} +@end ADDED tests/OFSystemInfoTests.m Index: tests/OFSystemInfoTests.m ================================================================== --- /dev/null +++ tests/OFSystemInfoTests.m @@ -0,0 +1,201 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFSystemInfoTests: OTTestCase +@end + +#ifdef OF_HAVE_SOCKETS +static void +appendAddresses(OFMutableString *string, OFData *addresses, bool *firstAddress) +{ + size_t count = addresses.count; + + for (size_t i = 0; i < count; i++) { + const OFSocketAddress *address = [addresses itemAtIndex: i]; + + if (!*firstAddress) + [string appendString: @", "]; + + *firstAddress = false; + + [string appendString: OFSocketAddressString(address)]; + } +} +#endif + +@implementation OFSystemInfoTests ++ (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, id) *) *)summary +{ + OFMutableArray *summary = [OFMutableArray array]; +#ifdef OF_HAVE_SOCKETS + OFDictionary *networkInterfaces; + OFMutableString *networkInterfacesString; + bool firstInterface = true; +#endif + +#define ADD(name, value) \ + [summary addObject: [OFPair pairWithFirstObject: name \ + secondObject: value]]; +#define ADD_UINT(name, value) \ + ADD(name, [OFNumber numberWithUnsignedInt: value]); +#define ADD_ULONGLONG(name, value) \ + ADD(name, [OFNumber numberWithUnsignedLongLong: value]); +#define ADD_BOOL(name, value) \ + ADD(name, [OFNumber numberWithBool: value]); + + ADD(@"ObjFW version", [OFSystemInfo ObjFWVersion]) + ADD_UINT(@"ObjFW version major", [OFSystemInfo ObjFWVersionMajor]) + ADD_UINT(@"ObjFW version minor", [OFSystemInfo ObjFWVersionMinor]) + ADD(@"Operating system name", [OFSystemInfo operatingSystemName]); + ADD(@"Operating system version", [OFSystemInfo operatingSystemVersion]); + ADD_ULONGLONG(@"Page size", [OFSystemInfo pageSize]); + ADD_ULONGLONG(@"Number of CPUs", [OFSystemInfo numberOfCPUs]); + ADD(@"User config IRI", [OFSystemInfo userConfigIRI].string); + ADD(@"User data IRI", [OFSystemInfo userDataIRI].string); + ADD(@"Temporary directory IRI", + [OFSystemInfo temporaryDirectoryIRI].string); + ADD(@"CPU vendor", [OFSystemInfo CPUVendor]); + ADD(@"CPU model", [OFSystemInfo CPUModel]); + +#if defined(OF_AMD64) || defined(OF_X86) + ADD_BOOL(@"Supports MMX", [OFSystemInfo supportsMMX]); + ADD_BOOL(@"Supports 3DNow!", [OFSystemInfo supports3DNow]); + ADD_BOOL(@"Supports enhanced 3DNow!", + [OFSystemInfo supportsEnhanced3DNow]); + ADD_BOOL(@"Supports SSE", [OFSystemInfo supportsSSE]); + ADD_BOOL(@"Supports SSE2", [OFSystemInfo supportsSSE2]); + ADD_BOOL(@"Supports SSE3", [OFSystemInfo supportsSSE3]); + ADD_BOOL(@"Supports SSSE3", [OFSystemInfo supportsSSSE3]); + ADD_BOOL(@"Supports SSE4.1", [OFSystemInfo supportsSSE41]); + ADD_BOOL(@"Supports SSE4.2", [OFSystemInfo supportsSSE42]); + ADD_BOOL(@"Supports AVX", [OFSystemInfo supportsAVX]); + ADD_BOOL(@"Supports AVX2", [OFSystemInfo supportsAVX2]); + ADD_BOOL(@"Supports AES-NI", [OFSystemInfo supportsAESNI]); + ADD_BOOL(@"Supports SHA extensions", + [OFSystemInfo supportsSHAExtensions]); + ADD_BOOL(@"Supports fused multiply-add", + [OFSystemInfo supportsFusedMultiplyAdd]); + ADD_BOOL(@"Supports F16C", [OFSystemInfo supportsF16C]); + ADD_BOOL(@"Supports AVX-512 Foundation", + [OFSystemInfo supportsAVX512Foundation]); + ADD_BOOL(@"Supports AVX-512 Conflict Detection Instructions", + [OFSystemInfo supportsAVX512ConflictDetectionInstructions]); + ADD_BOOL(@"Supports AVX-512 Exponential and Reciprocal Instructions", + [OFSystemInfo supportsAVX512ExponentialAndReciprocalInstructions]); + ADD_BOOL(@"Supports AVX-512 Prefetch Instructions", + [OFSystemInfo supportsAVX512PrefetchInstructions]); + ADD_BOOL(@"Supports AVX-512 Vector Length Extensions", + [OFSystemInfo supportsAVX512VectorLengthExtensions]); + ADD_BOOL(@"Supports AVX-512 Doubleword and Quadword Instructions", + [OFSystemInfo supportsAVX512DoublewordAndQuadwordInstructions]); + ADD_BOOL(@"Supports AVX-512 Byte and Word Instructions", + [OFSystemInfo supportsAVX512ByteAndWordInstructions]); + ADD_BOOL(@"Supports AVX-512 Integer Fused Multiply Add", + [OFSystemInfo supportsAVX512IntegerFusedMultiplyAdd]); + ADD_BOOL(@"Supports AVX-512 Vector Byte Manipulation Instructions", + [OFSystemInfo supportsAVX512VectorByteManipulationInstructions]); + ADD_BOOL(@"Supports AVX-512 Vector Population Count Instruction", + [OFSystemInfo supportsAVX512VectorPopulationCountInstruction]); + ADD_BOOL(@"Supports AVX-512 Vector Neutral Network Instructions", + [OFSystemInfo supportsAVX512VectorNeuralNetworkInstructions]); + ADD_BOOL(@"Supports AVX-512 Vector Byte Manipulation Instructions 2", + [OFSystemInfo supportsAVX512VectorByteManipulationInstructions2]); + ADD_BOOL(@"Supports AVX-512 Bit Algorithms", + [OFSystemInfo supportsAVX512BitAlgorithms]); + ADD_BOOL(@"Supports AVX-512 Float16 Instructions", + [OFSystemInfo supportsAVX512Float16Instructions]); + ADD_BOOL(@"Supports AVX-512 BFloat16 Instructions", + [OFSystemInfo supportsAVX512BFloat16Instructions]); +#endif + +#ifdef OF_POWERPC + ADD_BOOL(@"Supports AltiVec", [OFSystemInfo supportsAltiVec]); +#endif + +#undef ADD +#undef ADD_UINT +#undef ADD_ULONGLONG +#undef ADD_BOOL + +#ifdef OF_HAVE_SOCKETS + networkInterfaces = [OFSystemInfo networkInterfaces]; + networkInterfacesString = [OFMutableString string]; + for (OFString *name in networkInterfaces) { + bool firstAddress = true; + OFNetworkInterface interface; + OFData *hardwareAddress; + + if (!firstInterface) + [networkInterfacesString appendString: @"; "]; + + firstInterface = false; + + [networkInterfacesString appendFormat: @"%@(", name]; + + interface = [networkInterfaces objectForKey: name]; + + appendAddresses(networkInterfacesString, + [interface objectForKey: OFNetworkInterfaceIPv4Addresses], + &firstAddress); +# ifdef OF_HAVE_IPV6 + appendAddresses(networkInterfacesString, + [interface objectForKey: OFNetworkInterfaceIPv6Addresses], + &firstAddress); +# endif +# ifdef OF_HAVE_IPX + appendAddresses(networkInterfacesString, + [interface objectForKey: OFNetworkInterfaceIPXAddresses], + &firstAddress); +# endif +# ifdef OF_HAVE_APPLETALK + appendAddresses(networkInterfacesString, + [interface objectForKey: + OFNetworkInterfaceAppleTalkAddresses], &firstAddress); +# endif + + hardwareAddress = [interface + objectForKey: OFNetworkInterfaceHardwareAddress]; + if (hardwareAddress != nil) { + const unsigned char *bytes = hardwareAddress.items; + size_t length = hardwareAddress.count; + + if (!firstAddress) + [networkInterfacesString appendString: @", "]; + + for (size_t i = 0; i < length; i++) { + if (i > 0) + [networkInterfacesString + appendString: @":"]; + + [networkInterfacesString + appendFormat: @"%02X", bytes[i]]; + } + } + + [networkInterfacesString appendString: @")"]; + } + [summary addObject: + [OFPair pairWithFirstObject: @"Network interfaces" + secondObject: networkInterfacesString]]; +#endif + + return summary; +} +@end ADDED tests/OFTCPSocketTests.m Index: tests/OFTCPSocketTests.m ================================================================== --- /dev/null +++ tests/OFTCPSocketTests.m @@ -0,0 +1,51 @@ +/* + * 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" + +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFTCPSocketTests: OTTestCase +@end + +@implementation OFTCPSocketTests +- (void)testTCPSocket +{ + OFTCPSocket *server, *client, *accepted; + OFSocketAddress address; + char buffer[6]; + + server = [OFTCPSocket socket]; + client = [OFTCPSocket socket]; + + address = [server bindToHost: @"127.0.0.1" port: 0]; + [server listen]; + + [client connectToHost: @"127.0.0.1" + port: OFSocketAddressIPPort(&address)]; + + accepted = [server accept]; + OTAssertEqualObjects(OFSocketAddressString(accepted.remoteAddress), + @"127.0.0.1"); + + [client writeString: @"Hello!"]; + + [accepted readIntoBuffer: buffer exactLength: 6]; + OTAssertEqual(memcmp(buffer, "Hello!", 6), 0); +} +@end ADDED tests/OFThreadTests.m Index: tests/OFThreadTests.m ================================================================== --- /dev/null +++ tests/OFThreadTests.m @@ -0,0 +1,48 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFThreadTests: OTTestCase +@end + +@interface TestThread: OFThread +@end + +@implementation TestThread +- (id)main +{ + [[OFThread threadDictionary] setObject: @"bar" forKey: @"foo"]; + OFEnsure([[[OFThread threadDictionary] + objectForKey: @"foo"] isEqual: @"bar"]); + + return @"success"; +} +@end + +@implementation OFThreadTests +- (void)testThread +{ + TestThread *thread = [TestThread thread]; + + [thread start]; + + OTAssertEqualObjects([thread join], @"success"); + OTAssertNil([[OFThread threadDictionary] objectForKey: @"foo"]); +} +@end ADDED tests/OFUDPSocketTests.m Index: tests/OFUDPSocketTests.m ================================================================== --- /dev/null +++ tests/OFUDPSocketTests.m @@ -0,0 +1,46 @@ +/* + * 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" + +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFUDPSocketTests: OTTestCase +@end + +@implementation OFUDPSocketTests +- (void)testUDPSocket +{ + OFUDPSocket *sock = [OFUDPSocket socket]; + OFSocketAddress addr1, addr2; + char buffer[6]; + + sock = [OFUDPSocket socket]; + + addr1 = [sock bindToHost: @"127.0.0.1" port: 0]; + OTAssertEqualObjects(OFSocketAddressString(&addr1), @"127.0.0.1"); + + [sock sendBuffer: "Hello" length: 6 receiver: &addr1]; + + [sock receiveIntoBuffer: buffer length: 6 sender: &addr2]; + OTAssertEqual(memcmp(buffer, "Hello", 6), 0); + OTAssertEqualObjects(OFSocketAddressString(&addr2), @"127.0.0.1"); + OTAssertEqual(OFSocketAddressIPPort(&addr2), + OFSocketAddressIPPort(&addr1)); +} +@end ADDED tests/OFUNIXDatagramSocketTests.m Index: tests/OFUNIXDatagramSocketTests.m ================================================================== --- /dev/null +++ tests/OFUNIXDatagramSocketTests.m @@ -0,0 +1,79 @@ +/* + * 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" + +#include +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFUNIXDatagramSocketTests: OTTestCase +@end + +@implementation OFUNIXDatagramSocketTests +- (void)testUNIXDatagramSocket +{ + OFUNIXDatagramSocket *sock = [OFUNIXDatagramSocket socket]; + OFString *path; + OFSocketAddress address1, address2; + char buffer[5]; + +#if defined(OF_HAVE_FILES) && !defined(OF_IOS) + path = [[OFSystemInfo temporaryDirectoryIRI] + IRIByAppendingPathComponent: [[OFUUID UUID] UUIDString]] + .fileSystemRepresentation; +#else + /* + * We can have sockets, including UNIX sockets, while file support is + * disabled. + * + * We also use this code path for iOS, as the temporaryDirectoryIRI is + * too long on the iOS simulator. + */ + path = [OFString stringWithFormat: @"/tmp/%@", + [[OFUUID UUID] UUIDString]]; +#endif + + @try { + address1 = [sock bindToPath: path]; + } @catch (OFBindSocketFailedException *e) { + switch (e.errNo) { + case EAFNOSUPPORT: + case EPERM: + OTSkip(@"UNIX datagram sockets unsupported"); + default: + @throw e; + } + } + + @try { + [sock sendBuffer: "Hello" length: 5 receiver: &address1]; + + OTAssertEqual([sock receiveIntoBuffer: buffer + length: 5 + sender: &address2], 5); + OTAssertEqual(memcmp(buffer, "Hello", 5), 0); + OTAssertTrue(OFSocketAddressEqual(&address1, &address2)); + OTAssertEqual(OFSocketAddressHash(&address1), + OFSocketAddressHash(&address2)); + } @finally { +#ifdef OF_HAVE_FILES + [[OFFileManager defaultManager] removeItemAtPath: path]; +#endif + } +} +@end ADDED tests/OFUNIXStreamSocketTests.m Index: tests/OFUNIXStreamSocketTests.m ================================================================== --- /dev/null +++ tests/OFUNIXStreamSocketTests.m @@ -0,0 +1,84 @@ +/* + * 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" + +#include +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFUNIXStreamSocketTests: OTTestCase +@end + +@implementation OFUNIXStreamSocketTests +- (void)testUNIXStreamSocket +{ + OFString *path; + OFUNIXStreamSocket *sockClient, *sockServer, *sockAccepted; + char buffer[5]; + +#if defined(OF_HAVE_FILES) && !defined(OF_IOS) + path = [[OFSystemInfo temporaryDirectoryIRI] + IRIByAppendingPathComponent: [[OFUUID UUID] UUIDString]] + .fileSystemRepresentation; +#else + /* + * We can have sockets, including UNIX sockets, while file support is + * disabled. + * + * We also use this code path for iOS, as the temporaryDirectory:RI is + * too long on the iOS simulator. + */ + path = [OFString stringWithFormat: @"/tmp/%@", + [[OFUUID UUID] UUIDString]]; +#endif + + sockClient = [OFUNIXStreamSocket socket]; + sockServer = [OFUNIXStreamSocket socket]; + + @try { + [sockServer bindToPath: path]; + } @catch (OFBindSocketFailedException *e) { + switch (e.errNo) { + case EAFNOSUPPORT: + case EPERM: + OTSkip(@"UNIX stream sockets unsupported"); + default: + @throw e; + } + } + + @try { + [sockServer listen]; + + [sockClient connectToPath: path]; + + sockAccepted = [sockServer accept]; + [sockAccepted writeBuffer: "Hello" length: 5]; + + OTAssertEqual([sockClient readIntoBuffer: buffer length: 5], 5); + OTAssertEqual(memcmp(buffer, "Hello", 5), 0); + + OTAssertEqual(OFSocketAddressUNIXPath( + sockAccepted.remoteAddress).length, 0); + } @finally { +#ifdef OF_HAVE_FILES + [[OFFileManager defaultManager] removeItemAtPath: path]; +#endif + } +} +@end ADDED tests/OFUTF8StringTests.m Index: tests/OFUTF8StringTests.m ================================================================== --- /dev/null +++ tests/OFUTF8StringTests.m @@ -0,0 +1,30 @@ +/* + * 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 "OFStringTests.h" + +#import "OFUTF8String.h" + +@interface OFUTF8StringTests: OFStringTests +@end + +@implementation OFUTF8StringTests +- (Class)arrayClass +{ + return [OFUTF8String class]; +} +@end ADDED tests/OFValueTests.m Index: tests/OFValueTests.m ================================================================== --- /dev/null +++ tests/OFValueTests.m @@ -0,0 +1,178 @@ +/* + * 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" + +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFValueTests: OTTestCase +@end + +@implementation OFValueTests +- (void)testObjCType +{ + OFRange range = OFMakeRange(1, 64); + OFValue *value = [OFValue valueWithBytes: &range + objCType: @encode(OFRange)]; + + OTAssertEqual(strcmp(value.objCType, @encode(OFRange)), 0); +} + +- (void)testGetValueSize +{ + OFRange range = OFMakeRange(1, 64), range2; + OFValue *value = [OFValue valueWithBytes: &range + objCType: @encode(OFRange)]; + + [value getValue: &range2 size: sizeof(OFRange)]; + OTAssert(OFEqualRanges(range2, range)); +} + +- (void)testGetValueSizeThrowsOnWrongSize +{ + OFRange range = OFMakeRange(1, 64); + OFValue *value = [OFValue valueWithBytes: &range + objCType: @encode(OFRange)]; + + OTAssertThrowsSpecific( + [value getValue: &range size: sizeof(OFRange) - 1], + OFOutOfRangeException); +} + +- (void)testPointer +{ + void *pointer = &pointer; + OFValue *value = [OFValue valueWithPointer: pointer]; + + OTAssertEqual(value.pointerValue, pointer); + OTAssertEqual([[OFValue valueWithBytes: &pointer + objCType: @encode(void *)] pointerValue], + pointer); + + OTAssertThrowsSpecific( + [[OFValue valueWithBytes: "a" + objCType: @encode(char)] pointerValue], + OFOutOfRangeException); +} + +- (void)testNonretainedObject +{ + id object = (id)&object; + OFValue *value = [OFValue valueWithNonretainedObject: object]; + + OTAssertEqual(value.nonretainedObjectValue, object); + OTAssertEqual([[OFValue + valueWithBytes: &object + objCType: @encode(id)] nonretainedObjectValue], object); + + OTAssertThrowsSpecific( + [[OFValue valueWithBytes: "a" + objCType: @encode(char)] nonretainedObjectValue], + OFOutOfRangeException); +} + +- (void)testRange +{ + OFRange range = OFMakeRange(1, 64), range2; + OFValue *value = [OFValue valueWithRange: range]; + + OTAssert(OFEqualRanges(value.rangeValue, range)); + OTAssert(OFEqualRanges( + [[OFValue valueWithBytes: &range + objCType: @encode(OFRange)] rangeValue], range)); + + [value getValue: &range2 size: sizeof(range2)]; + OTAssert(OFEqualRanges(range2, range)); + + OTAssertThrowsSpecific( + [[OFValue valueWithBytes: "a" + objCType: @encode(char)] rangeValue], + OFOutOfRangeException); +} + +- (void)testPoint +{ + OFPoint point = OFMakePoint(1.5f, 3.0f), point2; + OFValue *value = [OFValue valueWithPoint: point]; + + OTAssert(OFEqualPoints(value.pointValue, point)); + OTAssert(OFEqualPoints( + [[OFValue valueWithBytes: &point + objCType: @encode(OFPoint)] pointValue], point)); + + [value getValue: &point2 size: sizeof(point2)]; + OTAssert(OFEqualPoints(point2, point)); + + OTAssertThrowsSpecific( + [[OFValue valueWithBytes: "a" + objCType: @encode(char)] pointValue], + OFOutOfRangeException); +} + +- (void)testSize +{ + OFSize size = OFMakeSize(4.5f, 5.0f), size2; + OFValue *value = [OFValue valueWithSize: size]; + + OTAssert(OFEqualSizes(value.sizeValue, size)); + OTAssert(OFEqualSizes( + [[OFValue valueWithBytes: &size + objCType: @encode(OFSize)] sizeValue], size)); + + [value getValue: &size2 size: sizeof(size2)]; + OTAssert(OFEqualSizes(size2, size)); + + OTAssertThrowsSpecific( + [[OFValue valueWithBytes: "a" + objCType: @encode(char)] sizeValue], + OFOutOfRangeException); +} + +- (void)testRect +{ + OFRect rect = OFMakeRect(1.5f, 3.0f, 4.5f, 6.0f), rect2; + OFValue *value = [OFValue valueWithRect: rect]; + + OTAssert(OFEqualRects(value.rectValue, rect)); + OTAssert(OFEqualRects( + [[OFValue valueWithBytes: &rect + objCType: @encode(OFRect)] rectValue], rect)); + + [value getValue: &rect2 size: sizeof(rect2)]; + OTAssert(OFEqualRects(rect2, rect)); + + OTAssertThrowsSpecific( + [[OFValue valueWithBytes: "a" objCType: @encode(char)] rectValue], + OFOutOfRangeException); +} + +- (void)testIsEqual +{ + OFRect rect = OFMakeRect(1.5f, 3.0f, 4.5f, 6.0f); + + OTAssertEqualObjects([OFValue valueWithRect: rect], + [OFValue valueWithBytes: &rect + objCType: @encode(OFRect)]); + OTAssertNotEqualObjects( + [OFValue valueWithBytes: "a" objCType: @encode(signed char)], + [OFValue valueWithBytes: "a" objCType: @encode(unsigned char)]); + OTAssertNotEqualObjects( + [OFValue valueWithBytes: "a" objCType: @encode(char)], + [OFValue valueWithBytes: "b" objCType: @encode(char)]); +} +@end ADDED tests/OFWindowsRegistryKeyTests.m Index: tests/OFWindowsRegistryKeyTests.m ================================================================== --- /dev/null +++ tests/OFWindowsRegistryKeyTests.m @@ -0,0 +1,127 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFWindowsRegistryKeyTests: OTTestCase +{ + OFWindowsRegistryKey *_softwareKey, *_objFWKey; +} +@end + +@implementation OFWindowsRegistryKeyTests +- (void)setUp +{ + [super setUp]; + + _softwareKey = [[[OFWindowsRegistryKey currentUserKey] + openSubkeyAtPath: @"Software" + accessRights: KEY_ALL_ACCESS + options: 0] retain]; + _objFWKey = [[_softwareKey createSubkeyAtPath: @"ObjFW" + accessRights: KEY_ALL_ACCESS + securityAttributes: NULL + options: 0 + disposition: NULL] retain]; +} + +- (void)tearDown +{ + [_softwareKey deleteSubkeyAtPath: @"ObjFW"]; + + [super tearDown]; +} + +- (void)dealloc +{ + [_softwareKey release]; + [_objFWKey release]; + + [super dealloc]; +} + +- (void)testClassesRootKey +{ + OTAssertEqual([[OFWindowsRegistryKey classesRootKey] class], + [OFWindowsRegistryKey class]); +} + +- (void)testCurrentConfigKey +{ + OTAssertEqual([[OFWindowsRegistryKey currentConfigKey] class], + [OFWindowsRegistryKey class]); +} + +- (void)testCurrentUserKey +{ + OTAssertEqual([[OFWindowsRegistryKey currentUserKey] class], + [OFWindowsRegistryKey class]); +} + +- (void)testLocalMachineKey +{ + OTAssertEqual([[OFWindowsRegistryKey localMachineKey] class], + [OFWindowsRegistryKey class]); +} + +- (void)testOpenSubkeyAtPathAccessRightsOptionsThrowsForNonExistentKey +{ + OTAssertThrowsSpecific([[OFWindowsRegistryKey currentUserKey] + openSubkeyAtPath: @"nonexistent" + accessRights: KEY_ALL_ACCESS + options: 0], OFOpenWindowsRegistryKeyFailedException); +} + +- (void)testSetAndGetData +{ + OFData *data = [OFData dataWithItems: "abcdef" count: 6]; + DWORD type; + + [_objFWKey setData: data forValueNamed: @"data" type: REG_BINARY]; + OTAssertEqualObjects([_objFWKey dataForValueNamed: @"data" type: &type], + data); + OTAssertEqual(type, REG_BINARY); +} + +- (void)testSetAndGetString +{ + DWORD type; + + [_objFWKey setString: @"foobar" forValueNamed: @"string"]; + OTAssertEqualObjects([_objFWKey stringForValueNamed: @"string"], + @"foobar"); + + [_objFWKey setString: @"%PATH%;foo" + forValueNamed: @"expand" + type: REG_EXPAND_SZ]; + OTAssertEqualObjects([_objFWKey stringForValueNamed: @"expand" + type: &type], + @"%PATH%;foo"); + OTAssertEqual(type, REG_EXPAND_SZ); +} + +- (void)testDeleteValue +{ + [_objFWKey setString: @"foobar" forValueNamed: @"deleteme"]; + OTAssertEqualObjects([_objFWKey stringForValueNamed: @"deleteme"], + @"foobar"); + + [_objFWKey deleteValueNamed: @"deleteme"]; + OTAssertNil([_objFWKey stringForValueNamed: @"deleteme"]); +} +@end ADDED tests/OFXMLElementBuilderTests.m Index: tests/OFXMLElementBuilderTests.m ================================================================== --- /dev/null +++ tests/OFXMLElementBuilderTests.m @@ -0,0 +1,70 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFXMLElementBuilderTests: OTTestCase +{ + OFXMLNode *_nodes[2]; + size_t _i; +} +@end + +@implementation OFXMLElementBuilderTests +- (void)dealloc +{ + [_nodes[0] release]; + [_nodes[1] release]; + + [super dealloc]; +} + +- (void)elementBuilder: (OFXMLElementBuilder *)builder + didBuildElement: (OFXMLElement *)element +{ + OTAssertEqual(_i, 0); + _nodes[_i++] = [element retain]; +} + +- (void)elementBuilder: (OFXMLElementBuilder *)builder + didBuildOrphanNode: (OFXMLNode *)node +{ + OTAssertEqual(_i, 1); + _nodes[_i++] = [node retain]; +} + +- (void)testElementBuilder +{ + OFXMLParser *parser = [OFXMLParser parser]; + OFXMLElementBuilder *builder = [OFXMLElementBuilder builder]; + OFString *string = @"barbaz" + " " + ""; + + parser.delegate = builder; + builder.delegate = self; + + [parser parseString: string]; + OTAssertEqualObjects(_nodes[0].XMLString, string); + + [parser parseString: @""]; + OTAssertEqualObjects(_nodes[1].XMLString, @""); + + OTAssertEqual(_i, 2); +} +@end ADDED tests/OFXMLNodeTests.m Index: tests/OFXMLNodeTests.m ================================================================== --- /dev/null +++ tests/OFXMLNodeTests.m @@ -0,0 +1,206 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFXMLNodeTests: OTTestCase +@end + +@implementation OFXMLNodeTests +- (void)testElementWithName +{ + OTAssertEqualObjects( + [[OFXMLElement elementWithName: @"foo"] XMLString], + @""); +} + +- (void)testElementWithNameStringValue +{ + OTAssertEqualObjects( + [[OFXMLElement elementWithName: @"foo" + stringValue: @"b&ar"] XMLString], + @"b&ar"); +} + +- (void)testElementWithNameNamespace +{ + OFXMLElement *element; + + element = [OFXMLElement elementWithName: @"foo" + namespace: @"urn:objfw:test"]; + [element addAttributeWithName: @"test" stringValue: @"test"]; + [element setPrefix: @"objfw-test" forNamespace: @"urn:objfw:test"]; + OTAssertEqualObjects(element.XMLString, + @""); + + element = [OFXMLElement elementWithName: @"foo" + namespace: @"urn:objfw:test"]; + [element addAttributeWithName: @"test" stringValue: @"test"]; + OTAssertEqualObjects(element.XMLString, + @""); +} + +- (void)testElementWithNameNamespaceStringValue +{ + OFXMLElement *element = [OFXMLElement elementWithName: @"foo" + namespace: @"urn:objfw:test" + stringValue: @"x"]; + [element setPrefix: @"objfw-test" forNamespace: @"urn:objfw:test"]; + OTAssertEqualObjects(element.XMLString, + @"x"); +} + +- (void)testElementWithXMLStringAndStringValue +{ + OTAssertEqualObjects([[OFXMLElement elementWithXMLString: + @"\r\nfoo" + @"bazqux"] stringValue], + @"foobarbazqux"); +} + +- (void)testCharactersWithString +{ + OTAssertEqualObjects( + [[OFXMLCharacters charactersWithString: @""] XMLString], + @"<foo>"); +} + +- (void)testCDATAWithString +{ + OTAssertEqualObjects( + [[OFXMLCDATA CDATAWithString: @""] XMLString], + @"]]>"); +} + +- (void)testCommentWithText +{ + OTAssertEqualObjects( + [[OFXMLComment commentWithText: @" comment "] XMLString], + @""); +} + +- (void)testIsEqual +{ + OTAssertEqualObjects( + [OFXMLElement elementWithXMLString: @""], + [OFXMLElement elementWithXMLString: @""]); + + OTAssertEqualObjects( + [OFXMLElement elementWithXMLString: @""], + [OFXMLElement elementWithXMLString: @""]); + + OTAssertNotEqualObjects( + [OFXMLElement elementWithXMLString: @""], + [OFXMLElement elementWithXMLString: @""]); +} + +- (void)testHash +{ + OTAssertEqual( + [[OFXMLElement elementWithXMLString: @""] hash], + [[OFXMLElement elementWithXMLString: @""] + hash]); + + OTAssertEqual( + [[OFXMLElement elementWithXMLString: @""] hash], + [[OFXMLElement elementWithXMLString: @""] hash]); + + OTAssertNotEqual( + [[OFXMLElement elementWithXMLString: @""] hash], + [[OFXMLElement elementWithXMLString: @""] hash]); +} + +- (void)testAddAttributeWithNameStringValue +{ + OFXMLElement *element = [OFXMLElement elementWithName: @"foo" + stringValue: @"b&ar"]; + + [element setPrefix: @"objfw-test" forNamespace: @"urn:objfw:test"]; + [element addAttributeWithName: @"foo" + stringValue: @"b&ar"]; + [element addAttributeWithName: @"foo" + namespace: @"urn:objfw:test" + stringValue: @"bar"]; + + OTAssertEqualObjects(element.XMLString, + @"b&ar"); +} + +- (void)testRemoveAttributeForNameNamespace +{ + OFXMLElement *element = [OFXMLElement elementWithName: @"foo" + stringValue: @"b&ar"]; + + [element setPrefix: @"objfw-test" forNamespace: @"urn:objfw:test"]; + [element addAttributeWithName: @"foo" + stringValue: @"b&ar"]; + [element addAttributeWithName: @"foo" + namespace: @"urn:objfw:test" + stringValue: @"bar"]; + + [element removeAttributeForName: @"foo"]; + OTAssertEqualObjects(element.XMLString, + @"b&ar"); + + [element removeAttributeForName: @"foo" namespace: @"urn:objfw:test"]; + OTAssertEqualObjects(element.XMLString, @"b&ar"); +} + +- (void)testAddChild +{ + OFXMLElement *element; + + element = [OFXMLElement elementWithName: @"foo"]; + [element addAttributeWithName: @"foo" stringValue: @"b&ar"]; + [element addChild: [OFXMLElement elementWithName: @"bar"]]; + OTAssertEqualObjects(element.XMLString, + @""); + + element = [OFXMLElement elementWithName: @"foo" + namespace: @"urn:objfw:test"]; + [element setPrefix: @"objfw-test" forNamespace: @"urn:objfw:test"]; + [element addAttributeWithName: @"test" stringValue: @"test"]; + [element addChild: [OFXMLElement elementWithName: @"bar" + namespace: @"urn:objfw:test"]]; + OTAssertEqualObjects(element.XMLString, + @""); +} + +- (void)testElementsForNameNamespace +{ + OFXMLElement *element = [OFXMLElement elementWithName: @"foo"]; + OFXMLElement *bar; + + [element addChild: [OFXMLElement elementWithName: @"foo"]]; + bar = [OFXMLElement elementWithName: @"bar" + namespace: @"urn:objfw:test"]; + [element addChild: bar]; + + OTAssertEqualObjects([element elementsForName: @"bar" + namespace: @"urn:objfw:test"], + [OFArray arrayWithObject: bar]); +} + +- (void)testXMLStringWithIndentation +{ + OTAssertEqualObjects([[OFXMLElement + elementWithXMLString: @"a\nb"] + XMLStringWithIndentation: 2], + @"\n \n a\nb\n \n \n"); +} +@end ADDED tests/OFXMLParserTests.m Index: tests/OFXMLParserTests.m ================================================================== --- /dev/null +++ tests/OFXMLParserTests.m @@ -0,0 +1,415 @@ +/* + * 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" + +#include +#include + +#import "ObjFW.h" +#import "ObjFWTest.h" + +@interface OFXMLParserTests: OTTestCase +{ + int _i; +} +@end + +enum EventType { + eventTypeProcessingInstruction, + eventTypeTagOpen, + eventTypeTagClose, + eventTypeString, + eventTypeCDATA, + eventTypeComment +}; + +@implementation OFXMLParserTests +- (void)parser: (OFXMLParser *)parser + didCreateEvent: (enum EventType)type + name: (OFString *)name + prefix: (OFString *)prefix + namespace: (OFString *)namespace + attributes: (OFArray *)attrs + string: (OFString *)string +{ + switch (_i++) { + case 0: + OTAssertEqual(type, eventTypeProcessingInstruction); + OTAssertEqualObjects(name, @"xml"); + OTAssertEqualObjects(string, @"version='1.0'"); + break; + case 1: + OTAssertEqual(type, eventTypeProcessingInstruction); + OTAssertEqualObjects(name, @"p?i"); + OTAssertNil(string); + break; + case 2: + OTAssertEqual(type, eventTypeTagOpen); + OTAssertEqualObjects(name, @"root"); + OTAssertNil(prefix); + OTAssertNil(namespace); + OTAssertEqual(attrs.count, 0); + break; + case 3: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n\n "); + break; + case 4: + OTAssertEqual(type, eventTypeCDATA); + OTAssertEqualObjects(string, @"f<]]]oo]"); + OTAssertEqual(parser.lineNumber, 3); + break; + case 5: + OTAssertEqual(type, eventTypeTagOpen); + OTAssertEqualObjects(name, @"bar"); + OTAssertNil(prefix); + OTAssertNil(namespace); + OTAssertNil(attrs); + break; + case 6: + OTAssertEqual(type, eventTypeTagClose); + OTAssertEqualObjects(name, @"bar"); + OTAssertNil(prefix); + OTAssertNil(namespace); + OTAssertNil(attrs); + break; + case 7: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n "); + break; + case 8: + OTAssertEqual(type, eventTypeTagOpen); + OTAssertEqualObjects(name, @"foobar"); + OTAssertNil(prefix); + OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); + OTAssertEqualObjects(attrs, [OFArray arrayWithObject: + [OFXMLAttribute attributeWithName: @"xmlns" + stringValue: @"urn:objfw:test:" + @"foobar"]]); + break; + case 9: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n "); + break; + case 10: + OTAssertEqual(type, eventTypeTagOpen); + OTAssertEqualObjects(name, @"qux"); + OTAssertNil(prefix); + OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); + OTAssertEqualObjects(attrs, [OFArray arrayWithObject: + [OFXMLAttribute attributeWithName: @"foo" + namespace: @"http://www.w3.org/" + @"2000/xmlns/" + stringValue: @"urn:objfw:test:foo"]]); + break; + case 11: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n "); + break; + case 12: + OTAssertEqual(type, eventTypeTagOpen); + OTAssertEqualObjects(name, @"bla"); + OTAssertEqualObjects(prefix, @"foo"); + OTAssertEqualObjects(namespace, @"urn:objfw:test:foo"); + OTAssertEqualObjects(attrs, ([OFArray arrayWithObjects: + [OFXMLAttribute attributeWithName: @"bla" + namespace: @"urn:objfw:test:foo" + stringValue: @"bla"], + [OFXMLAttribute attributeWithName: @"blafoo" + stringValue: @"foo"], nil])); + break; + case 13: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n "); + break; + case 14: + OTAssertEqual(type, eventTypeTagOpen); + OTAssertEqualObjects(name, @"blup"); + OTAssertNil(prefix); + OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); + OTAssertEqualObjects(attrs, ([OFArray arrayWithObjects: + [OFXMLAttribute attributeWithName: @"qux" + namespace: @"urn:objfw:test:foo" + stringValue: @"asd"], + [OFXMLAttribute attributeWithName: @"quxqux" + stringValue: @"test"], nil])); + break; + case 15: + OTAssertEqual(type, eventTypeTagClose); + OTAssertEqualObjects(name, @"blup"); + OTAssertNil(prefix); + OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); + break; + case 16: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n "); + break; + case 17: + OTAssertEqual(type, eventTypeTagOpen); + OTAssertEqualObjects(name, @"bla"); + OTAssertEqualObjects(prefix, @"bla"); + OTAssertEqualObjects(namespace, @"urn:objfw:test:bla"); + OTAssertEqualObjects(attrs, ([OFArray arrayWithObjects: + [OFXMLAttribute attributeWithName: @"bla" + namespace: @"http://www.w3.org/" + @"2000/xmlns/" + stringValue: @"urn:objfw:test:bla"], + [OFXMLAttribute attributeWithName: @"qux" + stringValue: @"qux"], + [OFXMLAttribute attributeWithName: @"foo" + namespace: @"urn:objfw:test:bla" + stringValue: @"blafoo"], nil])); + break; + case 18: + OTAssertEqual(type, eventTypeTagClose); + OTAssertEqualObjects(name, @"bla"); + OTAssertEqualObjects(prefix, @"bla"); + OTAssertEqualObjects(namespace, @"urn:objfw:test:bla"); + break; + case 19: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n "); + break; + case 20: + OTAssertEqual(type, eventTypeTagOpen); + OTAssertEqualObjects(name, @"abc"); + OTAssertNil(prefix); + OTAssertEqualObjects(namespace, @"urn:objfw:test:abc"); + OTAssertEqualObjects(attrs, ([OFArray arrayWithObjects: + [OFXMLAttribute attributeWithName: @"xmlns" + stringValue: @"urn:objfw:test:abc"], + [OFXMLAttribute attributeWithName: @"abc" + stringValue: @"abc"], + [OFXMLAttribute attributeWithName: @"abc" + namespace: @"urn:objfw:test:foo" + stringValue: @"abc"], nil])); + break; + case 21: + OTAssertEqual(type, eventTypeTagClose); + OTAssertEqualObjects(name, @"abc"); + OTAssertNil(prefix); + OTAssertEqualObjects(namespace, @"urn:objfw:test:abc"); + break; + case 22: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n "); + break; + case 23: + OTAssertEqual(type, eventTypeTagClose); + OTAssertEqualObjects(name, @"bla"); + OTAssertEqualObjects(prefix, @"foo"); + OTAssertEqualObjects(namespace, @"urn:objfw:test:foo"); + break; + case 24: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n "); + break; + case 25: + OTAssertEqual(type, eventTypeComment); + OTAssertEqualObjects(string, @" commänt "); + break; + case 26: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n "); + break; + case 27: + OTAssertEqual(type, eventTypeTagClose); + OTAssertEqualObjects(name, @"qux"); + OTAssertNil(prefix); + OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); + break; + case 28: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n "); + break; + case 29: + OTAssertEqual(type, eventTypeTagClose); + OTAssertEqualObjects(name, @"foobar"); + OTAssertNil(prefix); + OTAssertEqualObjects(namespace, @"urn:objfw:test:foobar"); + break; + case 30: + OTAssertEqual(type, eventTypeString); + OTAssertEqualObjects(string, @"\n"); + break; + case 31: + OTAssertEqual(type, eventTypeTagClose); + OTAssertEqualObjects(name, @"root"); + OTAssertNil(prefix); + OTAssertNil(namespace); + break; + } +} + +- (void)parser: (OFXMLParser *)parser + foundProcessingInstructionWithTarget: (OFString *)target + text: (OFString *)text +{ + [self parser: parser + didCreateEvent: eventTypeProcessingInstruction + name: target + prefix: nil + namespace: nil + attributes: nil + string: text]; +} + +- (void)parser: (OFXMLParser *)parser + didStartElement: (OFString *)name + prefix: (OFString *)prefix + namespace: (OFString *)namespace + attributes: (OFArray *)attrs +{ + [self parser: parser + didCreateEvent: eventTypeTagOpen + name: name + prefix: prefix + namespace: namespace + attributes: attrs + string: nil]; +} + +- (void)parser: (OFXMLParser *)parser + didEndElement: (OFString *)name + prefix: (OFString *)prefix + namespace: (OFString *)namespace +{ + [self parser: parser + didCreateEvent: eventTypeTagClose + name: name + prefix: prefix + namespace: namespace + attributes: nil + string: nil]; +} + +- (void)parser: (OFXMLParser *)parser foundCharacters: (OFString *)string +{ + [self parser: parser + didCreateEvent: eventTypeString + name: nil + prefix: nil + namespace: nil + attributes: nil + string: string]; +} + +- (void)parser: (OFXMLParser *)parser foundCDATA: (OFString *)CDATA +{ + [self parser: parser + didCreateEvent: eventTypeCDATA + name: nil + prefix: nil + namespace: nil + attributes: nil + string: CDATA]; +} + +- (void)parser: (OFXMLParser *)parser foundComment: (OFString *)comment +{ + [self parser: parser + didCreateEvent: eventTypeComment + name: nil + prefix: nil + namespace: nil + attributes: nil + string: comment]; +} + +- (OFString *)parser: (OFXMLParser *)parser + foundUnknownEntityNamed: (OFString *)entity +{ + if ([entity isEqual: @"foo"]) + return @"foobar"; + + return nil; +} + +- (void)testParser +{ + static const char *string = "\xEF\xBB\xBF" + "\r\r" + " \n" + " \r\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + OFXMLParser *parser; + size_t j, length; + + parser = [OFXMLParser parser]; + parser.delegate = self; + + /* Simulate a stream where we only get chunks */ + length = strlen(string); + + for (j = 0; j < length; j+= 2) { + if (parser.hasFinishedParsing) + abort(); + + if (j + 2 > length) + [parser parseBuffer: string + j length: 1]; + else + [parser parseBuffer: string + j length: 2]; + } + + OTAssertEqual(_i, 32); + OTAssertEqual(parser.lineNumber, 18); + OTAssertTrue(parser.hasFinishedParsing); + + /* Parsing whitespaces after the document */ + [parser parseString: @" \t\r\n "]; + + /* Parsing comments after the document */ + [parser parseString: @" \t\r\n "]; + + /* Detection of junk after the document */ + OTAssertThrowsSpecific([parser parseString: @"a"], + OFMalformedXMLException); + OTAssertThrowsSpecific([parser parseString: @""], + OFMalformedXMLException); + + parser = [OFXMLParser parser]; + OTAssertThrowsSpecific([parser parseString: @""], + OFMalformedXMLException); +} + +- (void)testDetectionOfInvalidEncoding +{ + OFXMLParser *parser = [OFXMLParser parser]; + + OTAssertThrowsSpecific( + [parser parseString: @""], + OFInvalidEncodingException); +} +@end ADDED tests/RuntimeARCTests.m Index: tests/RuntimeARCTests.m ================================================================== --- /dev/null +++ tests/RuntimeARCTests.m @@ -0,0 +1,63 @@ +/* + * 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 "ObjFW.h" +#import "ObjFWTest.h" + +@interface RuntimeARCTests: OTTestCase +@end + +@interface RuntimeARCTestClass: OFObject +@end + +@implementation RuntimeARCTests +- (void)testExceptionsDuringInit +{ + OTAssertThrows((void)[[RuntimeARCTestClass alloc] init]); +} + +- (void)testWeakReferences +{ + id object = [[OFObject alloc] init]; + __weak id weak = object; + + OTAssertEqual(weak, object); + + object = nil; + OTAssertNil(weak); +} +@end + +@implementation RuntimeARCTestClass +- (instancetype)init +{ + self = [super init]; + +#if defined(OF_WINDOWS) && defined(OF_AMD64) + /* + * Clang has a bug on Windows where it creates an invalid call into + * objc_retainAutoreleasedReturnValue(). Work around it by not using an + * autoreleased exception. + */ + @throw [[OFException alloc] init]; +#else + @throw [OFException exception]; +#endif + + return self; +} +@end ADDED tests/RuntimeTests.m Index: tests/RuntimeTests.m ================================================================== --- /dev/null +++ tests/RuntimeTests.m @@ -0,0 +1,167 @@ +/* + * 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 "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 ADDED tests/plugin/Info.plist.in Index: tests/plugin/Info.plist.in ================================================================== --- /dev/null +++ tests/plugin/Info.plist.in @@ -0,0 +1,22 @@ + + + + + CFBundleExecutable + TestPlugin + CFBundleName + TestPlugin + CFBundleIdentifier + im.nil.objfw.tests.plugin + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleVersion + @BUNDLE_VERSION@ + CFBundleShortVersionString + @BUNDLE_SHORT_VERSION@ + MinimumOSVersion + 9.0 + + ADDED tests/plugin/Makefile Index: tests/plugin/Makefile ================================================================== --- /dev/null +++ tests/plugin/Makefile @@ -0,0 +1,11 @@ +DISTCLEAN = Info.plist + +PLUGIN_NOINST = TestPlugin${PLUGIN_SUFFIX} +SRCS = TestPlugin.m + +include ../../buildsys.mk +include ../../extra.mk + +CPPFLAGS += -I../.. -I../../src -I../../src/runtime +LIBS := ${TESTPLUGIN_LIBS} ${LIBS} +LD = ${OBJC} ADDED tests/plugin/TestPlugin.h Index: tests/plugin/TestPlugin.h ================================================================== --- /dev/null +++ tests/plugin/TestPlugin.h @@ -0,0 +1,20 @@ +/* + * 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 "OFObject.h" + +@interface TestPlugin: OFObject +- (int)test: (int)num; +@end ADDED tests/plugin/TestPlugin.m Index: tests/plugin/TestPlugin.m ================================================================== --- /dev/null +++ tests/plugin/TestPlugin.m @@ -0,0 +1,51 @@ +/* + * 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 "TestPlugin.h" + +#ifdef OF_OBJFW_RUNTIME +# import "runtime/private.h" + +OF_DESTRUCTOR() +{ + Class class = objc_getClass("TestPlugin"); + + if (class == Nil) + /* + * musl has broken dlclose(): Instead of calling the destructor + * on dlclose(), they call it on exit(). This of course means + * that our tests might have already called objc_deinit() and + * the class is already gone. + */ + return; + + objc_unregisterClass(class); +} +#endif + +@implementation TestPlugin +- (int)test: (int)num +{ + return num * 2; +} +@end + +Class +class(void) +{ + return [TestPlugin class]; +} ADDED tests/subprocess/Makefile Index: tests/subprocess/Makefile ================================================================== --- /dev/null +++ tests/subprocess/Makefile @@ -0,0 +1,9 @@ +PROG_NOINST = subprocess${PROG_SUFFIX} +SRCS = Subprocess.m + +include ../../buildsys.mk +include ../../extra.mk + +CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../.. +LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} +LD = ${OBJC} ADDED tests/subprocess/Subprocess.m Index: tests/subprocess/Subprocess.m ================================================================== --- /dev/null +++ tests/subprocess/Subprocess.m @@ -0,0 +1,43 @@ +/* + * 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 "ObjFW.h" + +@interface Subprocess: OFObject +@end + +OF_APPLICATION_DELEGATE(Subprocess) + +@implementation Subprocess +- (void)applicationDidFinishLaunching: (OFNotification *)notification +{ + OFString *line; + + if (![[OFApplication arguments] isEqual: + [OFArray arrayWithObjects: @"tést", @"123", nil]]) + [OFApplication terminateWithStatus: 1]; + + if (![[[OFApplication environment] objectForKey: @"tëst"] + isEqual: @"yés"]) + [OFApplication terminateWithStatus: 2]; + + while ((line = [OFStdIn readLine]) != nil) + [OFStdOut writeLine: line.uppercaseString]; + + [OFApplication terminate]; +} +@end ADDED tests/testfile.bin Index: tests/testfile.bin ================================================================== --- /dev/null +++ tests/testfile.bin cannot compute difference between binary files ADDED tests/testfile.ini Index: tests/testfile.ini ================================================================== --- /dev/null +++ tests/testfile.ini @@ -0,0 +1,21 @@ +[tests] +foo = bar +foobar=baz +;comment + +[foobar] +;foobarcomment +qux=" asd" +"quxqux " = asd +quxquxqux="hello\"wrld" +qux2="a\f" + +[types] +integer = 0x20 +bool = true +float = 0.5 +array1 = 1 +array2 = 1 +double = 0.25 +array1 = 2 +array2 = 2 ADDED tests/testfile.txt Index: tests/testfile.txt ================================================================== --- /dev/null +++ tests/testfile.txt @@ -0,0 +1,1 @@ +test