diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 881c9b8c..2c85b5c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: runs-on: macOS-11 steps: - name: Checkout Repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Bundle Install run: bundle install - name: Select Xcode Version @@ -24,7 +24,7 @@ jobs: runs-on: macOS-11 steps: - name: Checkout Repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Bundle Install run: bundle install - name: Select Xcode Version @@ -45,7 +45,7 @@ jobs: fail-fast: false steps: - name: Checkout Repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Bundle Install run: bundle install - name: Select Xcode Version @@ -54,9 +54,6 @@ jobs: run: Scripts/github/prepare-simulators.sh ${{ matrix.platforms }} - name: Build and Test Framework run: Scripts/build.swift ${{ matrix.platforms }} - - name: Upload Coverage Reports - if: success() - run: Scripts/upload-coverage-reports.sh ${{ matrix.platforms }} spm-12: name: Build Xcode 12 runs-on: macOS-11 @@ -69,7 +66,7 @@ jobs: fail-fast: false steps: - name: Checkout Repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Bundle Install run: bundle install - name: Select Xcode Version @@ -78,9 +75,6 @@ jobs: run: Scripts/github/prepare-simulators.sh ${{ matrix.platforms }} - name: Build and Test Framework run: Scripts/build.swift ${{ matrix.platforms }} - - name: Upload Coverage Reports - if: success() - run: Scripts/upload-coverage-reports.sh ${{ matrix.platforms }} spm-13: name: Build Xcode 13 runs-on: macOS-12 @@ -93,7 +87,7 @@ jobs: fail-fast: false steps: - name: Checkout Repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Bundle Install run: bundle install - name: Select Xcode Version @@ -102,15 +96,17 @@ jobs: run: Scripts/github/prepare-simulators.sh ${{ matrix.platforms }} - name: Build and Test Framework run: Scripts/build.swift ${{ matrix.platforms }} + - name: Prepare Coverage Reports + run: ./Scripts/prepare-coverage-reports.sh - name: Upload Coverage Reports if: success() - run: Scripts/upload-coverage-reports.sh ${{ matrix.platforms }} + uses: codecov/codecov-action@v3 spm-13-swift: name: Swift Build Xcode 13 runs-on: macOS-12 steps: - name: Checkout Repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Bundle Install run: bundle install - name: Select Xcode Version diff --git a/Scripts/prepare-coverage-reports.sh b/Scripts/prepare-coverage-reports.sh new file mode 100755 index 00000000..4cacb22a --- /dev/null +++ b/Scripts/prepare-coverage-reports.sh @@ -0,0 +1,35 @@ +#!/bin/zsh -l +set -e + +function exportlcov() { + build_type=$1 + executable_name=$2 + + executable=$(find "${directory}" -type f -name $executable_name) + profile=$(find "${directory}" -type f -name 'Coverage.profdata') + output_file_name="$executable_name.lcov" + + can_proceed=true + if [[ $build_type == watchOS* ]]; then + echo "\tAborting creation of $output_file_name – watchOS not supported." + elif [[ -z $profile ]]; then + echo "\tAborting creation of $output_file_name – no profile found." + elif [[ -z $executable ]]; then + echo "\tAborting creation of $output_file_name – no executable found." + else + output_dir=".build/artifacts/$build_type" + mkdir -p $output_dir + + output_file="$output_dir/$output_file_name" + echo "\tExporting $output_file" + xcrun llvm-cov export -format="lcov" $executable -instr-profile $profile > $output_file + fi +} + +for directory in $(git rev-parse --show-toplevel)/.build/derivedData/*/; do + build_type=$(basename $directory) + echo "Finding coverage information for $build_type" + + exportlcov $build_type 'CacheAdvanceTests' + exportlcov $build_type 'CADCacheAdvanceTests' +done diff --git a/Scripts/upload-coverage-reports.sh b/Scripts/upload-coverage-reports.sh deleted file mode 100755 index f2d55ef3..00000000 --- a/Scripts/upload-coverage-reports.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -l -set -ex - -IFS=','; PLATFORMS=$(echo $1); unset IFS - -for PLATFORM in $PLATFORMS; do - bash <(curl -s https://codecov.io/bash) -J '^CacheAdvance(.framework)?$' -D .build/derivedData/$PLATFORM -t 8344b011-6b2a-4b3d-a573-eaf49684318e - bash <(curl -s https://codecov.io/bash) -J '^CADCacheAdvance(.framework)?$' -D .build/derivedData/$PLATFORM -t 8344b011-6b2a-4b3d-a573-eaf49684318e -done diff --git a/Sources/CADCacheAdvance/CADCacheAdvance.swift b/Sources/CADCacheAdvance/CADCacheAdvance.swift index ff644d01..db69f110 100644 --- a/Sources/CADCacheAdvance/CADCacheAdvance.swift +++ b/Sources/CADCacheAdvance/CADCacheAdvance.swift @@ -98,30 +98,17 @@ public final class __ObjectiveCCompatibleCacheAdvanceWithGenericData: NSObject { /// A decoder that treats all messages as if they are `Data`. final class PassthroughDataDecoder: MessageDecoder { func decode(_ type: T.Type, from data: Data) throws -> T where T : Decodable { - if let data = data as? T { - return data - } else { - throw DecodingError.dataCorrupted( - DecodingError.Context( - codingPath: [], - debugDescription: "Type was not Data")) - } + // Force cast because this type is only used with a CacheAdvance type. + return data as! T } } -// MARK: - PassthroughDataDecoder +// MARK: - PassthroughDataEncoder /// A encoder that treats all messages as if they are `Data`. final class PassthroughDataEncoder: MessageEncoder { func encode(_ value: T) throws -> Data where T : Encodable { - if let value = value as? Data { - return value - } else { - throw EncodingError.invalidValue( - value, - EncodingError.Context( - codingPath: [], - debugDescription: "Value was not Data")) - } + // Force cast because this type is only used with a CacheAdvance type. + return value as! Data } } diff --git a/Sources/CacheAdvance/BigEndianHostSwappable.swift b/Sources/CacheAdvance/BigEndianHostSwappable.swift index bcb19423..a27b784e 100644 --- a/Sources/CacheAdvance/BigEndianHostSwappable.swift +++ b/Sources/CacheAdvance/BigEndianHostSwappable.swift @@ -23,6 +23,9 @@ protocol BigEndianHostSwappable where Self: FixedWidthInteger { /// Converts the big-endian value in x to the current endian format and returns the resulting value. static func swapToHost(_ x: Self) -> Self + /// The maximum representable integer in this type. + static var max: Self { get } + } extension BigEndianHostSwappable { diff --git a/Sources/CacheAdvance/CacheAdvance.swift b/Sources/CacheAdvance/CacheAdvance.swift index c4557032..5b7603ce 100644 --- a/Sources/CacheAdvance/CacheAdvance.swift +++ b/Sources/CacheAdvance/CacheAdvance.swift @@ -97,7 +97,7 @@ public final class CacheAdvance { throw CacheAdvanceError.fileNotWritable } - let encodableMessage = EncodableMessage(message: message, encoder: encoder) + let encodableMessage = EncodableMessage(message: message, encoder: encoder) let messageData = try encodableMessage.encodedData() let bytesNeededToStoreMessage = Bytes(messageData.count) diff --git a/Sources/CacheAdvance/EncodableMessage.swift b/Sources/CacheAdvance/EncodableMessage.swift index e588a568..faf042c5 100644 --- a/Sources/CacheAdvance/EncodableMessage.swift +++ b/Sources/CacheAdvance/EncodableMessage.swift @@ -22,7 +22,7 @@ import Foundation /// `[messageSize][data]` /// - `messageSize` is a big-endian encoded `MessageSpan` of length `messageSpanStorageLength`. /// - `data` is length `messageSize`. -struct EncodableMessage { +struct EncodableMessage { // MARK: Initialization @@ -40,7 +40,7 @@ struct EncodableMessage { /// The encoded message, prefixed with the size of the message blob. func encodedData() throws -> Data { let messageData = try encoder.encode(message) - guard messageData.count < MessageSpan.max else { + guard messageData.count < Size.max else { // We can't encode the length this message in a MessageSpan. throw CacheAdvanceError.messageLargerThanCacheCapacity } diff --git a/Sources/SwiftTryCatch/SwiftTryCatch.h b/Sources/SwiftTryCatch/SwiftTryCatch.h index 6dedfe9e..875f8b7f 100644 --- a/Sources/SwiftTryCatch/SwiftTryCatch.h +++ b/Sources/SwiftTryCatch/SwiftTryCatch.h @@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN Provides try catch functionality for swift by wrapping around Objective-C */ -+ (void)try:(__attribute__((noescape)) void(^ _Nonnull)(void))try catch:(__attribute__((noescape)) void(^ _Nonnull)(NSException *exception))catch finally:(__attribute__((noescape)) void(^ _Nullable)(void))finally; ++ (void)try:(__attribute__((noescape)) void(^ _Nonnull)(void))try catch:(__attribute__((noescape)) void(^ _Nonnull)(NSException *exception))catch; @end NS_ASSUME_NONNULL_END diff --git a/Sources/SwiftTryCatch/SwiftTryCatch.m b/Sources/SwiftTryCatch/SwiftTryCatch.m index ba43466a..4cb0bccb 100644 --- a/Sources/SwiftTryCatch/SwiftTryCatch.m +++ b/Sources/SwiftTryCatch/SwiftTryCatch.m @@ -24,7 +24,7 @@ @implementation SwiftTryCatch /** Provides try catch functionality for swift by wrapping around Objective-C */ -+ (void)try:(__attribute__((noescape)) void(^ _Nonnull)(void))try catch:(__attribute__((noescape)) void(^ _Nonnull)(NSException *exception))catch finally:(__attribute__((noescape)) void(^ _Nullable)(void))finally; ++ (void)try:(__attribute__((noescape)) void(^ _Nonnull)(void))try catch:(__attribute__((noescape)) void(^ _Nonnull)(NSException *exception))catch; { @try { try(); @@ -32,11 +32,6 @@ + (void)try:(__attribute__((noescape)) void(^ _Nonnull)(void))try catch:(__attri @catch (NSException *exception) { catch(exception); } - @finally { - if (finally != NULL) { - finally(); - } - } } @end diff --git a/Tests/CacheAdvanceTests/CacheAdvanceTests.swift b/Tests/CacheAdvanceTests/CacheAdvanceTests.swift index 72797d97..b1470793 100644 --- a/Tests/CacheAdvanceTests/CacheAdvanceTests.swift +++ b/Tests/CacheAdvanceTests/CacheAdvanceTests.swift @@ -588,7 +588,7 @@ final class CacheAdvanceTests: XCTestCase { let encoder = JSONEncoder() return try FileHeader.expectedEndOfHeaderInFile + messages.reduce(0) { allocatedSize, message in - let encodableMessage = EncodableMessage(message: message, encoder: encoder) + let encodableMessage = EncodableMessage(message: message, encoder: encoder) let data = try encodableMessage.encodedData() return allocatedSize + UInt64(data.count) } diff --git a/Tests/CacheAdvanceTests/EncodableMessageTests.swift b/Tests/CacheAdvanceTests/EncodableMessageTests.swift index 87d7a843..ed1b8a91 100644 --- a/Tests/CacheAdvanceTests/EncodableMessageTests.swift +++ b/Tests/CacheAdvanceTests/EncodableMessageTests.swift @@ -27,7 +27,7 @@ final class EncodableMessageTests: XCTestCase { func test_encodedData_encodesCorrectSize() throws { let message = TestableMessage("This is a test") let data = try encoder.encode(message) - let encodedMessage = EncodableMessage(message: message, encoder: encoder) + let encodedMessage = EncodableMessage(message: message, encoder: encoder) let encodedData = try encodedMessage.encodedData() let prefix = encodedData.subdata(in: 0..(message: message, encoder: encoder) + let encodedMessage = EncodableMessage(message: message, encoder: encoder) let encodedData = try encodedMessage.encodedData() XCTAssertEqual(encodedData.count, data.count + MessageSpan.storageLength) } @@ -45,11 +45,16 @@ final class EncodableMessageTests: XCTestCase { func test_encodedData_hasDataPostfix() throws { let message = TestableMessage("This is a test") let data = try encoder.encode(message) - let encodedMessage = EncodableMessage(message: message, encoder: encoder) + let encodedMessage = EncodableMessage(message: message, encoder: encoder) let encodedData = try encodedMessage.encodedData() XCTAssertEqual(encodedData.advanced(by: MessageSpan.storageLength), data) } + func test_encodedData_whenMessageDataTooLarge_throwsError() throws { + let encodedMessage = EncodableMessage(message: Data(count: Int(UInt8.max)), encoder: encoder) + XCTAssertThrowsError(try encodedMessage.encodedData()) + } + // MARK: Private private let encoder = JSONEncoder() diff --git a/codecov.yml b/codecov.yml index a8e8790a..3b85da4f 100644 --- a/codecov.yml +++ b/codecov.yml @@ -5,3 +5,14 @@ comment: layout: "reach,diff,flags,tree" behavior: default require_changes: no + +coverage: + status: + project: + default: + threshold: 0.25% + patch: off + +ignore: + - "Sources/LorumIpsum" + - "Tests"