Skip to content

Commit bd587ef

Browse files
committed
Make computeXCTestMinimumDeploymentTarget() more robust
This could assert with empty stdout from `xcrun` or if the output of `xcrun` was not an absolute path. We should be robust against these cases and return the fallback. rdar://problem/62898201
1 parent a9380e3 commit bd587ef

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

Sources/PackageLoading/MinimumDeploymentTarget.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ public struct MinimumDeploymentTarget {
3030
return PlatformVersion(versionString)
3131
}
3232

33+
static func computeXCTestMinimumDeploymentTarget(with runResult: ProcessResult) throws -> PlatformVersion? {
34+
let sdkPath = try AbsolutePath(validating: try runResult.utf8Output().spm_chuzzle() ?? "/")
35+
let xcTestPath = sdkPath.appending(RelativePath("Developer/Library/Frameworks/XCTest.framework/XCTest"))
36+
return try computeMinimumDeploymentTarget(of: xcTestPath)
37+
}
38+
3339
static func computeXCTestMinimumDeploymentTarget(for platform: PackageModel.Platform) -> PlatformVersion {
3440
guard let sdkName = platform.sdkName else {
3541
return platform.oldestSupportedVersion
@@ -39,10 +45,8 @@ public struct MinimumDeploymentTarget {
3945
#if os(macOS)
4046
do {
4147
let runResult = try Process.popen(arguments: ["xcrun", "--sdk", sdkName, "--show-sdk-platform-path"])
42-
let sdkPath = AbsolutePath(try runResult.utf8Output().spm_chuzzle() ?? "")
43-
let xcTestPath = sdkPath.appending(RelativePath("Developer/Library/Frameworks/XCTest.framework/XCTest"))
4448

45-
if let version = try computeMinimumDeploymentTarget(of: xcTestPath) {
49+
if let version = try computeXCTestMinimumDeploymentTarget(with: runResult) {
4650
return version
4751
}
4852
} catch { } // we do not treat this a fatal and instead use the fallback minimum deployment target
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import TSCBasic
12+
import XCTest
13+
14+
@testable import PackageLoading
15+
16+
class MinimumDeploymentTargetTests: XCTestCase {
17+
#if os(macOS) // these tests eventually call `xcrun`.
18+
func testDoesNotAssertWithNoOutput() throws {
19+
let result = ProcessResult(arguments: [],
20+
environment: [:],
21+
exitStatus: .terminated(code: 0),
22+
output: "".asResult,
23+
stderrOutput: "xcodebuild: error: SDK \"macosx\" cannot be located.".asResult)
24+
25+
XCTAssertNil(try MinimumDeploymentTarget.computeXCTestMinimumDeploymentTarget(with: result))
26+
}
27+
28+
func testThrowsWithNonPathOutput() throws {
29+
let result = ProcessResult(arguments: [],
30+
environment: [:],
31+
exitStatus: .terminated(code: 0),
32+
output: "some string".asResult,
33+
stderrOutput: "".asResult)
34+
35+
XCTAssertThrowsError(try MinimumDeploymentTarget.computeXCTestMinimumDeploymentTarget(with: result))
36+
}
37+
38+
func testThrowsWithErrorForOutput() throws {
39+
let result = ProcessResult(arguments: [],
40+
environment: [:],
41+
exitStatus: .terminated(code: 0),
42+
output: .failure(DummyError()),
43+
stderrOutput: "".asResult)
44+
45+
XCTAssertThrowsError(try MinimumDeploymentTarget.computeXCTestMinimumDeploymentTarget(with: result))
46+
}
47+
#endif
48+
}
49+
50+
private struct DummyError: Error {
51+
}
52+
53+
private extension String {
54+
var asResult: Result<[UInt8], Error> {
55+
return .success(Array(utf8))
56+
}
57+
}

0 commit comments

Comments
 (0)