diff --git a/Package.resolved b/Package.resolved index 6d1c3b4..6d9655e 100644 --- a/Package.resolved +++ b/Package.resolved @@ -113,8 +113,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-syntax.git", "state" : { - "revision" : "ffa3cd6fc2aa62adbedd31d3efaf7c0d86a9f029", - "version" : "509.0.1" + "revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036", + "version" : "509.0.2" } }, { diff --git a/Package.swift b/Package.swift index bdbe54c..060106a 100644 --- a/Package.swift +++ b/Package.swift @@ -26,7 +26,7 @@ let package = Package( .package(url: "https://github.com/apple/swift-nio.git", from: "2.58.0"), .package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.19.0"), .package(url: "https://github.com/apple/swift-log.git", from: "1.5.3"), - .package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.1"), + .package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.2"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Sources/GeneratorCLI/GeneratorCLI.swift b/Sources/GeneratorCLI/GeneratorCLI.swift index 552b78c..402ef76 100644 --- a/Sources/GeneratorCLI/GeneratorCLI.swift +++ b/Sources/GeneratorCLI/GeneratorCLI.swift @@ -88,7 +88,7 @@ struct GeneratorCLI: AsyncParsableCommand { let linuxDistribution = try LinuxDistribution(name: linuxDistributionName, version: linuxDistributionVersion) let elapsed = try await ContinuousClock().measure { - try await SwiftSDKGenerator( + let generator = try await SwiftSDKGenerator( hostCPUArchitecture: self.hostArch, targetCPUArchitecture: self.targetArch, swiftVersion: self.swiftVersion, @@ -98,7 +98,13 @@ struct GeneratorCLI: AsyncParsableCommand { shouldUseDocker: self.withDocker, isVerbose: self.verbose ) - .generateBundle(shouldGenerateFromScratch: !self.incremental) + do { + try await generator.generateBundle(shouldGenerateFromScratch: !self.incremental) + try await generator.shutDown() + } catch { + try await generator.shutDown() + throw error + } } print("\nTime taken for this generator run: \(elapsed.intervalString).") diff --git a/Sources/GeneratorEngine/Cache/FileCacheRecord.swift b/Sources/GeneratorEngine/Cache/FileCacheRecord.swift index cedfd3a..6e0492b 100644 --- a/Sources/GeneratorEngine/Cache/FileCacheRecord.swift +++ b/Sources/GeneratorEngine/Cache/FileCacheRecord.swift @@ -12,7 +12,7 @@ import struct SystemPackage.FilePath -struct FileCacheRecord { +public struct FileCacheRecord: Sendable { let path: FilePath let hash: String } @@ -23,14 +23,14 @@ extension FileCacheRecord: Codable { case hash } - // FIXME: `Codable` on `FilePath` is broken - init(from decoder: any Decoder) throws { + // FIXME: `Codable` on `FilePath` is broken, thus all `Codable` types with `FilePath` properties need a custom impl. + public init(from decoder: any Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.path = try FilePath(container.decode(String.self, forKey: .path)) self.hash = try container.decode(String.self, forKey: .hash) } - func encode(to encoder: any Encoder) throws { + public func encode(to encoder: any Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(self.path.string, forKey: .path) try container.encode(self.hash, forKey: .hash) diff --git a/Sources/GeneratorEngine/Engine.swift b/Sources/GeneratorEngine/Engine.swift index 56954b7..549d2f5 100644 --- a/Sources/GeneratorEngine/Engine.swift +++ b/Sources/GeneratorEngine/Engine.swift @@ -32,7 +32,6 @@ public actor Engine { /// `defer { engine.shutDown }` on the line that follows this initializer call. /// - Parameter fileSystem: Implementation of a file system this engine should use. /// - Parameter cacheLocation: Location of cache storage used by the engine. - /// - Parameter httpClient: HTTP client to use in queries that need it. /// - Parameter logger: Logger to use during queries execution. public init( _ fileSystem: any FileSystem, @@ -63,7 +62,7 @@ public actor Engine { /// Executes a given query if no cached result of it is available. Otherwise fetches the result from engine's cache. /// - Parameter query: A query value to execute. /// - Returns: A file path to query's result recorded in a file. - public subscript(_ query: some QueryProtocol) -> FilePath { + public subscript(_ query: some QueryProtocol) -> FileCacheRecord { get async throws { var hashFunction = SHA512() query.hash(with: &hashFunction) @@ -78,7 +77,7 @@ public actor Engine { if fileHash == fileRecord.hash { self.cacheHits += 1 - return fileRecord.path + return fileRecord } } @@ -90,11 +89,12 @@ public actor Engine { try await $0.hash(with: &hashFunction) } let resultHash = hashFunction.finalize() + let result = FileCacheRecord(path: resultPath, hash: resultHash.description) // FIXME: update `SQLiteBackedCache` to store `resultHash` directly instead of relying on string conversions - try self.resultsCache.set(key, to: FileCacheRecord(path: resultPath, hash: resultHash.description)) + try self.resultsCache.set(key, to: result) - return resultPath + return result } } } diff --git a/Sources/SwiftSDKGenerator/Artifacts/DownloadableArtifacts.swift b/Sources/SwiftSDKGenerator/Artifacts/DownloadableArtifacts.swift index b88e10a..5608c0b 100644 --- a/Sources/SwiftSDKGenerator/Artifacts/DownloadableArtifacts.swift +++ b/Sources/SwiftSDKGenerator/Artifacts/DownloadableArtifacts.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import struct Foundation.URL +import GeneratorEngine import struct SystemPackage.FilePath /// Information about the OS for which the artifact is built, if it's downloaded as prebuilt. @@ -45,66 +46,11 @@ enum ArtifactOS: Hashable { typealias CPUMapping = [Triple.CPU: String] -/// SHA256 hashes of binary LLVM artifacts known to the generator. -private let knownLLVMBinariesVersions: [ArtifactOS: [String: CPUMapping]] = [ - .macOS: [ - "15.0.7": [ - Triple.CPU.arm64: "867c6afd41158c132ef05a8f1ddaecf476a26b91c85def8e124414f9a9ba188d", - ], - "16.0.0": [ - Triple.CPU.arm64: "2041587b90626a4a87f0de14a5842c14c6c3374f42c8ed12726ef017416409d9", - ], - "16.0.1": [ - Triple.CPU.arm64: "cb487fa991f047dc79ae36430cbb9ef14621c1262075373955b1d97215c75879", - ], - "16.0.4": [ - Triple.CPU.arm64: "429b8061d620108fee636313df55a0602ea0d14458c6d3873989e6b130a074bd", - ], - "16.0.5": [ - Triple.CPU.arm64: "1aed0787417dd915f0101503ce1d2719c8820a2c92d4a517bfc4044f72035bcc", - ], - ], -] - -/// SHA256 hashes of binary Swift artifacts known to the generator. -private let knownSwiftBinariesVersions: [ArtifactOS: [String: CPUMapping]] = [ - .linux(.ubuntu(.jammy)): [ - "5.7.3-RELEASE": [ - .arm64: "75003d5a995292ae3f858b767fbb89bc3edee99488f4574468a0e44341aec55b", - ], - "5.8-RELEASE": [ - .arm64: "12ea2df36f9af0aefa74f0989009683600978f62223e7dd73b627c90c7fe9273", - ], - "5.9-RELEASE": [ - .arm64: "30b289e02f7e03c380744ea97fdf0e96985dff504b0f09de23e098fdaf6513f3", - .x86_64: "bca015e9d727ca39385d7e5b5399f46302d54a02218d40d1c3063662ffc6b42f", - ], - ], - .macOS: [ - "5.7.3-RELEASE": [ - .arm64: "ba3516845eb8f4469a8bb06a273687f05791187324a3843996af32a73a2a687d", - .x86_64: "ba3516845eb8f4469a8bb06a273687f05791187324a3843996af32a73a2a687d", - ], - "5.8-RELEASE": [ - .arm64: "9b6cc56993652ca222c86a2d6b7b66abbd50bb92cc526efc2b23d47d40002097", - .x86_64: "9b6cc56993652ca222c86a2d6b7b66abbd50bb92cc526efc2b23d47d40002097", - ], - "5.9-RELEASE": [ - .arm64: "3cf7a4b2f3efcfcb4fef42b6588a7b1c54f7b0f2d0a479f41c3e1620b045f48e", - .x86_64: "3cf7a4b2f3efcfcb4fef42b6588a7b1c54f7b0f2d0a479f41c3e1620b045f48e", - ], - ], -] - -private let knownLLVMSourcesVersions: [String: String] = [ - "16.0.5": "37f540124b9cfd4680666e649f557077f9937c9178489cea285a672e714b2863", -] - -public struct DownloadableArtifacts: Sendable { - public struct Item: Sendable { +struct DownloadableArtifacts: Sendable { + @CacheKey + struct Item: Sendable { let remoteURL: URL var localPath: FilePath - let checksum: String? let isPrebuilt: Bool } @@ -112,7 +58,14 @@ public struct DownloadableArtifacts: Sendable { private(set) var hostLLVM: Item let targetSwift: Item - let allItems: [Item] + private let shouldUseDocker: Bool + var allItems: [Item] { + if self.shouldUseDocker { + [self.hostSwift, self.hostLLVM] + } else { + [self.hostSwift, self.hostLLVM, self.targetSwift] + } + } private let versions: VersionsConfiguration private let paths: PathsConfiguration @@ -136,7 +89,6 @@ public struct DownloadableArtifacts: Sendable { ), localPath: paths.artifactsCachePath .appending("host_swift_\(versions.swiftVersion)_\(hostTriple).pkg"), - checksum: knownSwiftBinariesVersions[hostArtifactsOS]?[versions.swiftVersion]?[hostTriple.cpu], isPrebuilt: true ) @@ -152,7 +104,6 @@ public struct DownloadableArtifacts: Sendable { )!, localPath: paths.artifactsCachePath .appending("host_llvm_\(versions.lldVersion)_\(hostTriple).tar.xz"), - checksum: knownLLVMBinariesVersions[hostArtifactsOS]?[versions.lldVersion]?[hostTriple.cpu], isPrebuilt: true ) @@ -161,15 +112,10 @@ public struct DownloadableArtifacts: Sendable { remoteURL: versions.swiftDownloadURL(), localPath: paths.artifactsCachePath .appending("target_swift_\(versions.swiftVersion)_\(targetTriple).tar.gz"), - checksum: knownSwiftBinariesVersions[targetArtifactsOS]?[versions.swiftVersion]?[targetTriple.cpu], isPrebuilt: true ) - self.allItems = if shouldUseDocker { - [self.hostSwift, self.hostLLVM] - } else { - [self.hostSwift, self.hostLLVM, self.targetSwift] - } + self.shouldUseDocker = shouldUseDocker } mutating func useLLVMSources() { @@ -185,7 +131,6 @@ public struct DownloadableArtifacts: Sendable { )!, localPath: self.paths.artifactsCachePath .appending("llvm_\(self.versions.lldVersion).src.tar.xz"), - checksum: knownLLVMSourcesVersions[self.versions.lldVersion], isPrebuilt: false ) } diff --git a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Download.swift b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Download.swift index e69907f..84524e9 100644 --- a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Download.swift +++ b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Download.swift @@ -12,16 +12,36 @@ import AsyncAlgorithms import AsyncHTTPClient +import GeneratorEngine import RegexBuilder import class Foundation.ByteCountFormatter import struct Foundation.URL +import struct SystemPackage.FilePath + private let ubuntuAMD64Mirror = "http://gb.archive.ubuntu.com/ubuntu" private let ubuntuARM64Mirror = "http://ports.ubuntu.com/ubuntu-ports" private let byteCountFormatter = ByteCountFormatter() +@Query +struct DownloadQuery { + let artifact: DownloadableArtifacts.Item + + func run(engine: Engine) async throws -> FilePath { + print("Downloading remote artifact not available in local cache: \(self.artifact.remoteURL)") + let stream = await engine.httpClient.streamDownloadProgress(for: self.artifact) + .removeDuplicates(by: didProgressChangeSignificantly) + .throttle(for: .seconds(1)) + + for try await item in stream { + report(progress: item.progress, for: item.artifact) + } + return self.artifact.localPath + } +} + extension SwiftSDKGenerator { func downloadArtifacts(_ client: HTTPClient) async throws { logGenerationStep("Downloading required toolchain packages...") @@ -35,42 +55,19 @@ extension SwiftSDKGenerator { downloadableArtifacts.useLLVMSources() } - let hostSwiftProgressStream = client.streamDownloadProgress(for: downloadableArtifacts.hostSwift) - .removeDuplicates(by: didProgressChangeSignificantly) - let hostLLVMProgressStream = client.streamDownloadProgress(for: downloadableArtifacts.hostLLVM) - .removeDuplicates(by: didProgressChangeSignificantly) - - print("Using these URLs for downloads:") - - for artifact in downloadableArtifacts.allItems { - print(artifact.remoteURL) - } - - // FIXME: some code duplication is necessary due to https://github.com/apple/swift-async-algorithms/issues/226 - if shouldUseDocker { - let stream = combineLatest(hostSwiftProgressStream, hostLLVMProgressStream) - .throttle(for: .seconds(1)) - - for try await (swiftProgress, llvmProgress) in stream { - report(progress: swiftProgress, for: downloadableArtifacts.hostSwift) - report(progress: llvmProgress, for: downloadableArtifacts.hostLLVM) + let results = try await withThrowingTaskGroup(of: FileCacheRecord.self) { group in + for item in self.downloadableArtifacts.allItems { + print(item.remoteURL) + group.addTask { + try await self.engine[DownloadQuery(artifact: item)] + } } - } else { - let targetSwiftProgressStream = client.streamDownloadProgress(for: downloadableArtifacts.targetSwift) - .removeDuplicates(by: didProgressChangeSignificantly) - - let stream = combineLatest( - hostSwiftProgressStream, - hostLLVMProgressStream, - targetSwiftProgressStream - ) - .throttle(for: .seconds(1)) - for try await (hostSwiftProgress, hostLLVMProgress, targetSwiftProgress) in stream { - report(progress: hostSwiftProgress, for: downloadableArtifacts.hostSwift) - report(progress: hostLLVMProgress, for: downloadableArtifacts.hostLLVM) - report(progress: targetSwiftProgress, for: downloadableArtifacts.targetSwift) + var result = [FileCacheRecord]() + for try await file in group { + result.append(file) } + return result } } @@ -224,14 +221,14 @@ extension HTTPClient { /// larger than 1MiB. Returns `false` otherwise. @Sendable private func didProgressChangeSignificantly( - previous: FileDownloadDelegate.Progress, - current: FileDownloadDelegate.Progress + previous: ArtifactDownloadProgress, + current: ArtifactDownloadProgress ) -> Bool { - guard previous.totalBytes == current.totalBytes else { + guard previous.progress.totalBytes == current.progress.totalBytes else { return true } - return current.receivedBytes - previous.receivedBytes > 1024 * 1024 * 1024 + return current.progress.receivedBytes - previous.progress.receivedBytes > 1024 * 1024 * 1024 } private func report(progress: FileDownloadDelegate.Progress, for artifact: DownloadableArtifacts.Item) { diff --git a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Entrypoint.swift b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Entrypoint.swift index 49393f9..5634e04 100644 --- a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Entrypoint.swift +++ b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Entrypoint.swift @@ -26,8 +26,8 @@ public extension Triple.CPU { } } -extension SwiftSDKGenerator { - public func generateBundle(shouldGenerateFromScratch: Bool) async throws { +public extension SwiftSDKGenerator { + func generateBundle(shouldGenerateFromScratch: Bool) async throws { var configuration = HTTPClient.Configuration(redirectConfiguration: .follow(max: 5, allowCycles: false)) // Workaround an issue with github.com returning 400 instead of 404 status to HEAD requests from AHC. configuration.httpVersion = .http1Only @@ -49,9 +49,7 @@ extension SwiftSDKGenerator { try createDirectoryIfNeeded(at: pathsConfiguration.sdkDirPath) try createDirectoryIfNeeded(at: pathsConfiguration.toolchainDirPath) - if try await !self.isCacheValid { - try await self.downloadArtifacts(client) - } + try await self.downloadArtifacts(client) if !shouldUseDocker { guard case let .ubuntu(version) = versionsConfiguration.linuxDistribution else { @@ -104,35 +102,6 @@ extension SwiftSDKGenerator { """ ) } - - /// Check whether cached downloads for required `DownloadArtifacts.Item` values can be reused instead of downloading - /// them each time the generator is running. - /// - Returns: `true` if artifacts are valid, `false` otherwise. - private var isCacheValid: Bool { - get async throws { - logGenerationStep("Checking packages cache...") - - guard downloadableArtifacts.allItems.map(\.localPath).allSatisfy(doesFileExist(at:)) else { - return false - } - - return try await withThrowingTaskGroup(of: Bool.self) { taskGroup in - for artifact in downloadableArtifacts.allItems { - taskGroup.addTask { - try await Self.isChecksumValid(artifact: artifact, isVerbose: self.isVerbose) - } - } - - for try await isValid in taskGroup { - guard isValid else { - return false - } - } - - return true - } - } - } } func logGenerationStep(_ message: String) { diff --git a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator.swift b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator.swift index e200945..8c999a8 100644 --- a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator.swift +++ b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator.swift @@ -11,9 +11,11 @@ //===----------------------------------------------------------------------===// import Foundation +import GeneratorEngine +import Logging import SystemPackage -/// Implementation of ``SwiftSDKGenerator`` for the local file system. +/// Top-level actor that sequences all of the required SDK generation steps. public actor SwiftSDKGenerator { let hostTriple: Triple let targetTriple: Triple @@ -24,6 +26,9 @@ public actor SwiftSDKGenerator { let shouldUseDocker: Bool let isVerbose: Bool + let engine: Engine + private var isShutDown = false + public init( hostCPUArchitecture: Triple.CPU?, targetCPUArchitecture: Triple.CPU?, @@ -83,6 +88,28 @@ public actor SwiftSDKGenerator { ) self.shouldUseDocker = shouldUseDocker self.isVerbose = isVerbose + + let engineCachePath = self.pathsConfiguration.artifactsCachePath.appending("cache.db") + self.engine = .init( + LocalFileSystem(), + Logger(label: "org.swift.swift-sdk-generator"), + cacheLocation: .path(engineCachePath) + ) + } + + public func shutDown() async throws { + precondition(!self.isShutDown, "`SwiftSDKGenerator/shutDown` should be called only once") + try await self.engine.shutDown() + + self.isShutDown = true + } + + deinit { + let isShutDown = self.isShutDown + precondition( + isShutDown, + "`Engine/shutDown` should be called explicitly on instances of `Engine` before deinitialization" + ) } private let fileManager = FileManager.default @@ -109,24 +136,6 @@ public actor SwiftSDKGenerator { #endif } - static func isChecksumValid(artifact: DownloadableArtifacts.Item, isVerbose: Bool) async throws -> Bool { - guard let expectedChecksum = artifact.checksum else { return false } - - let computedChecksum = try await String( - Shell.readStdout("openssl dgst -sha256 \(artifact.localPath)", shouldLogCommands: isVerbose) - .split(separator: "= ")[1] - // drop the trailing newline - .dropLast() - ) - - guard computedChecksum == expectedChecksum else { - print("SHA256 digest of file at `\(artifact.localPath)` does not match expected value: \(expectedChecksum)") - return false - } - - return true - } - private func buildDockerImage(name: String, dockerfileDirectory: FilePath) async throws { try await Shell.run( "\(Self.dockerCommand) build . -t \(name)", diff --git a/Sources/SwiftSDKGenerator/SystemUtils/HTTPClient+Download.swift b/Sources/SwiftSDKGenerator/SystemUtils/HTTPClient+Download.swift index 5ade8dd..1aa30b1 100644 --- a/Sources/SwiftSDKGenerator/SystemUtils/HTTPClient+Download.swift +++ b/Sources/SwiftSDKGenerator/SystemUtils/HTTPClient+Download.swift @@ -18,6 +18,11 @@ extension FileDownloadDelegate.Progress: @unchecked Sendable {} extension FilePath: @unchecked Sendable {} +struct ArtifactDownloadProgress { + let artifact: DownloadableArtifacts.Item + let progress: FileDownloadDelegate.Progress +} + extension HTTPClient { func downloadFile( from url: URL, @@ -54,7 +59,7 @@ extension HTTPClient { func streamDownloadProgress( for artifact: DownloadableArtifacts.Item - ) -> AsyncThrowingStream { + ) -> AsyncThrowingStream { .init { continuation in do { let delegate = try FileDownloadDelegate( @@ -66,7 +71,7 @@ extension HTTPClient { } }, reportProgress: { - continuation.yield($0) + continuation.yield(ArtifactDownloadProgress(artifact: artifact, progress: $0)) } ) let request = try HTTPClient.Request(url: artifact.remoteURL) @@ -76,7 +81,7 @@ extension HTTPClient { case let .failure(error): continuation.finish(throwing: error) case let .success(finalProgress): - continuation.yield(finalProgress) + continuation.yield(ArtifactDownloadProgress(artifact: artifact, progress: finalProgress)) continuation.finish() } } diff --git a/Tests/GeneratorEngineTests/EngineTests.swift b/Tests/GeneratorEngineTests/EngineTests.swift index 66ca93f..d6f22b6 100644 --- a/Tests/GeneratorEngineTests/EngineTests.swift +++ b/Tests/GeneratorEngineTests/EngineTests.swift @@ -61,8 +61,7 @@ struct MultiplyByTwo { let x: Int func run(engine: Engine) async throws -> FilePath { - let constPath = try await engine[Const(x: self.x)] - + let constPath = try await engine[Const(x: self.x)].path let constResult = try await engine.fileSystem.read(constPath, as: Int.self) let resultPath = FilePath("/MultiplyByTwo-\(constResult)") @@ -76,7 +75,7 @@ struct AddThirty { let x: Int func run(engine: Engine) async throws -> FilePath { - let constPath = try await engine[Const(x: self.x)] + let constPath = try await engine[Const(x: self.x)].path let constResult = try await engine.fileSystem.read(constPath, as: Int.self) let resultPath = FilePath("/AddThirty-\(constResult)") @@ -91,8 +90,8 @@ struct Expression { let y: Int func run(engine: Engine) async throws -> FilePath { - let multiplyPath = try await engine[MultiplyByTwo(x: self.x)] - let addThirtyPath = try await engine[AddThirty(x: self.y)] + let multiplyPath = try await engine[MultiplyByTwo(x: self.x)].path + let addThirtyPath = try await engine[AddThirty(x: self.y)].path let multiplyResult = try await engine.fileSystem.read(multiplyPath, as: Int.self) let addThirtyResult = try await engine.fileSystem.read(addThirtyPath, as: Int.self) @@ -111,7 +110,7 @@ final class EngineTests: XCTestCase { cacheLocation: .memory ) - var resultPath = try await engine[Expression(x: 1, y: 2)] + var resultPath = try await engine[Expression(x: 1, y: 2)].path var result = try await engine.fileSystem.read(resultPath, as: Int.self) XCTAssertEqual(result, 34) @@ -122,7 +121,7 @@ final class EngineTests: XCTestCase { var cacheHits = await engine.cacheHits XCTAssertEqual(cacheHits, 0) - resultPath = try await engine[Expression(x: 1, y: 2)] + resultPath = try await engine[Expression(x: 1, y: 2)].path result = try await engine.fileSystem.read(resultPath, as: Int.self) XCTAssertEqual(result, 34) @@ -132,7 +131,7 @@ final class EngineTests: XCTestCase { cacheHits = await engine.cacheHits XCTAssertEqual(cacheHits, 1) - resultPath = try await engine[Expression(x: 2, y: 1)] + resultPath = try await engine[Expression(x: 2, y: 1)].path result = try await engine.fileSystem.read(resultPath, as: Int.self) XCTAssertEqual(result, 35) @@ -142,7 +141,7 @@ final class EngineTests: XCTestCase { cacheHits = await engine.cacheHits XCTAssertEqual(cacheHits, 3) - resultPath = try await engine[Expression(x: 2, y: 1)] + resultPath = try await engine[Expression(x: 2, y: 1)].path result = try await engine.fileSystem.read(resultPath, as: Int.self) XCTAssertEqual(result, 35) diff --git a/Tests/SwiftSDKGeneratorTests/ArchitectureMappingTests.swift b/Tests/SwiftSDKGeneratorTests/ArchitectureMappingTests.swift index 7448f5b..4d63202 100644 --- a/Tests/SwiftSDKGeneratorTests/ArchitectureMappingTests.swift +++ b/Tests/SwiftSDKGeneratorTests/ArchitectureMappingTests.swift @@ -104,6 +104,8 @@ final class ArchitectureMappingTests: XCTestCase { paths.artifactBundlePath.string + sdkDirPathSuffix, "Unexpected sdkDirPathSuffix" ) + + try await sdk.shutDown() } func testX86ToX86SDKGenerator() async throws {