From b3c245d99ac8c1f52c4d6370e468f14b7a4a6db3 Mon Sep 17 00:00:00 2001 From: JJenkx Date: Sat, 31 Oct 2026 00:18:35 -0400 Subject: [PATCH 1/3] fix(tests): run the syslog and console identity tests under a Unicode TEMP on Windows With %TEMP% holding a character outside the ANSI code page, two Windows tests still abort: - guest_syslog captures stderr through std::tmpfile(), which returns NULL there (#13083). It now opens the capture with TemporaryFile::Open(), as the other libc tests do since #13104. - guest_kernel_sys_console_identity starts its PS4 child with std::system and a command built from directory.string() and argv[0]. Both are narrow, so `cd /d` gets '?' in place of the character and fails. On Windows the command is now built from directory.wstring() and GetModuleFileNameW and run with _wsystem, as AsyncLog's child does. Co-Authored-By: Claude Opus 5.5 --- .../libs/tests/GuestKernelSysConsoleIdentity.cpp | 16 ++++++++++++++-- core/libs/tests/GuestSyslog.cpp | 3 ++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/core/libs/tests/GuestKernelSysConsoleIdentity.cpp b/core/libs/tests/GuestKernelSysConsoleIdentity.cpp index dc953c7fbb..3dacd9e8b6 100644 --- a/core/libs/tests/GuestKernelSysConsoleIdentity.cpp +++ b/core/libs/tests/GuestKernelSysConsoleIdentity.cpp @@ -11,6 +11,15 @@ #include #include #include +#ifdef _WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif namespace { @@ -103,11 +112,14 @@ int main(int argc, char** argv) { file << std::string("TITLE\0TITLE_ID\0\0\0\0\0\0", 20) << std::string("Example\0", 8) << "CUSA00000" << std::string("\0\0\0", 3); } #ifdef _WIN32 - const std::string command = "\"cd /d \"" + directory.string() + "\" && \"" + argv[0] + "\" ps4-child\""; + std::wstring executable(32768, L'\0'); + executable.resize(GetModuleFileNameW(nullptr, executable.data(), static_cast(executable.size()))); + const std::wstring command = L"\"cd /d \"" + directory.wstring() + L"\" && \"" + executable + L"\" ps4-child\""; + const int status = _wsystem(command.c_str()); #else const std::string command = "cd \"" + directory.string() + "\" && \"" + argv[0] + "\" ps4-child"; -#endif const int status = std::system(command.c_str()); +#endif std::filesystem::remove_all(directory); Require(status == 0, "the PS4 child process must succeed"); return 0; diff --git a/core/libs/tests/GuestSyslog.cpp b/core/libs/tests/GuestSyslog.cpp index c0a954c07a..8d541a4401 100644 --- a/core/libs/tests/GuestSyslog.cpp +++ b/core/libs/tests/GuestSyslog.cpp @@ -1,5 +1,6 @@ #include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" +#include "tests/TemporaryFile.hpp" #include #include #include @@ -14,7 +15,7 @@ static void Require(bool value) { if (!value) std::abort(); } int main() { - auto* captured = std::tmpfile(); + auto* captured = TemporaryFile::Open(); Require(captured != nullptr); std::fflush(stderr); #ifdef _WIN32 From b1f846078f871b8fd4d1ddffbbda00c1ec300ef9 Mon Sep 17 00:00:00 2001 From: JJenkx Date: Sat, 31 Oct 2026 00:32:47 -0400 Subject: [PATCH 2/3] fix(tests): set the shader cache directory as a wide variable under a Unicode TEMP on Windows agc_pipeline_cache_header and agc_driver_lazy_resolved_abi passed ANYPS5_SHADER_CACHE_DIR through the narrow _putenv_s with path::string(), which is UTF-8 in MinGW's libstdc++. The driver reads the variable wide, so under a TEMP outside the ANSI code page it got a mangled directory: the header test's directory scan threw, and the lazy test found no cache files where it looked. On Windows both tests now set it with _wputenv_s from the wide path. Co-Authored-By: Claude Opus 5.5 --- core/libs/prx/libSceAgcDriver/tests/Recorder.cpp | 2 +- .../prx/libSceAgcDriver/tests/execution/LazyResolvedAbi.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp b/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp index f2b1f233fc..5c8c38f752 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp @@ -11086,7 +11086,7 @@ void pipelineCacheHeaderTests(const Device& device) { Require(versionDirectory.native().size() >= 220 && versionDirectory.native().size() <= 249, "the pipeline cache directory is not between 220 and 249 characters"); #ifdef _WIN32 _putenv_s("ANYPS5_NO_SHADER_CACHE", "0"); - _putenv_s("ANYPS5_SHADER_CACHE_DIR", directory.string().c_str()); + _wputenv_s(L"ANYPS5_SHADER_CACHE_DIR", directory.c_str()); #else setenv("ANYPS5_NO_SHADER_CACHE", "0", 1); setenv("ANYPS5_SHADER_CACHE_DIR", directory.string().c_str(), 1); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/LazyResolvedAbi.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/LazyResolvedAbi.cpp index aad7c87ddb..923ff59054 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/LazyResolvedAbi.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/LazyResolvedAbi.cpp @@ -602,7 +602,11 @@ int main(int argc, char** argv) { std::filesystem::create_directories(cache); SetEnvironment("LAZY_RESOLVED_ABI_REFERENCE", reference.string()); SetEnvironment("ANYPS5_NO_SHADER_CACHE", "0"); +#ifdef _WIN32 + _wputenv_s(L"ANYPS5_SHADER_CACHE_DIR", cache.c_str()); +#else SetEnvironment("ANYPS5_SHADER_CACHE_DIR", cache.string()); +#endif SetEnvironment("APS5_NO_PIPELINE_JOURNAL", "1"); ClearEnvironment("APS5_LAZY_SHADER_PREPARE"); const std::string command = "\"" + std::string(argv[0]) + "\" --eager-reference"; From eab4fef05cf1e6047634abc2caa0e6f0cc597142 Mon Sep 17 00:00:00 2001 From: JJenkx Date: Sat, 31 Oct 2026 09:30:47 -0400 Subject: [PATCH 3/3] fix(tests): start the Audio3d PS4-process child through a wide command on Windows guest_audio3d_port reruns its own executable from a temporary directory, and built the command from directory.string() and argv[0] for std::system. Under a TEMP with characters outside the active code page the narrow command lost them, cmd.exe could not change into the directory, and the test aborted at "the PS4 process checks must pass". On Windows the command is now built from directory.wstring() and the module's own path from GetModuleFileNameW, and run with _wsystem, as the console identity test does. Co-Authored-By: Claude Opus 5.5 --- core/libs/tests/GuestAudio3dPort.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/core/libs/tests/GuestAudio3dPort.cpp b/core/libs/tests/GuestAudio3dPort.cpp index 5dea9e7bdd..0cc56ad6fd 100644 --- a/core/libs/tests/GuestAudio3dPort.cpp +++ b/core/libs/tests/GuestAudio3dPort.cpp @@ -16,6 +16,15 @@ #include #include #include +#ifdef _WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif namespace { @@ -655,11 +664,15 @@ int RunAsPs4Process(const char* program) { file << std::string("TITLE\0TITLE_ID\0\0\0\0\0\0", 20) << std::string("Example\0", 8) << "CUSA00000" << std::string("\0\0\0", 3); } #ifdef _WIN32 - const std::string command = "\"cd /d \"" + directory.string() + "\" && \"" + program + "\" ps4-process\""; + static_cast(program); + std::wstring executable(32768, L'\0'); + executable.resize(GetModuleFileNameW(nullptr, executable.data(), static_cast(executable.size()))); + const std::wstring command = L"\"cd /d \"" + directory.wstring() + L"\" && \"" + executable + L"\" ps4-process\""; + const int status = _wsystem(command.c_str()); #else const std::string command = "cd \"" + directory.string() + "\" && \"" + program + "\" ps4-process"; -#endif const int status = std::system(command.c_str()); +#endif std::filesystem::remove_all(directory); return status; }