From 3dd057ee041530ec5a6450e11e3ea2f1768a3710 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Wed, 12 Jun 2024 13:58:04 -0400 Subject: [PATCH 1/3] Ignore the `--testing-library` argument we are going to start passing from SwiftPM. This PR adds functionality to XCTest's argument parser that allows it to skip arguments that the caller may specify but which are uninteresting to XCTest. Specifically, we are planning to start passing `--testing-library xctest` to the test runner process in order to disambiguate runs of XCTest from runs of Swift Testing, and we need to make sure this does not cause XCTest to run incorrectly. Resolves rdar://129695171. --- Sources/XCTest/Private/ArgumentParser.swift | 32 ++++++++++++++++++- .../ArgumentParserWithIgnoredArgs/main.swift | 22 +++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 Tests/Functional/ArgumentParserWithIgnoredArgs/main.swift diff --git a/Sources/XCTest/Private/ArgumentParser.swift b/Sources/XCTest/Private/ArgumentParser.swift index d30f86fbf..c4af7d1f8 100644 --- a/Sources/XCTest/Private/ArgumentParser.swift +++ b/Sources/XCTest/Private/ArgumentParser.swift @@ -50,8 +50,38 @@ internal struct ArgumentParser { private let arguments: [String] + /// Filter out arguments from an arguments array that XCTest doesn't care about. + /// + /// - Parameters: + /// - arguments: The arguments array to filter. + /// + /// - Returns: A copy of `arguments` with ignored arguments removed. + private static func removeIgnoredArguments(from arguments: [String]) -> [String] { + var result = [String]() + result.reserveCapacity(arguments.count) + + for i in arguments.indices { + let argument = arguments[i] + + // Filter out any arguments of the form "--testing-library=xctest". + if argument.starts(with: "--testing-library=") { + continue + } + + // Next, filter out any split arguments ("--testing-library xctest") + if argument == "--testing-library" { + i = arguments.index(after: i) + continue + } + + result.append(argument) + } + + return result + } + init(arguments: [String]) { - self.arguments = arguments + self.arguments = Self.removeIgnoredArguments(from: arguments) } var executionMode: ExecutionMode { diff --git a/Tests/Functional/ArgumentParserWithIgnoredArgs/main.swift b/Tests/Functional/ArgumentParserWithIgnoredArgs/main.swift new file mode 100644 index 000000000..b2408a580 --- /dev/null +++ b/Tests/Functional/ArgumentParserWithIgnoredArgs/main.swift @@ -0,0 +1,22 @@ +// RUN: %{swiftc} %s -o %T/ArgumentParserWithIgnoredArgs +// RUN: %T/ArgumentParserWithIgnoredArgs + +#if os(macOS) + import SwiftXCTest +#else + import XCTest +#endif + +class ArgumentParsingWithIgnoredArgsTestCase: XCTestCase { + static var allTests = { + return [ + ("testFail", testFail), + ("testSuccess", testSuccess), + ] + }() + func testFail() { XCTFail("failure") } + func testSuccess() { } +} + +let arguments = ["main", "--testing-library=xctest", "--testing-library", "xctest", "\(String(reflecting: ArgumentParsingTestCase.self))/testSuccess", "--testing-library",] +XCTMain([testCase(ArgumentParsingTestCase.allTests)], arguments: arguments) From 27dbb6bb106a698b3934c7c29c665d32c67c3c72 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Wed, 12 Jun 2024 16:22:56 -0400 Subject: [PATCH 2/3] That's not how you advance an iterator --- Sources/XCTest/Private/ArgumentParser.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Sources/XCTest/Private/ArgumentParser.swift b/Sources/XCTest/Private/ArgumentParser.swift index c4af7d1f8..a1a348c96 100644 --- a/Sources/XCTest/Private/ArgumentParser.swift +++ b/Sources/XCTest/Private/ArgumentParser.swift @@ -60,9 +60,8 @@ internal struct ArgumentParser { var result = [String]() result.reserveCapacity(arguments.count) - for i in arguments.indices { - let argument = arguments[i] - + var iterator = arguments.makeIterator() + while let argument = iterator.next() { // Filter out any arguments of the form "--testing-library=xctest". if argument.starts(with: "--testing-library=") { continue @@ -70,7 +69,7 @@ internal struct ArgumentParser { // Next, filter out any split arguments ("--testing-library xctest") if argument == "--testing-library" { - i = arguments.index(after: i) + _ = iterator.next() // skip subsequent value continue } From 6ad0502d9e66e6d7012becbe09f391baf9b95fa2 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Wed, 12 Jun 2024 19:24:35 -0400 Subject: [PATCH 3/3] Fix misspecified test --- Tests/Functional/ArgumentParserWithIgnoredArgs/main.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Functional/ArgumentParserWithIgnoredArgs/main.swift b/Tests/Functional/ArgumentParserWithIgnoredArgs/main.swift index b2408a580..8c0fbfe74 100644 --- a/Tests/Functional/ArgumentParserWithIgnoredArgs/main.swift +++ b/Tests/Functional/ArgumentParserWithIgnoredArgs/main.swift @@ -18,5 +18,5 @@ class ArgumentParsingWithIgnoredArgsTestCase: XCTestCase { func testSuccess() { } } -let arguments = ["main", "--testing-library=xctest", "--testing-library", "xctest", "\(String(reflecting: ArgumentParsingTestCase.self))/testSuccess", "--testing-library",] -XCTMain([testCase(ArgumentParsingTestCase.allTests)], arguments: arguments) +let arguments = ["main", "--testing-library=xctest", "--testing-library", "xctest", "\(String(reflecting: ArgumentParsingWithIgnoredArgsTestCase.self))/testSuccess", "--testing-library",] +XCTMain([testCase(ArgumentParsingWithIgnoredArgsTestCase.allTests)], arguments: arguments)