diff --git a/Sources/SWBCore/Settings/BuiltinMacros.swift b/Sources/SWBCore/Settings/BuiltinMacros.swift index 2c5448b6..d0f5dbd5 100644 --- a/Sources/SWBCore/Settings/BuiltinMacros.swift +++ b/Sources/SWBCore/Settings/BuiltinMacros.swift @@ -726,7 +726,6 @@ public final class BuiltinMacros { public static let GENERATE_RESOURCE_ACCESSORS = BuiltinMacros.declareBooleanMacro("GENERATE_RESOURCE_ACCESSORS") public static let GENERATE_TEST_ENTRY_POINT = BuiltinMacros.declareBooleanMacro("GENERATE_TEST_ENTRY_POINT") public static let GENERATED_TEST_ENTRY_POINT_PATH = BuiltinMacros.declarePathMacro("GENERATED_TEST_ENTRY_POINT_PATH") - public static let GENERATED_TEST_ENTRY_POINT_INCLUDE_DISCOVERED_TESTS = BuiltinMacros.declareBooleanMacro("GENERATED_TEST_ENTRY_POINT_INCLUDE_DISCOVERED_TESTS") public static let GENERATE_TEXT_BASED_STUBS = BuiltinMacros.declareBooleanMacro("GENERATE_TEXT_BASED_STUBS") public static let GENERATE_INTERMEDIATE_TEXT_BASED_STUBS = BuiltinMacros.declareBooleanMacro("GENERATE_INTERMEDIATE_TEXT_BASED_STUBS") public static let GLOBAL_API_NOTES_PATH = BuiltinMacros.declareStringMacro("GLOBAL_API_NOTES_PATH") @@ -1793,7 +1792,6 @@ public final class BuiltinMacros { GENERATE_RESOURCE_ACCESSORS, GENERATE_TEST_ENTRY_POINT, GENERATED_TEST_ENTRY_POINT_PATH, - GENERATED_TEST_ENTRY_POINT_INCLUDE_DISCOVERED_TESTS, GENERATE_TEXT_BASED_STUBS, GENERATE_INTERMEDIATE_TEXT_BASED_STUBS, GID, diff --git a/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec b/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec index 647cdaea..e8211ed1 100644 --- a/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec @@ -335,9 +335,6 @@ PROVISIONING_PROFILE_SUPPORTED = YES; PROVISIONING_PROFILE_REQUIRED = NO; - - GENERATE_TEST_ENTRY_POINT = "$(GENERATE_TEST_ENTRYPOINTS_FOR_BUNDLES)"; - GENERATED_TEST_ENTRY_POINT_PATH = "$(DERIVED_SOURCES_DIR)/test_entry_point.swift"; }; PackageTypes = ( com.apple.package-type.bundle.unit-test @@ -356,7 +353,6 @@ ENABLE_TESTING_SEARCH_PATHS = YES; GENERATE_TEST_ENTRY_POINT = YES; GENERATED_TEST_ENTRY_POINT_PATH = "$(DERIVED_SOURCES_DIR)/test_entry_point.swift"; - GENERATED_TEST_ENTRY_POINT_INCLUDE_DISCOVERED_TESTS = YES; }; PackageTypes = ( com.apple.package-type.mach-o-executable diff --git a/Sources/SWBUniversalPlatform/TestEntryPointGenerationTaskAction.swift b/Sources/SWBUniversalPlatform/TestEntryPointGenerationTaskAction.swift index db59e7ac..9765719a 100644 --- a/Sources/SWBUniversalPlatform/TestEntryPointGenerationTaskAction.swift +++ b/Sources/SWBUniversalPlatform/TestEntryPointGenerationTaskAction.swift @@ -25,30 +25,24 @@ class TestEntryPointGenerationTaskAction: TaskAction { let options = try Options.parse(Array(task.commandLineAsStrings.dropFirst())) var tests: [IndexStore.TestCaseClass] = [] - if options.discoverTests { - var objects: [Path] = [] - for linkerFilelist in options.linkerFilelist { - let filelistContents = String(String(decoding: try executionDelegate.fs.read(linkerFilelist), as: UTF8.self)) - let entries = filelistContents.split(separator: "\n", omittingEmptySubsequences: true).map { Path($0) }.map { - for indexUnitBasePath in options.indexUnitBasePath { - if let remappedPath = generateIndexOutputPath(from: $0, basePath: indexUnitBasePath) { - return remappedPath - } + var objects: [Path] = [] + for linkerFilelist in options.linkerFilelist { + let filelistContents = String(String(decoding: try executionDelegate.fs.read(linkerFilelist), as: UTF8.self)) + let entries = filelistContents.split(separator: "\n", omittingEmptySubsequences: true).map { Path($0) }.map { + for indexUnitBasePath in options.indexUnitBasePath { + if let remappedPath = generateIndexOutputPath(from: $0, basePath: indexUnitBasePath) { + return remappedPath } - return $0 } - objects.append(contentsOf: entries) - } - guard let indexStoreLibraryPath = options.indexStoreLibraryPath else { - outputDelegate.emitError("Test discovery was requested, but failed to lookup index store library in toolchain") - return .failed - } - let indexStoreAPI = try IndexStoreAPI(dylib: indexStoreLibraryPath) - for indexStore in options.indexStore { - let store = try IndexStore.open(store: indexStore, api: indexStoreAPI) - let testInfo = try store.listTests(in: objects) - tests.append(contentsOf: testInfo) + return $0 } + objects.append(contentsOf: entries) + } + let indexStoreAPI = try IndexStoreAPI(dylib: options.indexStoreLibraryPath) + for indexStore in options.indexStore { + let store = try IndexStore.open(store: indexStore, api: indexStoreAPI) + let testInfo = try store.listTests(in: objects) + tests.append(contentsOf: testInfo) } try executionDelegate.fs.write(options.output, contents: ByteString(encodingAsUTF8: """ @@ -58,7 +52,7 @@ class TestEntryPointGenerationTaskAction: TaskAction { \(testObservationFragment) - public import XCTest + import XCTest \(discoveredTestsFragment(tests: tests)) @main @@ -100,7 +94,16 @@ class TestEntryPointGenerationTaskAction: TaskAction { } } #endif - \(xctestFragment(enableExperimentalTestOutput: options.enableExperimentalTestOutput, disable: !options.discoverTests)) + if testingLibrary == "xctest" { + #if !os(Windows) && \(options.enableExperimentalTestOutput) + _ = Self.testOutputPath().map { SwiftPMXCTestObserver(testOutputPath: testOutputPath) } + #endif + #if os(WASI) + await XCTMain(__allDiscoveredTests()) as Never + #else + XCTMain(__allDiscoveredTests()) as Never + #endif + } } #else static func main() async { @@ -110,7 +113,16 @@ class TestEntryPointGenerationTaskAction: TaskAction { await Testing.__swiftPMEntryPoint() as Never } #endif - \(xctestFragment(enableExperimentalTestOutput: options.enableExperimentalTestOutput, disable: !options.discoverTests)) + if testingLibrary == "xctest" { + #if !os(Windows) && \(options.enableExperimentalTestOutput) + _ = Self.testOutputPath().map { SwiftPMXCTestObserver(testOutputPath: testOutputPath) } + #endif + #if os(WASI) + await XCTMain(__allDiscoveredTests()) as Never + #else + XCTMain(__allDiscoveredTests()) as Never + #endif + } } #endif } @@ -125,18 +137,14 @@ class TestEntryPointGenerationTaskAction: TaskAction { private struct Options: ParsableArguments { @Option var output: Path - @Option var indexStoreLibraryPath: Path? = nil - @Option() var linkerFilelist: [Path] = [] - @Option var indexStore: [Path] = [] - @Option var indexUnitBasePath: [Path] = [] + @Option var indexStoreLibraryPath: Path + @Option var linkerFilelist: [Path] + @Option var indexStore: [Path] + @Option var indexUnitBasePath: [Path] @Flag var enableExperimentalTestOutput: Bool = false - @Flag var discoverTests: Bool = false } private func discoveredTestsFragment(tests: [IndexStore.TestCaseClass]) -> String { - guard !tests.isEmpty else { - return "" - } var fragment = "" for moduleName in Set(tests.map { $0.module }).sorted() { fragment += "@testable import \(moduleName)\n" @@ -166,29 +174,11 @@ class TestEntryPointGenerationTaskAction: TaskAction { return fragment } - private func xctestFragment(enableExperimentalTestOutput: Bool, disable: Bool) -> String { - guard !disable else { - return "" - } - return """ - if testingLibrary == "xctest" { - #if !os(Windows) && \(enableExperimentalTestOutput) - _ = Self.testOutputPath().map { SwiftPMXCTestObserver(testOutputPath: testOutputPath) } - #endif - #if os(WASI) - await XCTMain(__allDiscoveredTests()) as Never - #else - XCTMain(__allDiscoveredTests()) as Never - #endif - } - """ - } - private var testObservationFragment: String = """ #if !os(Windows) // Test observation is not supported on Windows - public import Foundation - public import XCTest + import Foundation + import XCTest public final class SwiftPMXCTestObserver: NSObject { let testOutputPath: String @@ -572,7 +562,7 @@ class TestEntryPointGenerationTaskAction: TaskAction { } } - public import XCTest + import XCTest #if canImport(Darwin) // XCTAttachment is unavailable in swift-corelibs-xctest. extension TestAttachment { diff --git a/Sources/SWBUniversalPlatform/TestEntryPointGenerationTool.swift b/Sources/SWBUniversalPlatform/TestEntryPointGenerationTool.swift index ec9dbfb7..e8e97f25 100644 --- a/Sources/SWBUniversalPlatform/TestEntryPointGenerationTool.swift +++ b/Sources/SWBUniversalPlatform/TestEntryPointGenerationTool.swift @@ -19,13 +19,9 @@ final class TestEntryPointGenerationToolSpec: GenericCommandLineToolSpec, SpecId override func commandLineFromTemplate(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, optionContext: (any DiscoveredCommandLineToolSpecInfo)?, specialArgs: [String] = [], lookup: ((MacroDeclaration) -> MacroExpression?)? = nil) async -> [CommandLineArgument] { var args = await super.commandLineFromTemplate(cbc, delegate, optionContext: optionContext, specialArgs: specialArgs, lookup: lookup) - if cbc.scope.evaluate(BuiltinMacros.GENERATED_TEST_ENTRY_POINT_INCLUDE_DISCOVERED_TESTS) { - args.append("--discover-tests") - for toolchainLibrarySearchPath in cbc.producer.toolchains.map({ $0.librarySearchPaths }) { - if let path = toolchainLibrarySearchPath.findLibrary(operatingSystem: cbc.producer.hostOperatingSystem, basename: "IndexStore") { - args.append(contentsOf: ["--index-store-library-path", .path(path)]) - break - } + for (toolchainPath, toolchainLibrarySearchPath) in cbc.producer.toolchains.map({ ($0.path, $0.librarySearchPaths) }) { + if let path = toolchainLibrarySearchPath.findLibrary(operatingSystem: cbc.producer.hostOperatingSystem, basename: "IndexStore") { + args.append(contentsOf: ["--index-store-library-path", .path(path)]) } for input in cbc.inputs { if input.fileType.conformsTo(identifier: "text") { @@ -47,14 +43,12 @@ final class TestEntryPointGenerationToolSpec: GenericCommandLineToolSpec, SpecId public func constructTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, indexStorePaths: [Path], indexUnitBasePaths: [Path]) async { var commandLine = await commandLineFromTemplate(cbc, delegate, optionContext: nil) - if cbc.scope.evaluate(BuiltinMacros.GENERATED_TEST_ENTRY_POINT_INCLUDE_DISCOVERED_TESTS) { - for indexStorePath in indexStorePaths { - commandLine.append(contentsOf: ["--index-store", .path(indexStorePath)]) - } - - for basePath in indexUnitBasePaths { - commandLine.append(contentsOf: ["--index-unit-base-path", .path(basePath)]) - } + for indexStorePath in indexStorePaths { + commandLine.append(contentsOf: ["--index-store", .path(indexStorePath)]) + } + + for basePath in indexUnitBasePaths { + commandLine.append(contentsOf: ["--index-unit-base-path", .path(basePath)]) } delegate.createTask( diff --git a/Tests/SWBBuildSystemTests/BuildOperationTests.swift b/Tests/SWBBuildSystemTests/BuildOperationTests.swift index 8bac3097..cf9ebad8 100644 --- a/Tests/SWBBuildSystemTests/BuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/BuildOperationTests.swift @@ -382,76 +382,6 @@ fileprivate struct BuildOperationTests: CoreBasedTests { } } - @Test(.requireSDKs(.macOS)) - func unitTestWithGeneratedEntryPointViaMacOSOverride() async throws { - try await withTemporaryDirectory(removeTreeOnDeinit: false) { (tmpDir: Path) in - let testProject = try await TestProject( - "TestProject", - sourceRoot: tmpDir, - groupTree: TestGroup( - "SomeFiles", - children: [ - TestFile("test.swift"), - ]), - buildConfigurations: [ - TestBuildConfiguration("Debug", buildSettings: [ - "ARCHS": "$(ARCHS_STANDARD)", - "CODE_SIGNING_ALLOWED": "NO", - "PRODUCT_NAME": "$(TARGET_NAME)", - "SDKROOT": "$(HOST_PLATFORM)", - "SUPPORTED_PLATFORMS": "$(HOST_PLATFORM)", - "SWIFT_VERSION": swiftVersion, - "INDEX_DATA_STORE_DIR": "\(tmpDir.join("index").str)", - "LINKER_DRIVER": "swiftc" - ]) - ], - targets: [ - TestStandardTarget( - "MyTests", - type: .unitTest, - buildConfigurations: [ - TestBuildConfiguration("Debug", buildSettings: [ - "GENERATE_TEST_ENTRYPOINTS_FOR_BUNDLES": "YES" - ]) - ], - buildPhases: [ - TestSourcesBuildPhase(["test.swift"]), - ], - ), - ]) - let core = try await getCore() - let tester = try await BuildOperationTester(core, testProject, simulated: false) - try localFS.createDirectory(tmpDir.join("index")) - let projectDir = tester.workspace.projects[0].sourceRoot - - try await tester.fs.writeFileContents(projectDir.join("test.swift")) { stream in - stream <<< """ - import Testing - import XCTest - @Suite struct MySuite { - @Test func myTest() { - #expect(42 == 42) - } - } - - final class MYXCTests: XCTestCase { - func testFoo() { - XCTAssertTrue(true) - } - } - """ - } - - let destination: RunDestinationInfo = .host - try await tester.checkBuild(runDestination: destination, persistent: true) { results in - results.checkNoErrors() - results.checkTask(.matchRuleType("GenerateTestEntryPoint")) { task in - task.checkCommandLineMatches(["builtin-generateTestEntryPoint", "--output", .suffix("test_entry_point.swift")]) - } - } - } - } - @Test(.requireSDKs(.host), .skipHostOS(.macOS), .skipHostOS(.windows, "cannot find testing library")) func unitTestWithGeneratedEntryPoint() async throws { try await withTemporaryDirectory(removeTreeOnDeinit: false) { (tmpDir: Path) in diff --git a/Tests/SWBTaskConstructionTests/UnitTestTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/UnitTestTaskConstructionTests.swift index cd27640e..36c60d39 100644 --- a/Tests/SWBTaskConstructionTests/UnitTestTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/UnitTestTaskConstructionTests.swift @@ -366,7 +366,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { await tester.checkBuild(runDestination: .linux, fs: fs) { results in results.checkTarget("UnitTestRunner") { target in results.checkTask(.matchTarget(target), .matchRuleType("GenerateTestEntryPoint")) { task in - task.checkCommandLineMatches([.suffix("builtin-generateTestEntryPoint"), "--output", .suffix("test_entry_point.swift"), "--discover-tests", "--index-store-library-path", .suffix("libIndexStore.so"), "--linker-filelist", .suffix("UnitTestTarget.LinkFileList"), "--index-store", "/index", "--index-unit-base-path", "/tmp/Test/aProject/build"]) + task.checkCommandLineMatches([.suffix("builtin-generateTestEntryPoint"), "--output", .suffix("test_entry_point.swift"), "--index-store-library-path", .suffix("libIndexStore.so"), "--linker-filelist", .suffix("UnitTestTarget.LinkFileList"), "--index-store", "/index", "--index-unit-base-path", "/tmp/Test/aProject/build"]) task.checkInputs([ .pathPattern(.suffix("UnitTestTarget.LinkFileList")), .pathPattern(.suffix("UnitTestTarget.so")),