Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an experimental console output prefix option for command-line output. #476

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Sources/Testing/EntryPoints/EntryPoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ func entryPoint(passing args: __CommandLineArguments_v0?, eventHandler: Event.Ha
var options = Event.ConsoleOutputRecorder.Options()
options = .for(.stderr)
options.verbosity = args.verbosity
if let prefix = args.experimentalConsoleOutputPrefix {
options.prefix = prefix
}
let eventRecorder = Event.ConsoleOutputRecorder(options: options) { string in
try? FileHandle.stderr.write(string)
}
Expand Down Expand Up @@ -228,6 +231,9 @@ public struct __CommandLineArguments_v0: Sendable {
/// 0 JSON schema is finalized.
public var experimentalEventStreamVersion: Int?

/// The value of the `--experimental-console-output-prefix` argument.
public var experimentalConsoleOutputPrefix: String?

/// The value(s) of the `--filter` argument.
public var filter: [String]?

Expand Down Expand Up @@ -341,6 +347,13 @@ func parseCommandLineArguments(from args: [String]) throws -> __CommandLineArgum
result.quiet = true
}

// Console output prefix
if let prefixIndex = args.firstIndex(of: "--experimental-console-output-prefix"), !isLastArgument(at: prefixIndex) {
result.experimentalConsoleOutputPrefix = args[args.index(after: prefixIndex)]
} else if let prefix = Environment.variable(named: "SWT_EXPERIMENTAL_CONSOLE_OUTPUT_PREFIX") {
result.experimentalConsoleOutputPrefix = prefix
}

// Filtering
func filterValues(forArgumentsWithLabel label: String) -> [String] {
args.indices.lazy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ extension Event {
}
}

/// A prefix to apply to all lines of text in the output.
///
/// If set, the value of this property is written _before_ any symbol or
/// library-supplied text.
public var prefix: String?

public init() {}
}

Expand Down Expand Up @@ -309,15 +315,16 @@ extension Event.ConsoleOutputRecorder {
@discardableResult public func record(_ event: borrowing Event, in context: borrowing Event.Context) -> Bool {
let messages = _humanReadableOutputRecorder.record(event, in: context, verbosity: options.verbosity)
for message in messages {
let prefix = options.prefix ?? ""
let symbol = message.symbol?.stringValue(options: options) ?? " "

if case .details = message.symbol, options.useANSIEscapeCodes, options.ansiColorBitDepth > 1 {
// Special-case the detail symbol to apply grey to the entire line of
// text instead of just the symbol.
write("\(_ansiEscapeCodePrefix)90m\(symbol) \(message.stringValue)\(_resetANSIEscapeCode)\n")
write("\(prefix)\(_ansiEscapeCodePrefix)90m\(symbol) \(message.stringValue)\(_resetANSIEscapeCode)\n")
} else {
let colorDots = context.test.map(\.tags).map { self.colorDots(for: $0) } ?? ""
write("\(symbol) \(colorDots)\(message.stringValue)\n")
write("\(prefix)\(symbol) \(colorDots)\(message.stringValue)\n")
}
}
return !messages.isEmpty
Expand All @@ -336,7 +343,8 @@ extension Event.ConsoleOutputRecorder {
///
/// The caller is responsible for presenting this message to the user.
static func warning(_ message: String, options: Event.ConsoleOutputRecorder.Options) -> String {
let prefix = options.prefix ?? ""
let symbol = Event.Symbol.warning.stringValue(options: options)
return "\(symbol) \(message)\n"
return "\(prefix)\(symbol) \(message)\n"
}
}
25 changes: 25 additions & 0 deletions Tests/TestingTests/EventRecorderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,31 @@ struct EventRecorderTests {
}
}

@Test("Output with prefix on each line")
func prefixedOutput() async throws {
let stream = Stream()
let prefix = ">>What Fools These Prefixes Be<<"

var options = Event.ConsoleOutputRecorder.Options()
options.prefix = prefix

var configuration = Configuration()
configuration.deliverExpectationCheckedEvents = true
let eventRecorder = Event.ConsoleOutputRecorder(options: options, writingUsing: stream.write)
configuration.eventHandler = { event, context in
eventRecorder.record(event, in: context)
}

await runTest(for: WrittenTests.self, configuration: configuration)

let buffer = stream.buffer.rawValue
#expect(buffer.contains(prefix))

if testsWithSignificantIOAreEnabled {
print(buffer, terminator: "")
}
}

#if !os(Windows)
@available(_regexAPI, *)
@Test(
Expand Down
18 changes: 18 additions & 0 deletions Tests/TestingTests/SwiftPMTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,24 @@ struct SwiftPMTests {
#expect(eventRecords.count == 4)
}
#endif
@Test("--experimental-console-output-prefix argument")
func experimentalConsoleOutputPrefixArgument() throws {
let prefix = ">>What light through yonder prefix breaks?<<"
let args = try parseCommandLineArguments(from: ["PATH", "--experimental-console-output-prefix", prefix])
#expect(args.experimentalConsoleOutputPrefix == prefix)
}

@Test("SWT_EXPERIMENTAL_CONSOLE_OUTPUT_PREFIX environment variable")
func experimentalConsoleOutputPrefixEnvironmentVariable() throws {
let prefix = ">>My horse, my horse, my prefix for a horse!<<"
let oldValue = Environment.variable(named: "SWT_EXPERIMENTAL_CONSOLE_OUTPUT_PREFIX")
Environment.setVariable(prefix, named: "SWT_EXPERIMENTAL_CONSOLE_OUTPUT_PREFIX")
defer {
Environment.setVariable(oldValue, named: "SWT_EXPERIMENTAL_CONSOLE_OUTPUT_PREFIX")
}
let args = try parseCommandLineArguments(from: ["PATH"])
#expect(args.experimentalConsoleOutputPrefix == prefix)
}
#endif

@Test("--repetitions argument (alone)")
Expand Down