Files
AnyPS5/core/libs/tests/TemporaryFile.hpp
T
bunbeans2-archandClaude Opus 5.5 6878d1be40 fix(tests): open scratch streams under a Unicode TEMP on Windows
On Windows, std::tmpfile() returns NULL with errno 22 when %TEMP%
contains a character outside the ANSI code page, where GetTempPathA
returns '?' in its place. Fifteen tests that capture output through it
aborted. TemporaryFile::Open() opens a unique delete-on-close file under
temp_directory_path() with _wfopen; other hosts keep std::tmpfile().

Part of #13083

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 18:21:00 +01:00

39 lines
1003 B
C++

#ifndef CORE_LIBS_TESTS_TEMPORARYFILE_HPP
#define CORE_LIBS_TESTS_TEMPORARYFILE_HPP
#include <cstdio>
#ifdef _WIN32
#include <atomic>
#include <cerrno>
#include <chrono>
#include <filesystem>
#include <process.h>
#include <string>
#include <system_error>
#endif
namespace TemporaryFile {
inline std::FILE* Open() {
#ifdef _WIN32
static std::atomic<unsigned> serial{0};
std::error_code error;
const auto directory = std::filesystem::temp_directory_path(error);
if (error) return nullptr;
for (int attempt = 0; attempt < 100; ++attempt) {
const auto tick = std::chrono::steady_clock::now().time_since_epoch().count();
const auto name = directory / ("anyps5-test-" + std::to_string(_getpid()) + "-" + std::to_string(tick) + "-" + std::to_string(serial++) + ".tmp");
if (std::FILE* file = _wfopen(name.c_str(), L"w+bxD")) return file;
if (errno != EEXIST) return nullptr;
}
return nullptr;
#else
return std::tmpfile();
#endif
}
}
#endif