[newlib-cygwin] Cygwin: testsuite: add a mingw test program to spawn

Jeremy Drake via Cygwin-cvs <[email protected]>
Newsgroups gmane.os.cygwin.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=2af1914b6ad673a2041cf94cc8e78e1bdec57a27

commit 2af1914b6ad673a2041cf94cc8e78e1bdec57a27
Author: Jeremy Drake <[email protected]>
Date:   Wed Jun 25 16:42:08 2025 -0700

    Cygwin: testsuite: add a mingw test program to spawn
    
    This program is currently meant to test standard file handles and
    current working directory (since these are settable via posix_spawn),
    but could be extended to add additional checks if other cygwin-to-win32
    process properties need to be tested.
    
    Signed-off-by: Jeremy Drake <[email protected]>

Diff:
---
 winsup/testsuite/Makefile.am                       |   2 +-
 winsup/testsuite/cygrun.sh                         |   4 +-
 winsup/testsuite/mingw/Makefile.am                 |   7 +-
 winsup/testsuite/winsup.api/posix_spawn/winchild.c | 130 +++++++++++++++++++++
 4 files changed, 139 insertions(+), 4 deletions(-)

diff --git a/winsup/testsuite/Makefile.am b/winsup/testsuite/Makefile.am
index 957554a82..03f65d818 100644
--- a/winsup/testsuite/Makefile.am
+++ b/winsup/testsuite/Makefile.am
@@ -349,7 +349,7 @@ XFAIL_TESTS = \
 LOG_COMPILER = $(srcdir)/cygrun.sh
 
 export runtime_root=$(abs_builddir)/testinst/bin
-export cygrun=$(builddir)/mingw/cygrun
+export mingwtestdir=$(builddir)/mingw
 
 # Set up things in the Cygwin 'installation' at testsuite/testinst/ to provide
 # things which tests need to work
diff --git a/winsup/testsuite/cygrun.sh b/winsup/testsuite/cygrun.sh
index bf1d5cc6b..f1673e4db 100755
--- a/winsup/testsuite/cygrun.sh
+++ b/winsup/testsuite/cygrun.sh
@@ -11,7 +11,7 @@ export PATH="$runtime_root:${PATH}"
 if [ "$1" = "./mingw/cygload" ]
 then
     windows_runtime_root=$(cygpath -m $runtime_root)
-    $cygrun "$exe -v -cygwin $windows_runtime_root/cygwin1.dll"
+    $mingwtestdir/cygrun "$exe -v -cygwin $windows_runtime_root/cygwin1.dll"
 else
-    cygdrop $cygrun $exe
+    cygdrop $mingwtestdir/cygrun $exe
 fi
diff --git a/winsup/testsuite/mingw/Makefile.am b/winsup/testsuite/mingw/Makefile.am
index 772e73405..25300a15d 100644
--- a/winsup/testsuite/mingw/Makefile.am
+++ b/winsup/testsuite/mingw/Makefile.am
@@ -16,7 +16,7 @@ override CC = @MINGW_CC@
 override CXX = @MINGW_CXX@
 AM_CPPFLAGS =
 
-noinst_PROGRAMS = cygrun cygload
+noinst_PROGRAMS = cygrun cygload winchild
 
 cygrun_SOURCES = \
 	../cygrun.c
@@ -24,3 +24,8 @@ cygrun_SOURCES = \
 cygload_SOURCES = \
 	../winsup.api/cygload.cc
 cygload_LDFLAGS=-static -Wl,-e,cygloadCRTStartup
+
+winchild_SOURCES = \
+	../winsup.api/posix_spawn/winchild.c
+winchild_LDFLAGS=-municode
+winchild_LDADD=-lntdll
diff --git a/winsup/testsuite/winsup.api/posix_spawn/winchild.c b/winsup/testsuite/winsup.api/posix_spawn/winchild.c
new file mode 100644
index 000000000..6fdfa002c
--- /dev/null
+++ b/winsup/testsuite/winsup.api/posix_spawn/winchild.c
@@ -0,0 +1,130 @@
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winternl.h>
+#include <ctype.h>
+#include <stdio.h>
+
+
+int wmain (int argc, wchar_t **argv)
+{
+  if (argc != 3)
+    {
+      fwprintf (stderr, L"Usage: %ls handle expected\n", argv[0]);
+      return 1;
+    }
+
+  if (!wcscmp (argv[1], L"CWD"))
+    {
+      LPWSTR buffer;
+      DWORD len = GetCurrentDirectoryW (0, NULL);
+      if (len == 0)
+        {
+	  fwprintf (stderr, L"%ls: GetCurrentDirectory failed with error %lu\n",
+		    argv[0], GetLastError ());
+	  return 2;
+	}
+      buffer = malloc (len * sizeof (WCHAR));
+      if (GetCurrentDirectoryW (len, buffer) != len - 1)
+        {
+	  fwprintf (stderr, L"%ls: GetCurrentDirectory failed with error %lu\n",
+		    argv[0], GetLastError ());
+	  return 2;
+	}
+      if (wcscmp (argv[2], buffer))
+        {
+	  fwprintf (stderr, L"%ls: CWD '%ls' != expected '%ls'\n",
+		    argv[0], buffer, argv[2]);
+	  free (buffer);
+	  return 4;
+	}
+      free (buffer);
+    }
+  else if (iswdigit (argv[1][0]) && !argv[1][1])
+    {
+      HANDLE stdhandle;
+      DWORD nStdHandle;
+      switch (argv[1][0])
+      {
+	case L'0':
+	  nStdHandle = STD_INPUT_HANDLE;
+	  break;
+	case L'1':
+	  nStdHandle = STD_OUTPUT_HANDLE;
+	  break;
+	case L'2':
+	  nStdHandle = STD_ERROR_HANDLE;
+	  break;
+	default:
+	  fwprintf (stderr, L"%ls: Unknown handle '%ls'\n", argv[0], argv[1]);
+	  return 1;
+      }
+
+      stdhandle = GetStdHandle (nStdHandle);
+      if (stdhandle == INVALID_HANDLE_VALUE)
+        {
+	  fwprintf (stderr, L"%ls: Failed getting standard handle %ls: %lu\n",
+	      argv[0], argv[1], GetLastError ());
+	  return 2;
+	}
+      else if (stdhandle == NULL)
+	{
+	  if (wcscmp (argv[2], L"<CLOSED>"))
+	    {
+	      fwprintf (stderr,
+			L"%ls: Handle %ls name '%ls' != expected '%ls'\n",
+			argv[0], argv[1], L"<CLOSED>", argv[2]);
+	      return 4;
+	    }
+	}
+      else
+        {
+	  LPWSTR buf, win32path;
+	  buf = malloc (65536);
+	  if (!GetFinalPathNameByHandleW (stdhandle, buf,
+					  65536 / sizeof (WCHAR),
+					  FILE_NAME_OPENED|VOLUME_NAME_DOS))
+	    {
+	      POBJECT_NAME_INFORMATION pinfo = (POBJECT_NAME_INFORMATION) buf;
+	      DWORD err = GetLastError ();
+	      ULONG len;
+	      NTSTATUS status = NtQueryObject (stdhandle, ObjectNameInformation,
+					       pinfo, 65536, &len);
+	      if (!NT_SUCCESS (status))
+		{
+		  fwprintf (stderr,
+		      L"%ls: NtQueryObject for handle %ls failed: 0x%08x\n",
+		      argv[0], argv[1], status);
+		  free (buf);
+		  return 3;
+		}
+
+	      pinfo->Name.Buffer[pinfo->Name.Length / sizeof (WCHAR)] = L'\0';
+	      win32path = pinfo->Name.Buffer;
+	    }
+	  else
+	    {
+	      static const WCHAR prefix[] = L"\\\\?\\";
+	      win32path = buf;
+	      if (!wcsncmp (win32path, prefix,
+			    sizeof (prefix) / sizeof (WCHAR) - 1))
+		win32path += sizeof (prefix) / sizeof (WCHAR) - 1;
+	    }
+
+	  if (wcscmp (win32path, argv[2]))
+	    {
+	      fwprintf (stderr,
+			L"%ls: Handle %ls name '%ls' != expected '%ls'\n",
+			argv[0], argv[1], win32path, argv[2]);
+	      free (buf);
+	      return 4;
+	    }
+	  free (buf);
+	}
+    }
+  else
+    {
+      fwprintf (stderr, L"%ls: Unknown handle '%ls'\n", argv[0], argv[1]);
+      return 1;
+    }
+  return 0;
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.