Index: .fossil-settings/clean-glob ================================================================== --- .fossil-settings/clean-glob +++ .fossil-settings/clean-glob @@ -37,10 +37,11 @@ tests/EBOOT.PBP tests/Info.plist tests/PARAM.SFO tests/objc_sync/objc_sync tests/plugin/Info.plist +tests/subprocess/subprocess tests/terminal/terminal_tests tests/testfile_bin.m tests/testfile_ini.m tests/tests tests/tests.3dsx Index: .fossil-settings/ignore-glob ================================================================== --- .fossil-settings/ignore-glob +++ .fossil-settings/ignore-glob @@ -42,10 +42,11 @@ tests/iOS.xcodeproj/*.pbxuser tests/iOS.xcodeproj/project.xcworkspace tests/iOS.xcodeproj/xcuserdata tests/objc_sync/objc_sync tests/plugin/Info.plist +tests/subprocess/subprocess tests/terminal/terminal_tests tests/testfile_bin.m tests/testfile_ini.m tests/tests tests/tests.3dsx Index: .gitignore ================================================================== --- .gitignore +++ .gitignore @@ -42,10 +42,11 @@ tests/iOS.xcodeproj/*.pbxuser tests/iOS.xcodeproj/project.xcworkspace tests/iOS.xcodeproj/xcuserdata tests/objc_sync/objc_sync tests/plugin/Info.plist +tests/subprocess/subprocess tests/terminal/terminal_tests tests/testfile_bin.m tests/testfile_ini.m tests/tests tests/tests.3dsx Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -1954,11 +1954,12 @@ break ]) ]) ]) AS_IF([test x"$have_subprocesses" = x"yes"], [ - AC_SUBST(OF_SUBPROCESS_M, "OFSubprocess.m") + AC_SUBST(USE_SRCS_SUBPROCESS, '${SRCS_SUBPROCESS}') + AC_SUBST(SUBPROCESS, "subprocess") AC_DEFINE(OF_HAVE_SUBPROCESSES, 1, [Whether we have subprocesses]) ]) AC_CHECK_HEADERS_ONCE([complex.h sys/ioctl.h sys/ttycom.h]) AC_CHECK_FUNCS(ioctl isatty) Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -60,11 +60,10 @@ OF_KQUEUE_KERNEL_EVENT_OBSERVER_M = @OF_KQUEUE_KERNEL_EVENT_OBSERVER_M@ OF_OPENSSL_TLS_STREAM_M = @OF_OPENSSL_TLS_STREAM_M@ OF_POLL_KERNEL_EVENT_OBSERVER_M = @OF_POLL_KERNEL_EVENT_OBSERVER_M@ OF_SECURE_TRANSPORT_TLS_STREAM_M = @OF_SECURE_TRANSPORT_TLS_STREAM_M@ OF_SELECT_KERNEL_EVENT_OBSERVER_M = @OF_SELECT_KERNEL_EVENT_OBSERVER_M@ -OF_SUBPROCESS_M = @OF_SUBPROCESS_M@ REEXPORT_RUNTIME = @REEXPORT_RUNTIME@ REEXPORT_RUNTIME_FRAMEWORK = @REEXPORT_RUNTIME_FRAMEWORK@ RUNTIME = @RUNTIME@ RUNTIME_ARC_TESTS_M = @RUNTIME_ARC_TESTS_M@ RUNTIME_AUTORELEASE_M = @RUNTIME_AUTORELEASE_M@ @@ -72,10 +71,11 @@ RUNTIME_INSTANCE_M = @RUNTIME_INSTANCE_M@ RUNTIME_LIBS = @RUNTIME_LIBS@ SFDC_INLINE_H = @SFDC_INLINE_H@ SFDC_TARGET = @SFDC_TARGET@ SFD_FILE = @SFD_FILE@ +SUBPROCESS = @SUBPROCESS@ TESTPLUGIN = @TESTPLUGIN@ TESTPLUGIN_LIBS = @TESTPLUGIN_LIBS@ TESTS_LIBS = @TESTS_LIBS@ TESTS_STATIC_LIB = @TESTS_STATIC_LIB@ TLS = @TLS@ @@ -86,10 +86,11 @@ USE_SRCS_APPLETALK = @USE_SRCS_APPLETALK@ USE_SRCS_FILES = @USE_SRCS_FILES@ USE_SRCS_IPX = @USE_SRCS_IPX@ USE_SRCS_PLUGINS = @USE_SRCS_PLUGINS@ USE_SRCS_SOCKETS = @USE_SRCS_SOCKETS@ +USE_SRCS_SUBPROCESS = @USE_SRCS_SUBPROCESS@ USE_SRCS_TAGGED_POINTERS = @USE_SRCS_TAGGED_POINTERS@ USE_SRCS_THREADS = @USE_SRCS_THREADS@ USE_SRCS_UNIX_SOCKETS = @USE_SRCS_UNIX_SOCKETS@ USE_SRCS_WINDOWS = @USE_SRCS_WINDOWS@ WRAPPER = @WRAPPER@ Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -87,11 +87,10 @@ OFString+JSONParsing.m \ OFString+PercentEncoding.m \ OFString+PropertyListParsing.m \ OFString+XMLEscaping.m \ OFString+XMLUnescaping.m \ - ${OF_SUBPROCESS_M} \ OFSystemInfo.m \ OFTarArchive.m \ OFTarArchiveEntry.m \ OFThread.m \ OFTimer.m \ @@ -110,10 +109,11 @@ OFZIPArchive.m \ OFZIPArchiveEntry.m \ ${USE_SRCS_FILES} \ ${USE_SRCS_PLUGINS} \ ${USE_SRCS_SOCKETS} \ + ${USE_SRCS_SUBPROCESS} \ ${USE_SRCS_THREADS} \ ${USE_SRCS_WINDOWS} SRCS_FILES = OFFile.m \ OFString+PathAdditions.m SRCS_PLUGINS = OFPlugin.m @@ -142,10 +142,11 @@ SRCS_IPX = OFIPXSocket.m \ OFSPXSocket.m \ OFSPXStreamSocket.m SRCS_UNIX_SOCKETS = OFUNIXDatagramSocket.m \ OFUNIXStreamSocket.m +SRCS_SUBPROCESS = OFSubprocess.m SRCS_THREADS = OFCondition.m \ OFMutex.m \ OFPlainCondition.m \ OFPlainMutex.m \ OFPlainThread.m \ Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -1,9 +1,10 @@ include ../extra.mk SUBDIRS = ${TESTPLUGIN} \ ${OBJC_SYNC} \ + ${SUBPROCESS} \ terminal CLEAN = EBOOT.PBP \ boot.dol \ ${PROG_NOINST}.arm9 \ @@ -59,10 +60,11 @@ ${RUNTIME_ARC_TESTS_M} \ TestsAppDelegate.m \ ${USE_SRCS_FILES} \ ${USE_SRCS_PLUGINS} \ ${USE_SRCS_SOCKETS} \ + ${USE_SRCS_SUBPROCESS} \ ${USE_SRCS_THREADS} \ ${USE_SRCS_WINDOWS} \ testfile_bin.m \ testfile_ini.m SRCS_PLUGINS = OFPluginTests.m @@ -81,10 +83,11 @@ SRCS_IPX = OFIPXSocketTests.m \ OFSPXSocketTests.m \ OFSPXStreamSocketTests.m SRCS_UNIX_SOCKETS = OFUNIXDatagramSocketTests.m \ OFUNIXStreamSocketTests.m +SRCS_SUBPROCESS = OFSubprocessTests.m SRCS_THREADS = OFThreadTests.m SRCS_WINDOWS = OFWindowsRegistryKeyTests.m IOS_USER ?= mobile IOS_TMP ?= /tmp/objfw-test @@ -224,10 +227,15 @@ rm -fr romfs tests.nacp ${PROG_NOINST}.rpx: ${PROG_NOINST} elf2rpl $< $@ -CPPFLAGS += -I../src -I../src/exceptions -I../src/runtime -I.. -DSTDOUT +CPPFLAGS += -I../src \ + -I../src/exceptions \ + -I../src/runtime \ + -I.. \ + -DSTDOUT \ + -DPROG_SUFFIX=\"${PROG_SUFFIX}\" OBJCFLAGS_RuntimeARCTests.m = -fobjc-arc -fobjc-arc-exceptions LIBS := ${TESTS_LIBS} ${LIBS} LDFLAGS += ${MAP_LDFLAGS} LD = ${OBJC} ADDED tests/OFSubprocessTests.m Index: tests/OFSubprocessTests.m ================================================================== --- tests/OFSubprocessTests.m +++ tests/OFSubprocessTests.m @@ -0,0 +1,57 @@ +/* + * 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 "TestsAppDelegate.h" + +static OFString *const module = @"OFSubprocess"; + +@implementation TestsAppDelegate (OFSubprocessTests) +- (void)subprocessTests +{ + void *pool = objc_autoreleasePoolPush(); +#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"]; + + TEST(@"+[subprocessWithProgram:programName:arguments:environment]", + (subprocess = + [OFSubprocess subprocessWithProgram: program + programName: program + arguments: arguments + environment: environment])) + + TEST(@"Standard input", R([subprocess writeLine: @"Hellö world!"])) + + TEST(@"Standard output", + [[subprocess readLine] isEqual: @"HELLÖ WORLD!"]) + + TEST(@"-[closeForWriting]", R([subprocess closeForWriting])) + + TEST(@"-[waitForTermination]", [subprocess waitForTermination] == 0) + + objc_autoreleasePoolPop(pool); +} +@end Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -248,10 +248,14 @@ @end @interface TestsAppDelegate (OFStringTests) - (void)stringTests; @end + +@interface TestsAppDelegate (OFSubprocessTests) +- (void)subprocessTests; +@end @interface TestsAppDelegate (OFTCPSocketTests) - (void)TCPSocketTests; @end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -442,12 +442,15 @@ [self XMLElementBuilderTests]; [self JSONTests]; [self propertyListTests]; [self matrix4x4Tests]; -#if defined(OF_HAVE_PLUGINS) +#ifdef OF_HAVE_PLUGINS [self pluginTests]; +#endif +#ifdef OF_HAVE_SUBPROCESSES + [self subprocessTests]; #endif #ifdef OF_WINDOWS [self windowsRegistryKeyTests]; #endif ADDED tests/subprocess/Makefile Index: tests/subprocess/Makefile ================================================================== --- tests/subprocess/Makefile +++ 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 ================================================================== --- tests/subprocess/Subprocess.m +++ 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