From db786ca14a39d396a11df1d7524a6bc5fff0da25 Mon Sep 17 00:00:00 2001 From: Sam Khouri Date: Mon, 11 Aug 2025 18:18:47 -0400 Subject: [PATCH] Test: Migrate CFamilyTargetTests to Swift Testing and augment Migrate the `CFamilyTargetTests` test to Swift Testing and augment the test to run against both the Native and SwiftBUild build system, in addition to the `debug` and `release` build configuration. Depends on: #9013 Relates to: #8997 issue: rdar://157669245 --- .../SwiftTesting+TraitsBug.swift | 8 + .../FunctionalTests/CFamilyTargetTests.swift | 271 ++++++++++++++---- 2 files changed, 218 insertions(+), 61 deletions(-) diff --git a/Sources/_InternalTestSupport/SwiftTesting+TraitsBug.swift b/Sources/_InternalTestSupport/SwiftTesting+TraitsBug.swift index f2fa5605c64..99de658066a 100644 --- a/Sources/_InternalTestSupport/SwiftTesting+TraitsBug.swift +++ b/Sources/_InternalTestSupport/SwiftTesting+TraitsBug.swift @@ -54,6 +54,14 @@ extension Trait where Self == Testing.Bug { ) } + public static var IssueWindowsCannotSaveAttachment: Self { + // error: unable to write file 'C:\Users\ContainerAdministrator\AppData\Local\Temp\CFamilyTargets_CDynamicLookup.hNxGHC\CFamilyTargets_CDynamicLookup\.build\x86_64-unknown-windows-msvc\Intermediates.noindex\CDynamicLookup.build\Release-windows\CDynamicLookup.build\Objects-normal\x86_64\CDynamicLookup.LinkFileList': No such file or directory (2) + .issue( + "https://github.com/swiftlang/swift-foundation/issues/1486", + relationship: .defect, + ) + } + public static var IssueProductTypeForObjectLibraries: Self { .issue( "https://github.com/swiftlang/swift-build/issues/609", diff --git a/Tests/FunctionalTests/CFamilyTargetTests.swift b/Tests/FunctionalTests/CFamilyTargetTests.swift index a3f9d15d223..0a218b9b2fc 100644 --- a/Tests/FunctionalTests/CFamilyTargetTests.swift +++ b/Tests/FunctionalTests/CFamilyTargetTests.swift @@ -2,13 +2,14 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors +// Copyright (c) 2014-2025 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation import Basics import Commands @@ -18,98 +19,246 @@ import PackageModel import SourceControl import _InternalTestSupport import Workspace -import XCTest +import Testing import class Basics.AsyncProcess -/// Asserts if a directory (recursively) contains a file. -private func XCTAssertDirectoryContainsFile(dir: AbsolutePath, filename: String, file: StaticString = #file, line: UInt = #line) { +/// Expects a directory (recursively) contains a file. +fileprivate func expectDirectoryContainsFile( + dir: AbsolutePath, + filename: String, + sourceLocation: SourceLocation = #_sourceLocation, +) { do { for entry in try walk(dir) { if entry.basename == filename { return } } } catch { - XCTFail("Failed with error \(error)", file: file, line: line) + Issue.record("Failed with error \(error)", sourceLocation: sourceLocation) } - XCTFail("Directory \(dir) does not contain \(file)", file: file, line: line) + Issue.record("Directory \(dir) does not contain \(filename)", sourceLocation: sourceLocation) } -final class CFamilyTargetTestCase: XCTestCase { - func testCLibraryWithSpaces() async throws { - try await fixtureXCTest(name: "CFamilyTargets/CLibraryWithSpaces") { fixturePath in - await XCTAssertBuilds(fixturePath, buildSystem: .native) - let debugPath = fixturePath.appending(components: ".build", try UserToolchain.default.targetTriple.platformBuildPathComponent, "debug") - XCTAssertDirectoryContainsFile(dir: debugPath, filename: "Bar.c.o") - XCTAssertDirectoryContainsFile(dir: debugPath, filename: "Foo.c.o") +@Suite( + .tags( + .TestSize.large, + ), +) +struct CFamilyTargetTestCase { + @Test( + .issue("https://github.com/swiftlang/swift-build/issues/333", relationship: .defect), + .tags( + .Feature.Command.Build, + ), + arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), + ) + func cLibraryWithSpaces( + data: BuildData, + ) async throws { + try await withKnownIssue(isIntermittent: true) { + try await fixture(name: "CFamilyTargets/CLibraryWithSpaces") { fixturePath in + try await executeSwiftBuild( + fixturePath, + configuration: data.config, + buildSystem: data.buildSystem, + ) + if data.buildSystem == .native { + let binPath = try fixturePath.appending(components: data.buildSystem.binPath(for: data.config)) + expectDirectoryContainsFile(dir: binPath, filename: "Bar.c.o") + expectDirectoryContainsFile(dir: binPath, filename: "Foo.c.o") + } + } + } when: { + data.buildSystem == .swiftbuild } } - func testCUsingCAndSwiftDep() async throws { - try await fixtureXCTest(name: "DependencyResolution/External/CUsingCDep") { fixturePath in - let packageRoot = fixturePath.appending("Bar") - await XCTAssertBuilds(packageRoot, buildSystem: .native) - let debugPath = fixturePath.appending(components: "Bar", ".build", try UserToolchain.default.targetTriple.platformBuildPathComponent, "debug") - XCTAssertDirectoryContainsFile(dir: debugPath, filename: "Sea.c.o") - XCTAssertDirectoryContainsFile(dir: debugPath, filename: "Foo.c.o") - let path = try SwiftPM.packagePath(for: "Foo", packageRoot: packageRoot) - XCTAssertEqual(try GitRepository(path: path).getTags(), ["1.2.3"]) + @Test( + .tags( + .Feature.Command.Build, + ), + .IssueWindowsLongPath, + .IssueWindowsPathLastConponent, + .IssueWindowsRelativePathAssert, + .IssueWindowsCannotSaveAttachment, + arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), + ) + func cUsingCAndSwiftDep( + data: BuildData, + ) async throws { + try await withKnownIssue(isIntermittent: true) { + try await fixture(name: "DependencyResolution/External/CUsingCDep") { fixturePath in + let packageRoot = fixturePath.appending("Bar") + try await executeSwiftBuild( + packageRoot, + configuration: data.config, + buildSystem: data.buildSystem, + ) + if data.buildSystem == .native { + let binPath = try packageRoot.appending(components: data.buildSystem.binPath(for: data.config)) + expectDirectoryContainsFile(dir: binPath, filename: "Sea.c.o") + expectDirectoryContainsFile(dir: binPath, filename: "Foo.c.o") + } + let path = try SwiftPM.packagePath(for: "Foo", packageRoot: packageRoot) + let actualTags = try GitRepository(path: path).getTags() + #expect(actualTags == ["1.2.3"]) + } + } when: { + ProcessInfo.hostOperatingSystem == .windows && data.buildSystem == .swiftbuild } } - func testModuleMapGenerationCases() async throws { - try await fixtureXCTest(name: "CFamilyTargets/ModuleMapGenerationCases") { fixturePath in - await XCTAssertBuilds(fixturePath, buildSystem: .native) - let debugPath = fixturePath.appending(components: ".build", try UserToolchain.default.targetTriple.platformBuildPathComponent, "debug") - XCTAssertDirectoryContainsFile(dir: debugPath, filename: "Jaz.c.o") - XCTAssertDirectoryContainsFile(dir: debugPath, filename: "main.swift.o") - XCTAssertDirectoryContainsFile(dir: debugPath, filename: "FlatInclude.c.o") - XCTAssertDirectoryContainsFile(dir: debugPath, filename: "UmbrellaHeader.c.o") + @Test( + .tags( + .Feature.Command.Build, + ), + .IssueWindowsLongPath, + .IssueWindowsPathLastConponent, + .IssueWindowsRelativePathAssert, + .IssueWindowsCannotSaveAttachment, + arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), + ) + func moduleMapGenerationCases( + data: BuildData, + ) async throws { + try await withKnownIssue(isIntermittent: true) { + try await fixture(name: "CFamilyTargets/ModuleMapGenerationCases") { fixturePath in + try await executeSwiftBuild( + fixturePath, + configuration: data.config, + buildSystem: data.buildSystem, + ) + if data.buildSystem == .native { + let binPath = try fixturePath.appending(components: data.buildSystem.binPath(for: data.config)) + expectDirectoryContainsFile(dir: binPath, filename: "Jaz.c.o") + expectDirectoryContainsFile(dir: binPath, filename: "main.swift.o") + expectDirectoryContainsFile(dir: binPath, filename: "FlatInclude.c.o") + expectDirectoryContainsFile(dir: binPath, filename: "UmbrellaHeader.c.o") + } + } + } when: { + ProcessInfo.hostOperatingSystem == .windows && data.buildSystem == .swiftbuild } } - - func testNoIncludeDirCheck() async throws { - try await fixtureXCTest(name: "CFamilyTargets/CLibraryNoIncludeDir") { fixturePath in - await XCTAssertAsyncThrowsError( + + @Test( + .tags( + .Feature.Command.Build, + ), + arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), + ) + func noIncludeDirCheck( + data: BuildData, + ) async throws { + try await fixture(name: "CFamilyTargets/CLibraryNoIncludeDir") { fixturePath in + let error = try await #require(throws: (any Error).self) { try await executeSwiftBuild( fixturePath, - buildSystem: .native, - ), - "This build should throw an error", - ) { err in - // The err.localizedDescription doesn't capture the detailed error string so interpolate - let errStr = "\(err)" - let missingIncludeDirStr = "\(ModuleError.invalidPublicHeadersDirectory("Cfactorial"))" - XCTAssert(errStr.contains(missingIncludeDirStr)) + configuration: data.config, + buildSystem: data.buildSystem, + ) } + + let errString = "\(error)" + let missingIncludeDirStr = "\(ModuleError.invalidPublicHeadersDirectory("Cfactorial"))" + #expect(errString.contains(missingIncludeDirStr)) } } - func testCanForwardExtraFlagsToClang() async throws { - // Try building a fixture which needs extra flags to be able to build. - try await fixtureXCTest(name: "CFamilyTargets/CDynamicLookup") { fixturePath in - await XCTAssertBuilds(fixturePath, Xld: ["-undefined", "dynamic_lookup"], buildSystem: .native) - let debugPath = fixturePath.appending(components: ".build", try UserToolchain.default.targetTriple.platformBuildPathComponent, "debug") - XCTAssertDirectoryContainsFile(dir: debugPath, filename: "Foo.c.o") + @Test( + .tags( + .Feature.Command.Build, + ), + .IssueWindowsLongPath, + .IssueWindowsPathLastConponent, + .IssueWindowsRelativePathAssert, + .IssueWindowsCannotSaveAttachment, + arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), + ) + func canForwardExtraFlagsToClang( + data: BuildData, + ) async throws { + try await withKnownIssue(isIntermittent: true) { + try await fixture(name: "CFamilyTargets/CDynamicLookup") { fixturePath in + try await executeSwiftBuild( + fixturePath, + configuration: data.config, + Xld: ["-undefined", "dynamic_lookup"], + buildSystem: data.buildSystem, + ) + if data.buildSystem == .native { + let binPath = try fixturePath.appending(components: data.buildSystem.binPath(for: data.config)) + expectDirectoryContainsFile(dir: binPath, filename: "Foo.c.o") + } + } + } when: { + ProcessInfo.hostOperatingSystem == .windows && data.buildSystem == .swiftbuild } } - func testObjectiveCPackageWithTestTarget() async throws { - #if !os(macOS) - try XCTSkipIf(true, "test is only supported on macOS") - #endif - try await fixtureXCTest(name: "CFamilyTargets/ObjCmacOSPackage") { fixturePath in + @Test( + .tags( + .Feature.Command.Build, + .Feature.Command.Test, + ), + .requireHostOS(.macOS), + arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), + + ) + func objectiveCPackageWithTestTarget( + data: BuildData, + + ) async throws { + try await fixture(name: "CFamilyTargets/ObjCmacOSPackage") { fixturePath in // Build the package. - await XCTAssertBuilds(fixturePath, buildSystem: .native) - XCTAssertDirectoryContainsFile(dir: fixturePath.appending(components: ".build", try UserToolchain.default.targetTriple.platformBuildPathComponent, "debug"), filename: "HelloWorldExample.m.o") + try await executeSwiftBuild( + fixturePath, + configuration: data.config, + buildSystem: data.buildSystem, + ) + if data.buildSystem == .native { + let binPath = try fixturePath.appending(components: data.buildSystem.binPath(for: data.config)) + expectDirectoryContainsFile(dir: binPath, filename: "HelloWorldExample.m.o") + expectDirectoryContainsFile(dir: binPath, filename: "HelloWorldExample.m.o") + } // Run swift-test on package. - await XCTAssertSwiftTest(fixturePath, buildSystem: .native) + try await executeSwiftTest( + fixturePath, + configuration: data.config, + buildSystem: data.buildSystem, + ) + } } - - func testCanBuildRelativeHeaderSearchPaths() async throws { - try await fixtureXCTest(name: "CFamilyTargets/CLibraryParentSearchPath") { fixturePath in - await XCTAssertBuilds(fixturePath, buildSystem: .native) - XCTAssertDirectoryContainsFile(dir: fixturePath.appending(components: ".build", try UserToolchain.default.targetTriple.platformBuildPathComponent, "debug"), filename: "HeaderInclude.swiftmodule") + + @Test( + .tags( + .Feature.Command.Build, + ), + .IssueWindowsLongPath, + .IssueWindowsPathLastConponent, + .IssueWindowsRelativePathAssert, + .IssueWindowsCannotSaveAttachment, + arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms), + ) + func canBuildRelativeHeaderSearchPaths( + data: BuildData, + + ) async throws { + try await withKnownIssue(isIntermittent: true) { + try await fixture(name: "CFamilyTargets/CLibraryParentSearchPath") { fixturePath in + try await executeSwiftBuild( + fixturePath, + configuration: data.config, + buildSystem: data.buildSystem, + ) + if data.buildSystem == .native { + let binPath = try fixturePath.appending(components: data.buildSystem.binPath(for: data.config)) + expectDirectoryContainsFile(dir: binPath, filename: "HeaderInclude.swiftmodule") + } + } + } when: { + ProcessInfo.hostOperatingSystem == .windows && data.buildSystem == .swiftbuild } } }