From 85e0124d4080c46989900ad1ca286e26cc79161d Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Wed, 20 Aug 2025 21:37:40 -0700 Subject: [PATCH] Fix the build when the SubprocessFoundation trait is disabled Closes #129 --- .github/workflows/pull_request.yml | 11 +++++ Sources/Subprocess/Buffer.swift | 42 +++++++++++++++++++- Tests/SubprocessTests/IntegrationTests.swift | 14 +++++++ Tests/SubprocessTests/UnixTests.swift | 2 + 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d212a627..d1bf7009 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -28,11 +28,22 @@ jobs: # Test dependencies yum install -y procps fi + linux_build_command: 'swift test && swift test --disable-default-traits' windows_swift_versions: '["6.1", "nightly-main"]' + windows_build_command: | + Invoke-Program swift test + Invoke-Program swift test --disable-default-traits enable_macos_checks: true macos_xcode_versions: '["16.3"]' + macos_build_command: 'xcrun swift test && xcrun swift test --disable-default-traits' enable_linux_static_sdk_build: true linux_static_sdk_versions: '["6.1", "nightly-6.2"]' + linux_static_sdk_build_command: | + for triple in aarch64-swift-linux-musl x86_64-swift-linux-musl ; do + swift build --swift-sdk "\$triple" + swift build --swift-sdk "\$triple" --disable-default-traits + done + # empty line to ignore the --swift-sdk given by swiftlang/github-workflows/.github/workflows/scripts/install-and-build-with-sdk.sh \ soundness: name: Soundness diff --git a/Sources/Subprocess/Buffer.swift b/Sources/Subprocess/Buffer.swift index 4cd59d3c..8152ac56 100644 --- a/Sources/Subprocess/Buffer.swift +++ b/Sources/Subprocess/Buffer.swift @@ -120,5 +120,45 @@ extension DispatchData.Region { } } } -#endif +#if !SubprocessFoundation +/// `DispatchData.Region` is defined in Foundation, but we can't depend on Foundation when the SubprocessFoundation trait is disabled. +extension DispatchData { + typealias Region = _ContiguousBufferView + + var regions: [Region] { + contiguousBufferViews + } + + internal struct _ContiguousBufferView: @unchecked Sendable, RandomAccessCollection { + typealias Element = UInt8 + + internal let bytes: UnsafeBufferPointer + + internal var startIndex: Int { self.bytes.startIndex } + internal var endIndex: Int { self.bytes.endIndex } + + internal init(bytes: UnsafeBufferPointer) { + self.bytes = bytes + } + + internal func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType { + return try body(UnsafeRawBufferPointer(self.bytes)) + } + subscript(position: Int) -> UInt8 { + _read { + yield self.bytes[position] + } + } + } + + internal var contiguousBufferViews: [_ContiguousBufferView] { + var slices = [_ContiguousBufferView]() + enumerateBytes { (bytes, index, stop) in + slices.append(_ContiguousBufferView(bytes: bytes)) + } + return slices + } +} +#endif +#endif diff --git a/Tests/SubprocessTests/IntegrationTests.swift b/Tests/SubprocessTests/IntegrationTests.swift index 99045d9b..5788ae4a 100644 --- a/Tests/SubprocessTests/IntegrationTests.swift +++ b/Tests/SubprocessTests/IntegrationTests.swift @@ -559,6 +559,7 @@ extension SubprocessIntegrationTests { ) } + #if SubprocessFoundation @Test func testFileDescriptorInput() async throws { #if os(Windows) let setup = TestSetup( @@ -592,6 +593,7 @@ extension SubprocessIntegrationTests { // Make sure we read all bytes #expect(cat.standardOutput == expected) } + #endif #if SubprocessFoundation @Test func testDataInput() async throws { @@ -658,6 +660,7 @@ extension SubprocessIntegrationTests { } #endif + #if SubprocessFoundation @Test func testAsyncSequenceInput() async throws { #if os(Windows) let setup = TestSetup( @@ -700,6 +703,7 @@ extension SubprocessIntegrationTests { #expect(catResult.terminationStatus.isSuccess) #expect(catResult.standardOutput == expected) } + #endif @Test func testStandardInputWriterInput() async throws { #if os(Windows) @@ -810,6 +814,7 @@ extension SubprocessIntegrationTests { #expect(echoResult.terminationStatus.isSuccess) } + #if SubprocessFoundation @Test func testStringOutput() async throws { #if os(Windows) let setup = TestSetup( @@ -845,6 +850,7 @@ extension SubprocessIntegrationTests { ).trimmingNewLineAndQuotes() ) } + #endif @Test func testStringOutputExceedsLimit() async throws { #if os(Windows) @@ -878,6 +884,7 @@ extension SubprocessIntegrationTests { } } + #if SubprocessFoundation @Test func testBytesOutput() async throws { #if os(Windows) let setup = TestSetup( @@ -907,6 +914,7 @@ extension SubprocessIntegrationTests { catResult.standardOutput == Array(expected) ) } + #endif @Test func testBytesOutputExceedsLimit() async throws { #if os(Windows) @@ -1089,6 +1097,7 @@ extension SubprocessIntegrationTests { } #endif + #if SubprocessFoundation @Test func testStringErrorOutput() async throws { #if os(Windows) let setup = TestSetup( @@ -1124,6 +1133,7 @@ extension SubprocessIntegrationTests { ).trimmingNewLineAndQuotes() ) } + #endif @Test func testStringErrorOutputExceedsLimit() async throws { #if os(Windows) @@ -1156,6 +1166,7 @@ extension SubprocessIntegrationTests { } } + #if SubprocessFoundation @Test func testBytesErrorOutput() async throws { #if os(Windows) let setup = TestSetup( @@ -1185,6 +1196,7 @@ extension SubprocessIntegrationTests { catResult.standardError == Array(expected) ) } + #endif @Test func testBytesErrorOutputExceedsLimit() async throws { #if os(Windows) @@ -1757,6 +1769,7 @@ extension SubprocessIntegrationTests { try FileManager.default.removeItem(at: testFilePath) } + #if SubprocessFoundation @Test func testCaptureLongStandardOutputAndError() async throws { let string = String(repeating: "X", count: 100_000) #if os(Windows) @@ -1791,6 +1804,7 @@ extension SubprocessIntegrationTests { try await group.waitForAll() } } + #endif @Test func stressTestCancelProcessVeryEarlyOn() async throws { diff --git a/Tests/SubprocessTests/UnixTests.swift b/Tests/SubprocessTests/UnixTests.swift index 66f4342e..a27bc2d4 100644 --- a/Tests/SubprocessTests/UnixTests.swift +++ b/Tests/SubprocessTests/UnixTests.swift @@ -487,6 +487,7 @@ internal func assertNewSessionCreated( // MARK: - Performance Tests extension SubprocessUnixTests { + #if SubprocessFoundation @Test(.requiresBash) func testConcurrentRun() async throws { // Launch as many processes as we can // Figure out the max open file limit @@ -540,6 +541,7 @@ extension SubprocessUnixTests { try await group.waitForAll() } } + #endif } #endif // canImport(Darwin) || canImport(Glibc)