Skip to content

Commit d9ff7df

Browse files
committed
Add SwiftBuild coverage support
Ensure the SwiftBuild build systam has feature parity with the Native build system as it relates to coverage. Fixes: #9077 Fixes: #9197 Issue: rdar://159461439
1 parent 8b1cfc9 commit d9ff7df

File tree

18 files changed

+933
-566
lines changed

18 files changed

+933
-566
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// swift-tools-version: 6.2
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "Simple",
8+
products: [
9+
// Products define the executables and libraries a package produces, making them visible to other packages.
10+
.library(
11+
name: "Simple",
12+
targets: ["Simple"]
13+
),
14+
],
15+
targets: [
16+
// Targets are the basic building blocks of a package, defining a module or a test suite.
17+
// Targets can depend on other targets in this package and products from dependencies.
18+
.target(
19+
name: "Simple"
20+
),
21+
.testTarget(
22+
name: "SimpleTests",
23+
dependencies: ["Simple"]
24+
),
25+
]
26+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// The Swift Programming Language
2+
// https://docs.swift.org/swift-book
3+
4+
public func greet(name: String = "world") -> String {
5+
return "Hello, \(name)!"
6+
}
7+
8+
public func libA() -> String {
9+
return "libA"
10+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import Testing
2+
import XCTest
3+
@testable import Simple
4+
5+
@Test(
6+
arguments: [
7+
"Bob",
8+
"Alice",
9+
"",
10+
]
11+
)
12+
func testGreet(
13+
name: String
14+
) async throws {
15+
let actual = greet(name: name)
16+
17+
#expect(actual == "Hello, \(name)!")
18+
}
19+
20+
final class SimpleTests: XCTestCase {
21+
func testExample() throws {
22+
XCTAssertEqual(libA(), "libA", "Actual is not as expected")
23+
}
24+
}

Sources/Commands/SwiftTestCommand.swift

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import ArgumentParser
1414

1515
@_spi(SwiftPMInternal)
1616
import Basics
17+
import struct Basics.Triple
1718

1819
import _Concurrency
1920

@@ -597,7 +598,11 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
597598
for product in testProducts {
598599
// Export the codecov data as JSON.
599600
let jsonPath = productsBuildParameters.codeCovAsJSONPath(packageName: rootManifest.displayName)
600-
try await exportCodeCovAsJSON(to: jsonPath, testBinary: product.binaryPath, swiftCommandState: swiftCommandState)
601+
try await exportCodeCovAsJSON(
602+
to: jsonPath,
603+
testBinary: product.binaryPath,
604+
swiftCommandState: swiftCommandState,
605+
)
601606
}
602607
}
603608

@@ -619,7 +624,6 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
619624
}
620625
}
621626
args += ["-o", productsBuildParameters.codeCovDataFile.pathString]
622-
623627
try await AsyncProcess.checkNonZeroExit(arguments: args)
624628
}
625629

@@ -632,11 +636,17 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
632636
// Export using the llvm-cov tool.
633637
let llvmCov = try swiftCommandState.getTargetToolchain().getLLVMCov()
634638
let (productsBuildParameters, _) = try swiftCommandState.buildParametersForTest(options: self.options)
639+
let archArgs: [String] = if let arch = productsBuildParameters.triple.llvmCovArchArgument {
640+
["--arch", "\(arch)"]
641+
} else {
642+
[]
643+
}
635644
let args = [
636645
llvmCov.pathString,
637646
"export",
638647
"-instr-profile=\(productsBuildParameters.codeCovDataFile)",
639-
testBinary.pathString
648+
] + archArgs + [
649+
testBinary.pathString,
640650
]
641651
let result = try await AsyncProcess.popen(arguments: args)
642652

@@ -709,6 +719,21 @@ extension SwiftTestCommand {
709719
}
710720
}
711721

722+
fileprivate extension Triple {
723+
var llvmCovArchArgument: String? {
724+
guard let arch = self.arch else {
725+
return nil
726+
}
727+
switch arch {
728+
case .aarch64:
729+
// Apple platforms uses arm64
730+
return self.isApple() ? "arm64" : "aarch64"
731+
default:
732+
return "\(arch)"
733+
}
734+
}
735+
}
736+
712737
extension SwiftTestCommand {
713738
struct Last: SwiftCommand {
714739
@OptionGroup(visibility: .hidden)

Sources/SwiftBuildSupport/SwiftBuildSystem.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,8 +1077,9 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
10771077

10781078
private static func constructTestingSettingsOverrides(from parameters: BuildParameters.Testing) -> [String: String] {
10791079
var settings: [String: String] = [:]
1080-
// TODO: enableCodeCoverage
1081-
// explicitlyEnabledTestability
1080+
1081+
// Coverage settings
1082+
settings["CLANG_COVERAGE_MAPPING"] = parameters.enableCodeCoverage ? "YES" : "NO"
10821083

10831084
switch parameters.explicitlyEnabledTestability {
10841085
case true:

Sources/_InternalTestSupport/SwiftTesting+TraitsBug.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ extension Trait where Self == Testing.Bug {
5454
)
5555
}
5656

57+
public static var IssueWindowsPathTestsFailures: Self {
58+
.issue(
59+
"https://github.com/swiftlang/swift-package-manager/issues/8511",
60+
relationship: .defect,
61+
)
62+
}
63+
5764
public static var IssueWindowsCannotSaveAttachment: Self {
5865
// 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)
5966
.issue(

Tests/BasicsTests/FileSystem/PathTests.swift

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct PathTests {
4343
}
4444

4545
@Test(
46+
.IssueWindowsPathTestsFailures,
4647
arguments: [
4748
(path: "/ab/cd/ef/", expected: (windows ? #"\ab\cd\ef"# : "/ab/cd/ef"), label: "Trailing path seperator"),
4849
(path: "/ab/cd/ef//", expected: (windows ? #"\ab\cd\ef"# : "/ab/cd/ef"), label: "Trailing path seperator"),
@@ -110,6 +111,7 @@ struct PathTests {
110111
}
111112

112113
@Test(
114+
.IssueWindowsPathTestsFailures,
113115
arguments: [
114116
(path: "/./a", expected: (windows ? #"\"# : "/")),
115117
(path: "/../..", expected: (windows ? #"\"# : "/")),
@@ -143,6 +145,7 @@ struct PathTests {
143145
}
144146

145147
@Test(
148+
.IssueWindowsPathTestsFailures,
146149
arguments: [
147150
(path: "/../..", expected: "/"),
148151
]
@@ -178,6 +181,7 @@ struct PathTests {
178181
}
179182

180183
@Test(
184+
.IssueWindowsPathTestsFailures,
181185
arguments: [
182186
(path: "/../..", expected: "/"),
183187
]
@@ -204,6 +208,7 @@ struct PathTests {
204208
#expect(actual == expectedPath)
205209
}
206210
@Test(
211+
.IssueWindowsPathTestsFailures,
207212
arguments: [
208213
(path: "/", numParentDirectoryCalls: 1, expected: "/"),
209214
(path: "/", numParentDirectoryCalls: 2, expected: "/"),
@@ -215,6 +220,7 @@ struct PathTests {
215220
}
216221

217222
@Test(
223+
.IssueWindowsPathTestsFailures,
218224
arguments: [
219225
(path: "/bar/../foo/..//", numParentDirectoryCalls: 2, expected: "/"),
220226
(path: "/bar/../foo/..//yabba/a/b", numParentDirectoryCalls: 2, expected: "/yabba")
@@ -231,6 +237,7 @@ struct PathTests {
231237
}
232238

233239
@Test(
240+
.IssueWindowsPathTestsFailures,
234241
arguments: [
235242
(path: "/", expected: ["/"]),
236243
(path: "/.", expected: ["/"]),
@@ -368,6 +375,7 @@ struct PathTests {
368375
}
369376

370377
@Test(
378+
.IssueWindowsPathTestsFailures,
371379
arguments: [
372380
(path: "ab//cd//ef", expected: (windows ? #"ab\cd\ef"# : "ab/cd/ef"), label: "repeated path seperators"),
373381
(path: "ab//cd///ef", expected: (windows ? #"ab\cd\ef"# : "ab/cd/ef"), label: "repeated path seperators"),
@@ -440,7 +448,8 @@ struct PathTests {
440448
}
441449

442450
@Test(
443-
arguments: [
451+
.IssueWindowsPathTestsFailures,
452+
arguments: [
444453
(path: "../a/..", expected: "."),
445454
(path: "a/..", expected: "."),
446455
(path: "a/../////../////./////", expected: "."),
@@ -481,6 +490,7 @@ struct PathTests {
481490
}
482491

483492
@Test(
493+
.IssueWindowsPathTestsFailures,
484494
arguments: [
485495
(path: "a/..", expected: "."),
486496
(path: "a/../////../////./////", expected: ".."),
@@ -519,6 +529,7 @@ struct PathTests {
519529
}
520530

521531
@Test(
532+
.IssueWindowsPathTestsFailures,
522533
arguments: [
523534
(path: "../..", expected: ".."),
524535
(path: "../a/..", expected: ".."),
@@ -560,7 +571,8 @@ struct PathTests {
560571
}
561572

562573
@Test(
563-
arguments:[
574+
.IssueWindowsPathTestsFailures,
575+
arguments:[
564576
"a.",
565577
".a",
566578
"",
@@ -601,6 +613,7 @@ struct PathTests {
601613
}
602614

603615
@Test(
616+
.IssueWindowsPathTestsFailures,
604617
arguments: [
605618
(path: "foo/bar/..", expected: ["foo"]),
606619
(path: "bar/../foo", expected: ["foo"]),
@@ -622,21 +635,22 @@ struct PathTests {
622635
}
623636
}
624637

625-
@Test
638+
@Test(
639+
.IssueWindowsPathTestsFailures,
640+
)
626641
func relativePathValidation() throws {
627642
#expect(throws: Never.self) {
628643
try RelativePath(validating: "a/b/c/d")
629644
}
630645

631-
withKnownIssue {
646+
withKnownIssue("https://github.com/swiftlang/swift-package-manager/issues/8511: \\") {
632647
#expect {try RelativePath(validating: "/a/b/d")} throws: { error in
633648
("\(error)" == "invalid relative path '/a/b/d'; relative path should not begin with '/'")
634649
}
635650
} when: {
636651
ProcessInfo.hostOperatingSystem == .windows
637652
}
638653
}
639-
640654
}
641655

642656
@Test

Tests/BasicsTests/HTTPClientTests.swift

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -259,11 +259,8 @@ struct HTTPClientTests {
259259
var request = HTTPClient.Request(method: .get, url: "http://test")
260260
request.options.validResponseCodes = [200]
261261

262-
do {
263-
let response = try await httpClient.execute(request)
264-
Issue.record("unexpected success \(response)")
265-
} catch {
266-
#expect(error as? HTTPClientError == .badResponseStatusCode(statusCode))
262+
await #expect(throws: HTTPClientError.badResponseStatusCode(statusCode)) {
263+
try await httpClient.execute(request)
267264
}
268265
}
269266

@@ -407,11 +404,8 @@ struct HTTPClientTests {
407404
var request = HTTPClient.Request(url: "http://test")
408405
request.options.maximumResponseSizeInBytes = 10
409406

410-
do {
411-
let response = try await httpClient.execute(request)
412-
Issue.record("unexpected success \(response)")
413-
} catch {
414-
#expect(error as? HTTPClientError == .responseTooLarge(maxSize * 2))
407+
await #expect(throws: HTTPClientError.responseTooLarge(maxSize * 2)) {
408+
try await httpClient.execute(request)
415409
}
416410
}
417411

Tests/BuildTests/PluginsBuildPlanTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct PluginsBuildPlanTests {
2828
.tags(
2929
.Feature.Command.Build,
3030
),
31-
.issue("https://github.com/swiftlang/swift-package-manager/issues/8511", relationship: .defect), // Fails to build the project to due to incorrect Path handling
31+
.IssueWindowsPathTestsFailures, // Fails to build the project to due to incorrect Path handling
3232
arguments: BuildConfiguration.allCases,
3333
)
3434
func buildToolsDatabasePath(

0 commit comments

Comments
 (0)