diff --git a/Sources/Testing/ABI/EntryPoints/EntryPoint.swift b/Sources/Testing/ABI/EntryPoints/EntryPoint.swift index 61f2f92cb..1bd2ed53a 100644 --- a/Sources/Testing/ABI/EntryPoints/EntryPoint.swift +++ b/Sources/Testing/ABI/EntryPoints/EntryPoint.swift @@ -54,12 +54,29 @@ func entryPoint(passing args: __CommandLineArguments_v0?, eventHandler: Event.Ha #if !SWT_NO_FILE_IO // Configure the event recorder to write events to stderr. if configuration.verbosity > .min { - let eventRecorder = Event.ConsoleOutputRecorder(options: .for(.stderr)) { string in - try? FileHandle.stderr.write(string) - } - configuration.eventHandler = { [oldEventHandler = configuration.eventHandler] event, context in - eventRecorder.record(event, in: context) - oldEventHandler(event, context) + // Check for experimental console output flag + if Environment.flag(named: "SWT_ENABLE_EXPERIMENTAL_CONSOLE_OUTPUT") == true { + // Use experimental AdvancedConsoleOutputRecorder + var advancedOptions = Event.AdvancedConsoleOutputRecorder.Options() + advancedOptions.base = .for(.stderr) + + let eventRecorder = Event.AdvancedConsoleOutputRecorder(options: advancedOptions) { string in + try? FileHandle.stderr.write(string) + } + + configuration.eventHandler = { [oldEventHandler = configuration.eventHandler] event, context in + eventRecorder.record(event, in: context) + oldEventHandler(event, context) + } + } else { + // Use the standard console output recorder (default behavior) + let eventRecorder = Event.ConsoleOutputRecorder(options: .for(.stderr)) { string in + try? FileHandle.stderr.write(string) + } + configuration.eventHandler = { [oldEventHandler = configuration.eventHandler] event, context in + eventRecorder.record(event, in: context) + oldEventHandler(event, context) + } } } #endif diff --git a/Sources/Testing/CMakeLists.txt b/Sources/Testing/CMakeLists.txt index 8ddaa2cb5..03b784288 100644 --- a/Sources/Testing/CMakeLists.txt +++ b/Sources/Testing/CMakeLists.txt @@ -27,6 +27,7 @@ add_library(Testing Attachments/Attachment.swift Events/Clock.swift Events/Event.swift + Events/Recorder/Event.AdvancedConsoleOutputRecorder.swift Events/Recorder/Event.ConsoleOutputRecorder.swift Events/Recorder/Event.HumanReadableOutputRecorder.swift Events/Recorder/Event.JUnitXMLRecorder.swift diff --git a/Sources/Testing/Events/Recorder/Event.AdvancedConsoleOutputRecorder.swift b/Sources/Testing/Events/Recorder/Event.AdvancedConsoleOutputRecorder.swift new file mode 100644 index 000000000..784929993 --- /dev/null +++ b/Sources/Testing/Events/Recorder/Event.AdvancedConsoleOutputRecorder.swift @@ -0,0 +1,63 @@ +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for Swift project authors +// + +extension Event { + /// An experimental console output recorder that provides enhanced test result + /// display capabilities. + /// + /// This recorder is currently experimental and must be enabled via the + /// `SWT_ENABLE_EXPERIMENTAL_CONSOLE_OUTPUT` environment variable. + struct AdvancedConsoleOutputRecorder: Sendable { + /// Configuration options for the advanced console output recorder. + struct Options: Sendable { + /// Base console output recorder options to inherit from. + var base: Event.ConsoleOutputRecorder.Options + + init() { + self.base = Event.ConsoleOutputRecorder.Options() + } + } + + /// The options for this recorder. + let options: Options + + /// The write function for this recorder. + let write: @Sendable (String) -> Void + + /// The fallback console recorder for standard output. + private let _fallbackRecorder: Event.ConsoleOutputRecorder + + /// Initialize the advanced console output recorder. + /// + /// - Parameters: + /// - options: Configuration options for the recorder. + /// - write: A closure that writes output to its destination. + init(options: Options = Options(), writingUsing write: @escaping @Sendable (String) -> Void) { + self.options = options + self.write = write + self._fallbackRecorder = Event.ConsoleOutputRecorder(options: options.base, writingUsing: write) + } + } +} + +extension Event.AdvancedConsoleOutputRecorder { + /// Record an event by processing it and generating appropriate output. + /// + /// Currently this is a skeleton implementation that delegates to + /// ``Event/ConsoleOutputRecorder``. + /// + /// - Parameters: + /// - event: The event to record. + /// - eventContext: The context associated with the event. + func record(_ event: borrowing Event, in eventContext: borrowing Event.Context) { + // Skeleton implementation: delegate to ConsoleOutputRecorder + _fallbackRecorder.record(event, in: eventContext) + } +}