Skip to content

Commit 2a01f6e

Browse files
authored
Use structured concurrency in PackageLoadingTests (#7359)
This is a stripped down version of #6624 that modifies only the test suite and doesn't make any substantial to `ManifestLoader.swift` other than providing an `async` overload in `extension ManifestLoaderProtocol` that uses `withCheckedThrowingContinuation` to bridge into the existing implementation.
1 parent 5287062 commit 2a01f6e

19 files changed

+465
-514
lines changed

Package.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -608,10 +608,6 @@ let package = Package(
608608
dependencies: ["PackageLoading", "SPMTestSupport"],
609609
exclude: ["Inputs", "pkgconfigInputs"]
610610
),
611-
.testTarget(
612-
name: "PackageLoadingPerformanceTests",
613-
dependencies: ["PackageLoading", "SPMTestSupport"]
614-
),
615611
.testTarget(
616612
name: "PackageModelTests",
617613
dependencies: ["PackageModel", "SPMTestSupport"]

Sources/PackageLoading/ManifestLoader.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,39 @@ extension ManifestLoaderProtocol {
232232
completion(.failure(error))
233233
}
234234
}
235+
}
236+
237+
public func load(
238+
packagePath: AbsolutePath,
239+
packageIdentity: PackageIdentity,
240+
packageKind: PackageReference.Kind,
241+
packageLocation: String,
242+
packageVersion: (version: Version?, revision: String?)?,
243+
currentToolsVersion: ToolsVersion,
244+
identityResolver: IdentityResolver,
245+
dependencyMapper: DependencyMapper,
246+
fileSystem: FileSystem,
247+
observabilityScope: ObservabilityScope,
248+
delegateQueue: DispatchQueue,
249+
callbackQueue: DispatchQueue
250+
) async throws -> Manifest {
251+
try await withCheckedThrowingContinuation {
252+
self.load(
253+
packagePath: packagePath,
254+
packageIdentity: packageIdentity,
255+
packageKind: packageKind,
256+
packageLocation: packageLocation,
257+
packageVersion: packageVersion,
258+
currentToolsVersion: currentToolsVersion,
259+
identityResolver: identityResolver,
260+
dependencyMapper: dependencyMapper,
261+
fileSystem: fileSystem,
262+
observabilityScope: observabilityScope,
263+
delegateQueue: delegateQueue,
264+
callbackQueue: callbackQueue,
265+
completion: $0.resume(with:)
266+
)
267+
}
235268
}
236269
}
237270

Sources/SPMTestSupport/MockManifestLoader.swift

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import PackageGraph
1818

1919
import func XCTest.XCTFail
2020

21+
import enum TSCBasic.ProcessEnv
2122
import struct TSCUtility.Version
2223

2324
public enum MockManifestLoaderError: Swift.Error {
@@ -88,7 +89,7 @@ extension ManifestLoader {
8889
dependencyMapper: DependencyMapper? = .none,
8990
fileSystem: FileSystem,
9091
observabilityScope: ObservabilityScope
91-
) throws -> Manifest{
92+
) async throws -> Manifest{
9293
let packageIdentity: PackageIdentity
9394
let packageLocation: String
9495
switch packageKind {
@@ -109,27 +110,23 @@ extension ManifestLoader {
109110
// FIXME: placeholder
110111
packageLocation = identity.description
111112
}
112-
return try temp_await {
113-
self.load(
114-
manifestPath: manifestPath,
115-
manifestToolsVersion: manifestToolsVersion,
116-
packageIdentity: packageIdentity,
117-
packageKind: packageKind,
118-
packageLocation: packageLocation,
119-
packageVersion: nil,
120-
identityResolver: identityResolver,
121-
dependencyMapper: dependencyMapper ?? DefaultDependencyMapper(identityResolver: identityResolver),
122-
fileSystem: fileSystem,
123-
observabilityScope: observabilityScope,
124-
delegateQueue: .sharedConcurrent,
125-
callbackQueue: .sharedConcurrent,
126-
completion: $0
127-
)
128-
}
113+
return try await self.load(
114+
manifestPath: manifestPath,
115+
manifestToolsVersion: manifestToolsVersion,
116+
packageIdentity: packageIdentity,
117+
packageKind: packageKind,
118+
packageLocation: packageLocation,
119+
packageVersion: nil,
120+
identityResolver: identityResolver,
121+
dependencyMapper: dependencyMapper ?? DefaultDependencyMapper(identityResolver: identityResolver),
122+
fileSystem: fileSystem,
123+
observabilityScope: observabilityScope,
124+
delegateQueue: .sharedConcurrent,
125+
callbackQueue: .sharedConcurrent
126+
)
129127
}
130128
}
131129

132-
133130
extension ManifestLoader {
134131
public func load(
135132
packagePath: AbsolutePath,
@@ -139,7 +136,7 @@ extension ManifestLoader {
139136
dependencyMapper: DependencyMapper? = .none,
140137
fileSystem: FileSystem,
141138
observabilityScope: ObservabilityScope
142-
) throws -> Manifest{
139+
) async throws -> Manifest{
143140
let packageIdentity: PackageIdentity
144141
let packageLocation: String
145142
switch packageKind {
@@ -160,22 +157,44 @@ extension ManifestLoader {
160157
// FIXME: placeholder
161158
packageLocation = identity.description
162159
}
163-
return try temp_await {
164-
self.load(
165-
packagePath: packagePath,
166-
packageIdentity: packageIdentity,
167-
packageKind: packageKind,
168-
packageLocation: packageLocation,
169-
packageVersion: nil,
170-
currentToolsVersion: currentToolsVersion,
171-
identityResolver: identityResolver,
172-
dependencyMapper: dependencyMapper ?? DefaultDependencyMapper(identityResolver: identityResolver),
173-
fileSystem: fileSystem,
174-
observabilityScope: observabilityScope,
175-
delegateQueue: .sharedConcurrent,
176-
callbackQueue: .sharedConcurrent,
177-
completion: $0
178-
)
160+
return try await self.load(
161+
packagePath: packagePath,
162+
packageIdentity: packageIdentity,
163+
packageKind: packageKind,
164+
packageLocation: packageLocation,
165+
packageVersion: nil,
166+
currentToolsVersion: currentToolsVersion,
167+
identityResolver: identityResolver,
168+
dependencyMapper: dependencyMapper ?? DefaultDependencyMapper(identityResolver: identityResolver),
169+
fileSystem: fileSystem,
170+
observabilityScope: observabilityScope,
171+
delegateQueue: .sharedConcurrent,
172+
callbackQueue: .sharedConcurrent
173+
)
174+
}
175+
}
176+
177+
/// Temporary override environment variables
178+
///
179+
/// WARNING! This method is not thread-safe. POSIX environments are shared
180+
/// between threads. This means that when this method is called simultaneously
181+
/// from different threads, the environment will neither be setup nor restored
182+
/// correctly.
183+
public func withCustomEnv(_ env: [String: String], body: () async throws -> Void) async throws {
184+
let state = env.map { ($0, $1) }
185+
let restore = {
186+
for (key, value) in state {
187+
try ProcessEnv.setVar(key, value: value)
188+
}
189+
}
190+
do {
191+
for (key, value) in env {
192+
try ProcessEnv.setVar(key, value: value)
179193
}
194+
try await body()
195+
} catch {
196+
try? restore()
197+
throw error
180198
}
199+
try restore()
181200
}

Sources/SPMTestSupport/XCTAssertHelpers.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,35 @@ public func XCTAssertThrowsCommandExecutionError<T>(
187187
}
188188
}
189189

190+
public func XCTAssertAsyncEqual<T: Equatable>(
191+
_ expression1: @autoclosure () async throws -> T,
192+
_ expression2: @autoclosure () async throws -> T,
193+
_ message: @autoclosure () -> String = "",
194+
file: StaticString = #file,
195+
line: UInt = #line
196+
) async rethrows {
197+
let value1 = try await expression1()
198+
let value2 = try await expression2()
199+
200+
XCTAssertEqual(value1, value2, message(), file: file, line: line)
201+
}
202+
203+
struct XCAsyncTestErrorWhileUnwrappingOptional: Error {}
204+
205+
public func XCTAsyncUnwrap<T>(
206+
_ expression: @autoclosure () async throws -> T?,
207+
_ message: @autoclosure () -> String = "",
208+
file: StaticString = #filePath,
209+
line: UInt = #line
210+
) async throws -> T {
211+
guard let result = try await expression() else {
212+
throw XCAsyncTestErrorWhileUnwrappingOptional()
213+
}
214+
215+
return result
216+
}
217+
218+
190219
public struct CommandExecutionError: Error {
191220
public let result: ProcessResult
192221
public let stdout: String

Tests/PackageLoadingPerformanceTests/ManifestLoadingTests.swift

Lines changed: 0 additions & 92 deletions
This file was deleted.

0 commit comments

Comments
 (0)