https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=6df7cdc54b042451f76f3f9cbe3cc1138053a90c
commit 6df7cdc54b042451f76f3f9cbe3cc1138053a90c Author: Jeremy Drake <cyg...@jdrake.com> Date: Tue Jun 17 16:40:56 2025 -0700 Cygwin: testsuite: add posix_spawn tests Currently just a couple of tests of error conditions, but I have more tests to add. Signed-off-by: Jeremy Drake <cyg...@jdrake.com> Diff: --- winsup/testsuite/Makefile.am | 1 + winsup/testsuite/winsup.api/posix_spawn/errors.c | 57 ++++++++++++++++++++++++ winsup/testsuite/winsup.api/posix_spawn/test.h | 38 ++++++++++++++++ 3 files changed, 96 insertions(+) diff --git a/winsup/testsuite/Makefile.am b/winsup/testsuite/Makefile.am index 8f2967a6d..0b265261c 100644 --- a/winsup/testsuite/Makefile.am +++ b/winsup/testsuite/Makefile.am @@ -311,6 +311,7 @@ check_PROGRAMS = \ winsup.api/pthread/self2 \ winsup.api/pthread/threadidafterfork \ winsup.api/pthread/tsd1 \ + winsup.api/posix_spawn/errors \ winsup.api/samples/sample-fail \ winsup.api/samples/sample-pass # winsup.api/ltp/ulimit01 is omitted as we don't have <ulimit.h> diff --git a/winsup/testsuite/winsup.api/posix_spawn/errors.c b/winsup/testsuite/winsup.api/posix_spawn/errors.c new file mode 100644 index 000000000..38563441f --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/errors.c @@ -0,0 +1,57 @@ +#include "test.h" +#include <spawn.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static char tmppath[] = "pspawn.XXXXXX"; +static const char exit0[] = "exit 0\n"; + +void cleanup_tmpfile (void) +{ + unlink (tmppath); +} + +int main (void) +{ + pid_t pid; + int fd; + char *childargv[] = {"ls", NULL}; + char tmpsub[sizeof (tmppath) + 3]; + char *p; + + /* unbuffer stdout */ + setvbuf(stdout, NULL, _IONBF, 0); + + negError (fd = mkstemp (tmppath)); + atexit (cleanup_tmpfile); + negError (write (fd, exit0, sizeof (exit0) - 1)); + negError (close (fd)); + + /* expected ENOENT: posix_spawn without full path */ + errCodeExpected (ENOENT, + posix_spawn (&pid, childargv[0], NULL, NULL, childargv, environ)); + + /* expected EACCES: posix_spawn with path to non-executable file */ + errCodeExpected (EACCES, + posix_spawn (&pid, tmppath, NULL, NULL, childargv, environ)); + + negError (chmod (tmppath, 0755)); + + /* expected ENOEXEC: posix_spawn with unrecognized file format */ + errCodeExpected (ENOEXEC, + posix_spawn (&pid, tmppath, NULL, NULL, childargv, environ)); + + p = stpcpy (tmpsub, tmppath); + p = stpcpy (p, "/ls"); + +#ifndef __CYGWIN__ + /* Cygwin returns ENOENT rather than ENOTDIR here */ + /* expected ENOTDIR: posix_spawn with file as non-leaf entry in path */ + errCodeExpected (ENOTDIR, + posix_spawn (&pid, tmpsub, NULL, NULL, childargv, environ)); +#endif + + return 0; +} diff --git a/winsup/testsuite/winsup.api/posix_spawn/test.h b/winsup/testsuite/winsup.api/posix_spawn/test.h new file mode 100644 index 000000000..e10b6ce5e --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/test.h @@ -0,0 +1,38 @@ +#ifndef _POSIX_SPAWN_TEST_H_ +#define _POSIX_SPAWN_TEST_H_ + +#define _GNU_SOURCE +#include <errno.h> +#include <error.h> +#include <signal.h> +#include <sys/wait.h> + +#define negError(x) do { \ + if ((x) < 0) \ + error_at_line(1, errno, __FILE__, __LINE__, "%s", #x); \ +} while (0) + +#define sigError(x) do { \ + if ((x) == SIG_ERR) \ + error_at_line(1, errno, __FILE__, __LINE__, "%s", #x); \ +} while (0) + +#define errCodeExpected(expected, x) do { \ + int _errcode = (x); \ + if (_errcode != (expected)) \ + error_at_line(1, _errcode, __FILE__, __LINE__, "%s", #x); \ +} while (0) + +#define errCode(x) errCodeExpected(0, x) + +#define exitStatus(status, expectedExitCode) do { \ + if (WIFSIGNALED ((status))) \ + error_at_line (128 + WTERMSIG ((status)), 0, __FILE__, __LINE__ - 2, \ + "child terminated with signal %d", WTERMSIG ((status))); \ + else if (WIFEXITED ((status)) && WEXITSTATUS ((status)) != (expectedExitCode)) \ + error_at_line (WEXITSTATUS ((status)), 0, __FILE__, __LINE__ - 2, \ + "child exited with code %d", WEXITSTATUS ((status))); \ +} while (0) + +#endif /* _POSIX_SPAWN_TEST_H_ */ +