diff --git a/Sources/Testing/Support/FileHandle.swift b/Sources/Testing/Support/FileHandle.swift index 453cedcd0..9aca4a671 100644 --- a/Sources/Testing/Support/FileHandle.swift +++ b/Sources/Testing/Support/FileHandle.swift @@ -52,6 +52,21 @@ struct FileHandle: ~Copyable, Sendable { /// - Throws: Any error preventing the stream from being opened. init(atPath path: String, mode: String) throws { #if os(Windows) + // Special-case CONOUT$ to map to stdout. This way, if somebody specifies + // CONOUT$ as the target path for XML or JSON output from `swift test`, + // output will be correctly interleaved with writes to `stdout`. If we don't + // do this, the file will open successfully but will be opened in text mode + // (even if we ask for binary mode), will wrap at the virtual console's + // column limit, and won't share a file lock with the C `stdout` handle. + // + // To our knowledge, this sort of special-casing is not required on + // POSIX-like platforms (i.e. when opening "/dev/stdout"), but it can be + // adapted for use there if some POSIX-like platform does need it. + if path == "CONOUT$" && mode.contains("w") { + self = .stdout + return + } + // Windows deprecates fopen() as insecure, so call _wfopen_s() instead. let fileHandle = try path.withCString(encodedAs: UTF16.self) { path in try mode.withCString(encodedAs: UTF16.self) { mode in