From 518e8adc337e76f659287277d607d5c58c22aabc Mon Sep 17 00:00:00 2001 From: Mick F Date: Mon, 8 Jan 2024 12:11:28 +0100 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Globally=20exclude?= =?UTF-8?q?=20ObjC=20product=20and=20targets=20for=20Linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So that Swift Package Index can recognize the Linux support of the package. --- Dockerfile | 2 +- Package.swift | 79 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 54 insertions(+), 27 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4c0f4cc..54c3aa6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ WORKDIR /app COPY . . # Build the Swift project -RUN swift build --target Blocks +RUN swift build # Run the tests CMD ["swift", "test"] diff --git a/Package.swift b/Package.swift index 88752ff..4d8c08e 100644 --- a/Package.swift +++ b/Package.swift @@ -3,6 +3,57 @@ // 📜 https://github.com/apple/swift-package-manager/blob/main/Documentation/PackageDescription.md import PackageDescription +#if os(Linux) +let products: [Product] = [ + .library( + name: "Blocks", + targets: ["Blocks"] + ) +] +#else +let products: [Product] = [ + .library( + name: "Blocks", + targets: ["Blocks"] + ), + .library( + name: "ObjectiveBlocks", + targets: ["ObjectiveBlocks"] + ) +] +#endif + +#if os(Linux) +let targets: [Target] = [ + .target( + name: "Blocks", + dependencies: [] + ), + .testTarget( + name: "BlocksTests", + dependencies: ["Blocks"], + resources: [.process("Resources")] + ) +] +#else +let targets: [Target] = [ + .target( + name: "Blocks", + dependencies: [] + ), + .testTarget( + name: "BlocksTests", + dependencies: ["Blocks"], + resources: [.process("Resources")] + ), + .target( + name: "ObjectiveBlocks", + dependencies: [], + publicHeadersPath: "public" + ) +] +#endif + let package = Package( name: "swift-blocks", platforms: [ @@ -11,31 +62,7 @@ let package = Package( .tvOS(.v15), .watchOS(.v8) ], - products: [ - .library( - name: "Blocks", - targets: ["Blocks"] - ), - .library( - name: "ObjectiveBlocks", - targets: ["ObjectiveBlocks"] - ) - ], + products: products, dependencies: [], - targets: [ - .target( - name: "Blocks", - dependencies: [] - ), - .testTarget( - name: "BlocksTests", - dependencies: ["Blocks"], - resources: [.process("Resources")] - ), - .target( - name: "ObjectiveBlocks", - dependencies: [], - publicHeadersPath: "public" - ) - ] + targets: targets ) From 50a1e0e437b8e975efac0eb2de6c2633735b5508 Mon Sep 17 00:00:00 2001 From: Mick F Date: Mon, 8 Jan 2024 14:22:23 +0100 Subject: [PATCH 2/4] =?UTF-8?q?ci:=20=F0=9F=8E=A1=20Improve=20CI=20command?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build everything on Linux, and on iOS as well --- .github/workflows/build-linux.yml | 2 +- Makefile | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index c12d6ff..cc2f570 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -16,6 +16,6 @@ jobs: uses: actions/checkout@v4 - name: Build debug version run: | - swift build --target Blocks + swift build # TODO: Find a way for tests to work in spite of `ObjectiveBlocks` diff --git a/Makefile b/Makefile index 9b17faa..7697fd4 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,8 @@ cli: swift build --package-path Examples/BlocksCLI/ build-ios: - xcodebuild -verbose -scheme Blocks -destination "platform=iOS Simulator,OS=17.0.1" -derivedDataPath "/tmp/" clean build + xcrun xcodebuild clean build -scheme Blocks -destination generic/platform=ios + xcrun xcodebuild clean build -scheme ObjectiveBlocks -destination generic/platform=ios test-debug: swift package clean From b08e3f54e9cdb41d3534d7d4a7d7e4daf6badf62 Mon Sep 17 00:00:00 2001 From: Mick F Date: Mon, 8 Jan 2024 14:39:07 +0100 Subject: [PATCH 3/4] =?UTF-8?q?ci:=20=F0=9F=8E=A1=20Multiple=20jobs=20in?= =?UTF-8?q?=20same=20workflow=20to=20build=20Blocks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-ios.yml | 28 ----------------------- .github/workflows/build-linux.yml | 21 ----------------- .github/workflows/build.yml | 38 +++++++++++++++++++++++++++++-- Makefile | 2 +- 4 files changed, 37 insertions(+), 52 deletions(-) delete mode 100644 .github/workflows/build-ios.yml delete mode 100644 .github/workflows/build-linux.yml diff --git a/.github/workflows/build-ios.yml b/.github/workflows/build-ios.yml deleted file mode 100644 index 42a0158..0000000 --- a/.github/workflows/build-ios.yml +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: Build iOS - -# 📜 https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows -on: - workflow_dispatch: - pull_request: - branches: - - main - -jobs: - build: - runs-on: macos-13 - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Output XCode version - run: | - xcodebuild -version - - name: Build debug version - run: | - make build-ios - -# TODO: Find a way for tests without the following error: -# -# ``` -# Error Domain=com.apple.dt.IDEContainerErrorDomain Code=6 "Cannot open "Documentation.docc" as a "Folder" because it is already open as a "Swift User Managed Package Folder"." UserInfo={NSLocalizedDescription=Cannot open "Documentation.docc" as a "Folder" because it is already open as a "Swift User Managed Package Folder".} -# ``` diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml deleted file mode 100644 index cc2f570..0000000 --- a/.github/workflows/build-linux.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: Build Linux - -# 📜 https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows -on: - workflow_dispatch: - pull_request: - branches: - - main - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Build debug version - run: | - swift build - -# TODO: Find a way for tests to work in spite of `ObjectiveBlocks` diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 093385d..5be1eff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,5 +1,5 @@ --- -name: Build macOS +name: Build Blocks # 📜 https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows on: @@ -9,7 +9,8 @@ on: - main jobs: - build: + build_macOS: + name: Build macOS runs-on: macos-13 steps: - name: Checkout @@ -23,3 +24,36 @@ jobs: - name: Test debug version run: | make test + + build_iOS: + name: Build iOS + runs-on: macos-13 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Output XCode version + run: | + xcodebuild -version + - name: Show destinations + run: xcrun xcodebuild -showdestinations -scheme Blocks + - name: Build debug version + run: | + make build-ios + # TODO: Find a way for tests without the following error: + # + # ``` + # Error Domain=com.apple.dt.IDEContainerErrorDomain Code=6 "Cannot open "Documentation.docc" as a "Folder" because it is already open as a "Swift User Managed Package Folder"." UserInfo={NSLocalizedDescription=Cannot open "Documentation.docc" as a "Folder" because it is already open as a "Swift User Managed Package Folder".} + # ``` + + build_linux: + name: Build Linux + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Build debug version + run: | + swift build + - name: Test debug version + run: | + swift test diff --git a/Makefile b/Makefile index 7697fd4..22b4a76 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ test: set -o pipefail && swift test | xcpretty test-ios: - xcodebuild -verbose -scheme Blocks -destination "platform=iOS Simulator,OS=17.0.1" -derivedDataPath "/tmp/" clean build test + xcrun xcodebuild clean test -scheme Blocks -destination "platform=iOS Simulator,OS=17.0.1" release: swift build -c release From b2e255a6ed12bf679df9d677a5150b5cf4b6f7bc Mon Sep 17 00:00:00 2001 From: Mick F Date: Mon, 8 Jan 2024 16:06:28 +0100 Subject: [PATCH 4/4] =?UTF-8?q?test:=20=F0=9F=92=8D=20Make=20tests=20pass?= =?UTF-8?q?=20on=20Linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 3 + Tests/BlocksTests/JSONTests.swift | 11 -- Tests/BlocksTests/Security/PKCETests.swift | 2 + .../Security/SecurityErrorTests.swift | 2 + .../Security/SecurityUtilsTests.swift | 4 +- .../Transport/DummyURLRequest.swift | 3 + .../Transport/LoggingTransportTests.swift | 2 + .../StatusCodeCheckingTransportTests.swift | 4 + .../URLLoadingSystemErrorCodesTests.swift | 105 ++++++++++-------- .../Transport/URLRequestHeaderItemTests.swift | 3 + 10 files changed, 78 insertions(+), 61 deletions(-) diff --git a/Makefile b/Makefile index 22b4a76..ecb7333 100644 --- a/Makefile +++ b/Makefile @@ -58,3 +58,6 @@ dump-packages: build-linux-dev: docker build -t swift-blocks . + +test-linux-dev: + docker run swift-blocks \ No newline at end of file diff --git a/Tests/BlocksTests/JSONTests.swift b/Tests/BlocksTests/JSONTests.swift index 9b197b5..05e39cc 100644 --- a/Tests/BlocksTests/JSONTests.swift +++ b/Tests/BlocksTests/JSONTests.swift @@ -1,5 +1,4 @@ @testable import Blocks -import os import XCTest final class JSONTests: XCTestCase { @@ -44,15 +43,5 @@ final class JSONTests: XCTestCase { ] } """) - - // Test how things look with print and logger - JSON.print(sampleCodable) - - if #available(iOS 14.0, *) { - let logger = Logger(subsystem: "swift-blocks", category: "JSON") - logger.info("JSON public: \(JSON.stringify(sampleCodable), privacy: .public)") - logger.info("JSON private: \(JSON.stringify(sampleCodable), privacy: .private)") - logger.info("JSON auto/hash: \(JSON.stringify(sampleCodable), privacy: .auto(mask: .hash))") - } } } diff --git a/Tests/BlocksTests/Security/PKCETests.swift b/Tests/BlocksTests/Security/PKCETests.swift index 20087c8..09af314 100644 --- a/Tests/BlocksTests/Security/PKCETests.swift +++ b/Tests/BlocksTests/Security/PKCETests.swift @@ -1,3 +1,4 @@ +#if canImport(CryptoKit) @testable import Blocks import XCTest @@ -12,3 +13,4 @@ final class PKCETests: XCTestCase { XCTAssertEqual(try pkceSeeds.codeChallenge(), "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM") } } +#endif diff --git a/Tests/BlocksTests/Security/SecurityErrorTests.swift b/Tests/BlocksTests/Security/SecurityErrorTests.swift index cedbaa2..2187390 100644 --- a/Tests/BlocksTests/Security/SecurityErrorTests.swift +++ b/Tests/BlocksTests/Security/SecurityErrorTests.swift @@ -1,3 +1,4 @@ +#if canImport(Security) @testable import Blocks import XCTest @@ -7,3 +8,4 @@ final class SecurityErrorTests: XCTestCase { XCTAssertEqual(sut.localizedDescription, "A keychain with the same name already exists.") } } +#endif diff --git a/Tests/BlocksTests/Security/SecurityUtilsTests.swift b/Tests/BlocksTests/Security/SecurityUtilsTests.swift index 71445ca..dd8b6a6 100644 --- a/Tests/BlocksTests/Security/SecurityUtilsTests.swift +++ b/Tests/BlocksTests/Security/SecurityUtilsTests.swift @@ -1,7 +1,8 @@ +#if canImport(Security) import Blocks import XCTest -final class PKCEUtilsTests: XCTestCase { +final class SecurityUtilsTests: XCTestCase { func testGenerateCryptographicallySecureRandomOctets() { measure { do { @@ -17,3 +18,4 @@ final class PKCEUtilsTests: XCTestCase { } } } +#endif diff --git a/Tests/BlocksTests/Transport/DummyURLRequest.swift b/Tests/BlocksTests/Transport/DummyURLRequest.swift index 809b544..41bdfb2 100644 --- a/Tests/BlocksTests/Transport/DummyURLRequest.swift +++ b/Tests/BlocksTests/Transport/DummyURLRequest.swift @@ -1,5 +1,8 @@ @testable import Blocks import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif struct DummyURLRequest { func create() throws -> URLRequest { diff --git a/Tests/BlocksTests/Transport/LoggingTransportTests.swift b/Tests/BlocksTests/Transport/LoggingTransportTests.swift index c75866d..16c77a3 100644 --- a/Tests/BlocksTests/Transport/LoggingTransportTests.swift +++ b/Tests/BlocksTests/Transport/LoggingTransportTests.swift @@ -1,3 +1,4 @@ +#if canImport(os) @testable import Blocks import XCTest @@ -18,3 +19,4 @@ final class LoggingTransportTests: XCTestCase { XCTAssertEqual(data, "Hello".data(using: .utf8)!) } } +#endif diff --git a/Tests/BlocksTests/Transport/StatusCodeCheckingTransportTests.swift b/Tests/BlocksTests/Transport/StatusCodeCheckingTransportTests.swift index b6b3677..7e06fae 100644 --- a/Tests/BlocksTests/Transport/StatusCodeCheckingTransportTests.swift +++ b/Tests/BlocksTests/Transport/StatusCodeCheckingTransportTests.swift @@ -1,6 +1,9 @@ @testable import Blocks import XCTest +#if os(Linux) +// Cannot use this test as `HTTPURLResponse` has no accessible initializers +#else @available(iOS 15.0.0, *) @available(macOS 12.0, *) final class StatusCodeCheckingTransportTests: XCTestCase { @@ -47,3 +50,4 @@ final class StatusCodeCheckingTransportTests: XCTestCase { XCTAssertEqual(sut.localizedDescription, "Unexpected HTTP status code: 200") } } +#endif diff --git a/Tests/BlocksTests/Transport/URLLoadingSystemErrorCodesTests.swift b/Tests/BlocksTests/Transport/URLLoadingSystemErrorCodesTests.swift index 8e32ef1..34d155a 100644 --- a/Tests/BlocksTests/Transport/URLLoadingSystemErrorCodesTests.swift +++ b/Tests/BlocksTests/Transport/URLLoadingSystemErrorCodesTests.swift @@ -1,63 +1,70 @@ import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif import XCTest final class URLLoadingSystemErrorCodesTests: XCTestCase { func testErrorCodes() { - dump(NSURLErrorUnknown) // -1 + XCTAssertEqual(NSURLErrorUnknown, -1) - dump(NSURLErrorCancelled) // -999 - dump(NSURLErrorBadURL) // -1000 - dump(NSURLErrorTimedOut) // -1001 - dump(NSURLErrorUnsupportedURL) // -1002 - dump(NSURLErrorCannotFindHost) // -1003 - dump(NSURLErrorCannotConnectToHost) // -1004 - dump(NSURLErrorNetworkConnectionLost) // -1005 - dump(NSURLErrorDNSLookupFailed) // -1006 - dump(NSURLErrorHTTPTooManyRedirects) // -1007 - dump(NSURLErrorResourceUnavailable) // -1008 - dump(NSURLErrorNotConnectedToInternet) // -1009 - dump(NSURLErrorRedirectToNonExistentLocation) // -1010 - dump(NSURLErrorBadServerResponse) // -1011 - dump(NSURLErrorUserCancelledAuthentication) // -1012 - dump(NSURLErrorUserAuthenticationRequired) // -1013 - dump(NSURLErrorZeroByteResource) // -1014 - dump(NSURLErrorCannotDecodeRawData) // -1015 - dump(NSURLErrorCannotDecodeContentData) // -1016 - dump(NSURLErrorCannotParseResponse) // -1017 - dump(NSURLErrorAppTransportSecurityRequiresSecureConnection) // -1022 - dump(NSURLErrorFileDoesNotExist) // -1100 - dump(NSURLErrorFileIsDirectory) // -1101 - dump(NSURLErrorNoPermissionsToReadFile) // -1102 - dump(NSURLErrorDataLengthExceedsMaximum) // -1103 + XCTAssertEqual(NSURLErrorCancelled, -999) + XCTAssertEqual(NSURLErrorBadURL, -1000) + XCTAssertEqual(NSURLErrorTimedOut, -1001) + XCTAssertEqual(NSURLErrorUnsupportedURL, -1002) + XCTAssertEqual(NSURLErrorCannotFindHost, -1003) + XCTAssertEqual(NSURLErrorCannotConnectToHost, -1004) + XCTAssertEqual(NSURLErrorNetworkConnectionLost, -1005) + XCTAssertEqual(NSURLErrorDNSLookupFailed, -1006) + XCTAssertEqual(NSURLErrorHTTPTooManyRedirects, -1007) + XCTAssertEqual(NSURLErrorResourceUnavailable, -1008) + XCTAssertEqual(NSURLErrorNotConnectedToInternet, -1009) + XCTAssertEqual(NSURLErrorRedirectToNonExistentLocation, -1010) + XCTAssertEqual(NSURLErrorBadServerResponse, -1011) + XCTAssertEqual(NSURLErrorUserCancelledAuthentication, -1012) + XCTAssertEqual(NSURLErrorUserAuthenticationRequired, -1013) + XCTAssertEqual(NSURLErrorZeroByteResource, -1014) + XCTAssertEqual(NSURLErrorCannotDecodeRawData, -1015) + XCTAssertEqual(NSURLErrorCannotDecodeContentData, -1016) + XCTAssertEqual(NSURLErrorCannotParseResponse, -1017) + XCTAssertEqual(NSURLErrorAppTransportSecurityRequiresSecureConnection, -1022) + XCTAssertEqual(NSURLErrorFileDoesNotExist, -1100) + XCTAssertEqual(NSURLErrorFileIsDirectory, -1101) + XCTAssertEqual(NSURLErrorNoPermissionsToReadFile, -1102) + XCTAssertEqual(NSURLErrorDataLengthExceedsMaximum, -1103) // SSL Errors - dump(NSURLErrorFileOutsideSafeArea) // -1104 - dump(NSURLErrorSecureConnectionFailed) // -1200 - dump(NSURLErrorServerCertificateHasBadDate) // -1201 - dump(NSURLErrorServerCertificateUntrusted) // -1202 - dump(NSURLErrorServerCertificateHasUnknownRoot) // -1203 - dump(NSURLErrorServerCertificateNotYetValid) // -1204 - dump(NSURLErrorClientCertificateRejected) // -1205 - dump(NSURLErrorClientCertificateRequired) // -1206 - dump(NSURLErrorCannotLoadFromNetwork) // -2000 + #if os(Linux) + // cannot find 'NSURLErrorFileOutsideSafeArea' in scope 🤷‍♂️ + #else + XCTAssertEqual(NSURLErrorFileOutsideSafeArea, -1104) + #endif + XCTAssertEqual(NSURLErrorSecureConnectionFailed, -1200) + XCTAssertEqual(NSURLErrorServerCertificateHasBadDate, -1201) + XCTAssertEqual(NSURLErrorServerCertificateUntrusted, -1202) + XCTAssertEqual(NSURLErrorServerCertificateHasUnknownRoot, -1203) + XCTAssertEqual(NSURLErrorServerCertificateNotYetValid, -1204) + XCTAssertEqual(NSURLErrorClientCertificateRejected, -1205) + XCTAssertEqual(NSURLErrorClientCertificateRequired, -1206) + XCTAssertEqual(NSURLErrorCannotLoadFromNetwork, -2000) // Download and file I/O errors - dump(NSURLErrorCannotCreateFile) // -3000 - dump(NSURLErrorCannotOpenFile) // -3001 - dump(NSURLErrorCannotCloseFile) // -3002 - dump(NSURLErrorCannotWriteToFile) // -3003 - dump(NSURLErrorCannotRemoveFile) // -3004 - dump(NSURLErrorCannotMoveFile) // -3005 - dump(NSURLErrorDownloadDecodingFailedMidStream) // -3006 - dump(NSURLErrorDownloadDecodingFailedToComplete) // -3007 + XCTAssertEqual(NSURLErrorCannotCreateFile, -3000) + XCTAssertEqual(NSURLErrorCannotOpenFile, -3001) + XCTAssertEqual(NSURLErrorCannotCloseFile, -3002) + XCTAssertEqual(NSURLErrorCannotWriteToFile, -3003) + XCTAssertEqual(NSURLErrorCannotRemoveFile, -3004) + XCTAssertEqual(NSURLErrorCannotMoveFile, -3005) + XCTAssertEqual(NSURLErrorDownloadDecodingFailedMidStream, -3006) + XCTAssertEqual(NSURLErrorDownloadDecodingFailedToComplete, -3007) - dump(NSURLErrorInternationalRoamingOff) // -1018 - dump(NSURLErrorCallIsActive) // -1019 - dump(NSURLErrorDataNotAllowed) // -1020 - dump(NSURLErrorRequestBodyStreamExhausted) // -1021 + XCTAssertEqual(NSURLErrorInternationalRoamingOff, -1018) + XCTAssertEqual(NSURLErrorCallIsActive, -1019) + XCTAssertEqual(NSURLErrorDataNotAllowed, -1020) + XCTAssertEqual(NSURLErrorRequestBodyStreamExhausted, -1021) - dump(NSURLErrorBackgroundSessionRequiresSharedContainer) // -995 - dump(NSURLErrorBackgroundSessionInUseByAnotherProcess) // -996 - dump(NSURLErrorBackgroundSessionWasDisconnected) // -997 + XCTAssertEqual(NSURLErrorBackgroundSessionRequiresSharedContainer, -995) + XCTAssertEqual(NSURLErrorBackgroundSessionInUseByAnotherProcess, -996) + XCTAssertEqual(NSURLErrorBackgroundSessionWasDisconnected, -997) } } diff --git a/Tests/BlocksTests/Transport/URLRequestHeaderItemTests.swift b/Tests/BlocksTests/Transport/URLRequestHeaderItemTests.swift index cbb8524..ed54428 100644 --- a/Tests/BlocksTests/Transport/URLRequestHeaderItemTests.swift +++ b/Tests/BlocksTests/Transport/URLRequestHeaderItemTests.swift @@ -1,4 +1,7 @@ import Blocks +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif import XCTest final class URLRequestHeaderItemTests: XCTestCase {