diff --git a/Sources/Testing/Running/Configuration.swift b/Sources/Testing/Running/Configuration.swift index 786856e10..be9101d24 100644 --- a/Sources/Testing/Running/Configuration.swift +++ b/Sources/Testing/Running/Configuration.swift @@ -75,11 +75,10 @@ public struct Configuration: Sendable { /// The maximum number of times the test run should iterate. /// - /// - Precondition: The value of this property must be greater than or equal - /// to `1`. + /// - Precondition: The value of this property must be greater than `0`. public var maximumIterationCount: Int { willSet { - precondition(newValue >= 1, "Test runs must iterate at least once.") + precondition(newValue > 0, "Test runs must iterate at least once (maximumIterationCount was \(newValue)).") } } diff --git a/Sources/Testing/SourceAttribution/SourceLocation.swift b/Sources/Testing/SourceAttribution/SourceLocation.swift index 788163898..bbf3cf3a6 100644 --- a/Sources/Testing/SourceAttribution/SourceLocation.swift +++ b/Sources/Testing/SourceAttribution/SourceLocation.swift @@ -12,14 +12,19 @@ public struct SourceLocation: Sendable { /// The file ID of the source file. /// + /// - Precondition: The value of this property must not be empty and must be + /// formatted as described in the documentation for the + /// [`#fileID`](https://developer.apple.com/documentation/swift/fileID()). + /// macro in the Swift standard library. + /// /// ## See Also /// /// - ``moduleName`` /// - ``fileName`` public var fileID: String { - didSet { - precondition(!fileID.isEmpty) - precondition(fileID.contains("/")) + willSet { + precondition(!newValue.isEmpty, "SourceLocation.fileID must not be empty (was \(newValue))") + precondition(newValue.contains("/"), "SourceLocation.fileID must be a well-formed file ID (was \(newValue))") } } @@ -74,20 +79,45 @@ public struct SourceLocation: Sendable { public var _filePath: String /// The line in the source file. + /// + /// - Precondition: The value of this property must be greater than `0`. public var line: Int { - didSet { - precondition(line > 0) + willSet { + precondition(newValue > 0, "SourceLocation.line must be greater than 0 (was \(newValue))") } } /// The column in the source file. + /// + /// - Precondition: The value of this property must be greater than `0`. public var column: Int { - didSet { - precondition(column > 0) + willSet { + precondition(newValue > 0, "SourceLocation.column must be greater than 0 (was \(newValue))") } } + /// Initialize an instance of this type with the specified location details. + /// + /// - Parameters: + /// - fileID: The file ID of the source file, using the format described in + /// the documentation for the + /// [`#fileID`](https://developer.apple.com/documentation/swift/fileID()) + /// macro in the Swift standard library. + /// - filePath: The path to the source file. + /// - line: The line in the source file. Must be greater than `0`. + /// - column: The column in the source file. Must be greater than `0`. + /// + /// - Precondition: `fileID` must not be empty and must be formatted as + /// described in the documentation for + /// [`#fileID`](https://developer.apple.com/documentation/swift/fileID()). + /// - Precondition: `line` must be greater than `0`. + /// - Precondition: `column` must be greater than `0`. public init(fileID: String, filePath: String, line: Int, column: Int) { + precondition(!fileID.isEmpty, "SourceLocation.fileID must not be empty (was \(fileID))") + precondition(fileID.contains("/"), "SourceLocation.fileID must be a well-formed file ID (was \(fileID))") + precondition(line > 0, "SourceLocation.line must be greater than 0 (was \(line))") + precondition(column > 0, "SourceLocation.column must be greater than 0 (was \(column))") + self.fileID = fileID self._filePath = filePath self.line = line diff --git a/Tests/TestingTests/IssueTests.swift b/Tests/TestingTests/IssueTests.swift index 00f0f8c93..53fe92b84 100644 --- a/Tests/TestingTests/IssueTests.swift +++ b/Tests/TestingTests/IssueTests.swift @@ -1489,8 +1489,8 @@ struct IssueCodingTests { @Test func sourceLocationPropertyGetter() throws { let sourceLocation = SourceLocation( - fileID: "fileID", - filePath: "filePath", + fileID: "M/file.swift", + filePath: "M/file.swift", line: 13, column: 42 ) @@ -1509,8 +1509,8 @@ struct IssueCodingTests { @Test func sourceLocationPropertySetter() throws { let initialSourceLocation = SourceLocation( - fileID: "fileID", - filePath: "filePath", + fileID: "M/file.swift", + filePath: "file.swift", line: 13, column: 42 ) @@ -1523,8 +1523,8 @@ struct IssueCodingTests { let issue = Issue(kind: .apiMisused, sourceContext: sourceContext) let updatedSourceLocation = SourceLocation( - fileID: "fileID2", - filePath: "filePath2", + fileID: "M/file2.swift", + filePath: "file2.swift", line: 14, column: 43 ) diff --git a/Tests/TestingTests/SourceLocationTests.swift b/Tests/TestingTests/SourceLocationTests.swift index 4fde7e829..a6a22c3b4 100644 --- a/Tests/TestingTests/SourceLocationTests.swift +++ b/Tests/TestingTests/SourceLocationTests.swift @@ -51,21 +51,6 @@ struct SourceLocationTests { #expect(sourceLocation.fileName == "D.swift") } - -#if !SWT_NO_EXIT_TESTS - @Test("SourceLocation.fileID property must be well-formed") - func sourceLocationFileIDWellFormed() async { - await #expect(exitsWith: .failure) { - var sourceLocation = #_sourceLocation - sourceLocation.fileID = "" - } - await #expect(exitsWith: .failure) { - var sourceLocation = #_sourceLocation - sourceLocation.fileID = "ABC" - } - } -#endif - @Test("SourceLocation.line and .column properties") func sourceLocationLineAndColumn() { var sourceLocation = #_sourceLocation @@ -81,6 +66,34 @@ struct SourceLocationTests { } #if !SWT_NO_EXIT_TESTS + @Test("SourceLocation.init requires well-formed arguments") + func sourceLocationInitPreconditions() async { + await #expect(exitsWith: .failure, "Empty fileID") { + _ = SourceLocation(fileID: "", filePath: "", line: 1, column: 1) + } + await #expect(exitsWith: .failure, "Invalid fileID") { + _ = SourceLocation(fileID: "B.swift", filePath: "", line: 1, column: 1) + } + await #expect(exitsWith: .failure, "Zero line") { + _ = SourceLocation(fileID: "A/B.swift", filePath: "", line: 0, column: 1) + } + await #expect(exitsWith: .failure, "Zero column") { + _ = SourceLocation(fileID: "A/B.swift", filePath: "", line: 1, column: 0) + } + } + + @Test("SourceLocation.fileID property must be well-formed") + func sourceLocationFileIDWellFormed() async { + await #expect(exitsWith: .failure) { + var sourceLocation = #_sourceLocation + sourceLocation.fileID = "" + } + await #expect(exitsWith: .failure) { + var sourceLocation = #_sourceLocation + sourceLocation.fileID = "ABC" + } + } + @Test("SourceLocation.line and column properties must be positive") func sourceLocationLineAndColumnPositive() async { await #expect(exitsWith: .failure) {