Skip to content

Commit 1901502

Browse files
authored
Factor out bug report URL boilerplate into a utility function (#1635)
1 parent f38f79c commit 1901502

19 files changed

Lines changed: 82 additions & 18 deletions

Sources/Overlays/_Testing_Foundation/Attachments/_AttachableURLWrapper.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public struct _AttachableURLWrapper: Sendable {
5353
/// thrown if a file descriptor to `url` or `copyURL` cannot be created.
5454
init(url: URL, copiedToFileAt copyURL: URL? = nil, isCompressedDirectory: Bool) throws {
5555
if isCompressedDirectory && copyURL == nil {
56-
preconditionFailure("When attaching a directory to a test, the URL to its compressed copy must be supplied. Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new")
56+
preconditionFailure("When attaching a directory to a test, the URL to its compressed copy must be supplied. \(fileABugMessage)")
5757
}
5858
self.url = url
5959
self.data = try Data(contentsOf: copyURL ?? url, options: [.mappedIfSafe])

Sources/Testing/ABI/Encoded/ABI.EncodedTest.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ extension ABI {
135135

136136
init(encoding testCase: borrowing Test.Case) {
137137
guard let arguments = testCase.arguments else {
138-
preconditionFailure("Attempted to initialize an EncodedTestCase encoding a test case which is not parameterized: \(testCase). Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new")
138+
preconditionFailure("Attempted to initialize an EncodedTestCase encoding a test case which is not parameterized: \(testCase). \(fileABugMessage)")
139139
}
140140

141141
// TODO: define an encodable form of Test.Case.ID

Sources/Testing/Attachments/Attachment.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ extension Configuration {
584584
}
585585

586586
guard case let .valueAttached(attachment) = event.kind else {
587-
preconditionFailure("Passed the wrong kind of event to \(#function) (expected valueAttached, got \(event.kind)). Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new")
587+
preconditionFailure("Passed the wrong kind of event to \(#function) (expected valueAttached, got \(event.kind)). \(fileABugMessage)")
588588
}
589589
if attachment.fileSystemPath != nil {
590590
// Somebody already saved this attachment. This isn't necessarily a logic

Sources/Testing/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ add_library(Testing
9191
Support/Additions/TaskAdditions.swift
9292
Support/Additions/WinSDKAdditions.swift
9393
Support/Allocated.swift
94+
Support/BugReporting.swift
9495
Support/CartesianProduct.swift
9596
Support/CError.swift
9697
Support/CustomIssueRepresentable.swift

Sources/Testing/ExitTests/ExitTest.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ extension ExitTest {
294294

295295
// Set ExitTest.current before the test body runs.
296296
Self._current.withLock { current in
297-
precondition(current == nil, "Set the current exit test twice in the same process. Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new")
297+
precondition(current == nil, "Set the current exit test twice in the same process. \(fileABugMessage)")
298298
current = self.unsafeCopy()
299299
}
300300

@@ -1096,7 +1096,7 @@ extension ExitTest {
10961096
}
10971097
let capturedValuesJSON = try fileHandle.readToEnd()
10981098
let capturedValuesJSONLines = capturedValuesJSON.split(whereSeparator: \.isASCIINewline)
1099-
assert(capturedValues.count == capturedValuesJSONLines.count, "Expected to decode \(capturedValues.count) captured value(s) for the current exit test, but received \(capturedValuesJSONLines.count). Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new")
1099+
assert(capturedValues.count == capturedValuesJSONLines.count, "Expected to decode \(capturedValues.count) captured value(s) for the current exit test, but received \(capturedValuesJSONLines.count). \(fileABugMessage)")
11001100

11011101
// Walk the list of captured values' types, map them to their JSON blobs,
11021102
// and decode them.

Sources/Testing/ExitTests/SpawnProcess.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func spawnExecutable(
129129
func inherit(_ fileHandle: borrowing FileHandle, as standardFD: CInt? = nil) throws {
130130
try fileHandle.withUnsafePOSIXFileDescriptor { fd in
131131
guard let fd else {
132-
throw SystemError(description: "A child process cannot inherit a file handle without an associated file descriptor. Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new")
132+
throw SystemError(description: "A child process cannot inherit a file handle without an associated file descriptor. \(fileABugMessage)")
133133
}
134134
if let standardFD, standardFD != fd {
135135
_ = posix_spawn_file_actions_adddup2(fileActions, fd, standardFD)
@@ -241,7 +241,7 @@ func spawnExecutable(
241241
func inherit(_ fileHandle: borrowing FileHandle) throws -> HANDLE? {
242242
try fileHandle.withUnsafeWindowsHANDLE { windowsHANDLE in
243243
guard let windowsHANDLE else {
244-
throw SystemError(description: "A child process cannot inherit a file handle without an associated Windows handle. Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new")
244+
throw SystemError(description: "A child process cannot inherit a file handle without an associated Windows handle. \(fileABugMessage)")
245245
}
246246

247247
// Ensure the file handle can be inherited by the child process.

Sources/Testing/ExitTests/WaitFor.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ private func _blockAndWait(for pid: consuming pid_t) throws -> ExitStatus {
3333
case .init(CLD_KILLED), .init(CLD_DUMPED):
3434
return .signal(siginfo.si_status)
3535
default:
36-
throw SystemError(description: "Unexpected siginfo_t value. Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new and include this information: \(String(reflecting: siginfo))")
36+
throw SystemError(description: "Unexpected siginfo_t value. \(fileABugMessage(context: String(reflecting: siginfo)))")
3737
}
3838
} else if case let errorCode = swt_errno(), errorCode != EINTR {
3939
throw CError(rawValue: errorCode)
@@ -247,7 +247,7 @@ func wait(for pid: consuming pid_t) async throws -> ExitStatus {
247247
// we add this continuation to the dictionary, then it will simply loop
248248
// and report the status again.
249249
let oldContinuation = childProcessContinuations.updateValue(continuation, forKey: pid)
250-
assert(oldContinuation == nil, "Unexpected continuation found for PID \(pid). Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new")
250+
assert(oldContinuation == nil, "Unexpected continuation found for PID \(pid). \(fileABugMessage)")
251251

252252
// Wake up the waiter thread if it is waiting for more child processes.
253253
_ = pthread_cond_signal(_waitThreadNoChildrenCondition)

Sources/Testing/Support/Additions/TaskAdditions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func decorateTaskName(_ taskName: String?, withAction action: String?) -> String
1919
let prefix = "[Swift Testing]"
2020
return taskName.map { taskName in
2121
#if DEBUG
22-
precondition(!taskName.hasPrefix(prefix), "Applied prefix '\(prefix)' to task name '\(taskName)' twice. Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new")
22+
precondition(!taskName.hasPrefix(prefix), "Applied prefix '\(prefix)' to task name '\(taskName)' twice. \(fileABugMessage)")
2323
#endif
2424
let action = action.map { " - \($0)" } ?? ""
2525
return "\(prefix) \(taskName)\(action)"

Sources/Testing/Support/Additions/WinSDKAdditions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ let STATUS_SIGNAL_CAUGHT_BITS = {
4444
#if DEBUG
4545
assert(
4646
(result & STATUS_CODE_MASK) == 0,
47-
"Constructed NTSTATUS mask \(String(result, radix: 16)) encroached on code bits. Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new"
47+
"Constructed NTSTATUS mask \(String(result, radix: 16)) encroached on code bits. \(fileABugMessage)"
4848
)
4949
#endif
5050

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//
2+
// This source file is part of the Swift.org open source project
3+
//
4+
// Copyright (c) 2026 Apple Inc. and the Swift project authors
5+
// Licensed under Apache License v2.0 with Runtime Library Exception
6+
//
7+
// See https://swift.org/LICENSE.txt for license information
8+
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
//
10+
11+
/// A standardized message inviting a user to file a bug report at the provided
12+
/// URL.
13+
package var fileABugMessage: String {
14+
_fileABugMessage(context: "")
15+
}
16+
17+
/// A standardized message inviting a user to file a bug report at the provided
18+
/// URL and include the specified contextual information.
19+
///
20+
/// - Parameters:
21+
/// - context: Additional diagnostic information to include with the bug
22+
/// report message.
23+
///
24+
/// - Returns: A string combining a standard request to file a bug report (with
25+
/// a URL provided) and `context`.
26+
package func fileABugMessage(context: String) -> String {
27+
_fileABugMessage(context: context)
28+
}
29+
30+
/// Construct a message inviting a user to file a bug report with some optional
31+
/// context to provide.
32+
///
33+
/// - Parameters:
34+
/// - context: Optional additional diagnostic information to include with the
35+
/// bug report message.
36+
///
37+
/// - Returns: A string combining a standard request to file a bug report (with
38+
/// a URL provided) and `context`, if provided.
39+
///
40+
/// This common implementation function is provided because calling
41+
/// `fileABugMessage(context:)` directly from the `fileABugMessage` property
42+
/// getter isn't supported since they have the same base name.
43+
private func _fileABugMessage(context: String?) -> String {
44+
var result = "Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new"
45+
if let context {
46+
result += " and include this information: \(context)"
47+
}
48+
return result
49+
}

0 commit comments

Comments
 (0)