Closed nickasd closed 1 year ago
I just followed your instructions on how to run the tests and noticed that I still had to change the tests.
I don't know if I'm doing something wrong, but running bundle exec fastlane test
first gave an error
bundler: command not found: fastlane
Install missing gem executables with `bundle install`
But running bundle install
also wasn't sufficient. I had to add a line to Gemfile
:
gem "fastlane"
Then I was able to run the tests. But they fail in the Terminal:
xctest (95287) encountered an error (Failed to create a bundle instance representing 'appstoreconnect-swift-sdk/build/derived_data/Build/Products/Debug-iphonesimulator/AppStoreConnect-Swift-SDK-Tests.xctest'. Check that the bundle exists on disk. If you believe this error represents a bug, please attach the result bundle at appstoreconnect-swift-sdk/build/reports/AppStoreConnect-Swift-SDK.xcresult)
In fact, when opening appstoreconnect-swift-sdk/.swiftpm/xcode/package.xcworkspace
in Xcode and running the tests with Command-U
, I also get an error:
Logic Testing Unavailable Logic Testing on iOS devices is not supported. You can run logic tests on the Simulator.
I had to change the target to My Mac
and then the tests all passed. But I don't know what I have to do in order to be able to run the tests in the Terminal.
Warnings | |
---|---|
:warning: | 'Prices' is deprecated: Deprecated |
:warning: | 'AvailableTerritories' is deprecated: Deprecated |
:warning: | 'InAppPurchases' is deprecated: Deprecated |
:warning: | 'Prices' is deprecated: Deprecated |
:warning: | 'AvailableTerritories' is deprecated: Deprecated |
:warning: | 'InAppPurchases' is deprecated: Deprecated |
:warning: | 'Builds' is deprecated: Deprecated |
:warning: | 'Builds' is deprecated: Deprecated |
:warning: | 'AppPrice' is deprecated: Deprecated |
:warning: | 'AgeRatingDeclaration' is deprecated: Deprecated |
:warning: | 'AgeRatingDeclaration' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'AppStoreVersionSubmission' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'AppStoreVersionSubmission' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'Prices' is deprecated: Deprecated |
:warning: | 'AvailableTerritories' is deprecated: Deprecated |
:warning: | 'Prices' is deprecated: Deprecated |
:warning: | 'AvailableTerritories' is deprecated: Deprecated |
:warning: | 'AppPrice' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'Builds' is deprecated: Deprecated |
:warning: | 'AppStoreVersionSubmission' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'AppStoreVersionSubmission' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'Prices' is deprecated: Deprecated |
:warning: | 'AvailableTerritories' is deprecated: Deprecated |
:warning: | 'AppPrice' is deprecated: Deprecated |
:warning: | 'AgeRatingDeclaration' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'AppPrice' is deprecated: Deprecated |
:warning: | Left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used |
:warning: | 'Prices' is deprecated: Deprecated |
:warning: | 'AvailableTerritories' is deprecated: Deprecated |
:warning: | 'InAppPurchases' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
:warning: | 'AppStoreVersionExperiment' is deprecated: Deprecated |
Messages | |
---|---|
:book: | AppStoreConnect-Swift-SDK-Tests: Executed 17 tests (0 failed, 0 retried, 0 skipped) in 0.307 seconds |
:book: | View more details on Bitrise |
Name | Coverage |
---|
Severity | File | Reason |
---|---|---|
Warning | APIProviderTests.swift:13 | Colons should be next to the identifier when specifying a type and next to the key in dictionary literals (colon ) |
Warning | APIProviderTests.swift:43 | Method 'setUp()' should call to super function (overridden_super_call ) |
Warning | APIProviderTests.swift:9 | Imports should be sorted (sorted_imports ) |
Warning | APIProvider.swift:76 | Use shorthand syntax for optional binding (shorthand_optional_binding ) |
Warning | APIProvider.swift:138 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:244 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:274 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:295 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:312 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:322 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:338 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:351 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:362 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:372 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:380 | Lines should not have trailing whitespace (trailing_whitespace ) |
Warning | APIProvider.swift:106 | Parentheses are not needed when declaring closure arguments (unneeded_parentheses_in_closure_argument ) |
Generated by :no_entry_sign: Danger Swift against f171bc2ff5b599ecdb5f1812415ceed113dfad2d
Thanks a lot for your contribution! Unfortunately, I don't think this will solve the issue. It will make it impossible to run requests in parallel, which is a decrease in performance.
Thanks for checking. Are you sure that requests cannot run in parallel? I just tried changing ApiProvider.swift
by replacing this part
public func request<T>(_ endpoint: Request<T>) async throws -> T where T: Decodable {
try await withCheckedThrowingContinuation { continuation in
request(endpoint, completion: continuation.resume(with:))
}
}
with this
public func request<T>(_ endpoint: Request<T>) async throws -> T where T: Decodable {
return try await withCheckedThrowingContinuation { continuation in
print("start \(endpoint.path)")
request(endpoint) { result in
print("end \(endpoint.path)")
continuation.resume(with: result)
}
}
}
When running my app, which loads different resources at the same time, I get this output:
start /v1/apps/1516126920/appStoreVersions
end /v1/apps/1516126920/appStoreVersions
start /v1/appStoreVersions/a10abbf3-d8c1-41c5-b8d6-5584d6233aee/appStoreVersionLocalizations
start /v1/appStoreVersions/b7f6beb9-b1eb-4a4e-be81-1b8cbef43a27/appStoreVersionLocalizations
end /v1/appStoreVersions/b7f6beb9-b1eb-4a4e-be81-1b8cbef43a27/appStoreVersionLocalizations
start /v1/appStoreVersionLocalizations/d9b5cd20-5985-4173-a539-c5fd30486c9c/appPreviewSets
start /v1/appStoreVersionLocalizations/5d785f0d-3a6b-4239-b92c-0e6fc2c6b385/appPreviewSets
start /v1/appStoreVersionLocalizations/ddc0db09-6a40-4d1b-ad36-80d3b57b1333/appPreviewSets
start /v1/appStoreVersionLocalizations/52e7c3e9-0189-4aec-a3ca-02f9a2b375eb/appPreviewSets
start /v1/appStoreVersionLocalizations/6d90d4e0-2bc6-4403-ae8d-cc80850d87e4/appPreviewSets
end /v1/appStoreVersions/a10abbf3-d8c1-41c5-b8d6-5584d6233aee/appStoreVersionLocalizations
start /v1/appStoreVersionLocalizations/15e208e5-451a-4e88-9e1d-09cfb68bc416/appPreviewSets
start /v1/appStoreVersionLocalizations/1aa0bcda-4d55-4c87-8b5a-8d8582a1578d/appPreviewSets
start /v1/appStoreVersionLocalizations/54d2e544-6b35-47f5-b49a-a12694dd0a95/appPreviewSets
start /v1/appStoreVersionLocalizations/f24c988e-0551-4bfb-acee-7bc0968a40e7/appPreviewSets
start /v1/appStoreVersionLocalizations/326f5d17-97de-4a95-9b81-be06499dda6e/appPreviewSets
end /v1/appStoreVersionLocalizations/ddc0db09-6a40-4d1b-ad36-80d3b57b1333/appPreviewSets
end /v1/appStoreVersionLocalizations/6d90d4e0-2bc6-4403-ae8d-cc80850d87e4/appPreviewSets
end /v1/appStoreVersionLocalizations/52e7c3e9-0189-4aec-a3ca-02f9a2b375eb/appPreviewSets
end /v1/appStoreVersionLocalizations/15e208e5-451a-4e88-9e1d-09cfb68bc416/appPreviewSets
end /v1/appStoreVersionLocalizations/54d2e544-6b35-47f5-b49a-a12694dd0a95/appPreviewSets
end /v1/appStoreVersionLocalizations/d9b5cd20-5985-4173-a539-c5fd30486c9c/appPreviewSets
start /v1/appPreviewSets/2c2825e5-375f-4d8f-8664-0239f0552a87/appPreviews
end /v1/appStoreVersionLocalizations/5d785f0d-3a6b-4239-b92c-0e6fc2c6b385/appPreviewSets
end /v1/appStoreVersionLocalizations/f24c988e-0551-4bfb-acee-7bc0968a40e7/appPreviewSets
end /v1/appStoreVersionLocalizations/1aa0bcda-4d55-4c87-8b5a-8d8582a1578d/appPreviewSets
end /v1/appStoreVersionLocalizations/326f5d17-97de-4a95-9b81-be06499dda6e/appPreviewSets
end /v1/appPreviewSets/2c2825e5-375f-4d8f-8664-0239f0552a87/appPreviews
Isn't this a sign that requests run in parallel?
Thanks a lot for your contribution! Unfortunately, I don't think this will solve the issue. It will make it impossible to run requests in parallel, which is a decrease in performance.
Thanks for checking. Are you sure that requests cannot run in parallel? I just tried changing
ApiProvider.swift
by replacing this partpublic func request<T>(_ endpoint: Request<T>) async throws -> T where T: Decodable { try await withCheckedThrowingContinuation { continuation in request(endpoint, completion: continuation.resume(with:)) } }
with this
public func request<T>(_ endpoint: Request<T>) async throws -> T where T: Decodable { return try await withCheckedThrowingContinuation { continuation in print("start \(endpoint.path)") request(endpoint) { result in print("end \(endpoint.path)") continuation.resume(with: result) } } }
When running my app, which loads different resources at the same time, I get this output:
start /v1/apps/1516126920/appStoreVersions end /v1/apps/1516126920/appStoreVersions start /v1/appStoreVersions/a10abbf3-d8c1-41c5-b8d6-5584d6233aee/appStoreVersionLocalizations start /v1/appStoreVersions/b7f6beb9-b1eb-4a4e-be81-1b8cbef43a27/appStoreVersionLocalizations end /v1/appStoreVersions/b7f6beb9-b1eb-4a4e-be81-1b8cbef43a27/appStoreVersionLocalizations start /v1/appStoreVersionLocalizations/d9b5cd20-5985-4173-a539-c5fd30486c9c/appPreviewSets start /v1/appStoreVersionLocalizations/5d785f0d-3a6b-4239-b92c-0e6fc2c6b385/appPreviewSets start /v1/appStoreVersionLocalizations/ddc0db09-6a40-4d1b-ad36-80d3b57b1333/appPreviewSets start /v1/appStoreVersionLocalizations/52e7c3e9-0189-4aec-a3ca-02f9a2b375eb/appPreviewSets start /v1/appStoreVersionLocalizations/6d90d4e0-2bc6-4403-ae8d-cc80850d87e4/appPreviewSets end /v1/appStoreVersions/a10abbf3-d8c1-41c5-b8d6-5584d6233aee/appStoreVersionLocalizations start /v1/appStoreVersionLocalizations/15e208e5-451a-4e88-9e1d-09cfb68bc416/appPreviewSets start /v1/appStoreVersionLocalizations/1aa0bcda-4d55-4c87-8b5a-8d8582a1578d/appPreviewSets start /v1/appStoreVersionLocalizations/54d2e544-6b35-47f5-b49a-a12694dd0a95/appPreviewSets start /v1/appStoreVersionLocalizations/f24c988e-0551-4bfb-acee-7bc0968a40e7/appPreviewSets start /v1/appStoreVersionLocalizations/326f5d17-97de-4a95-9b81-be06499dda6e/appPreviewSets end /v1/appStoreVersionLocalizations/ddc0db09-6a40-4d1b-ad36-80d3b57b1333/appPreviewSets end /v1/appStoreVersionLocalizations/6d90d4e0-2bc6-4403-ae8d-cc80850d87e4/appPreviewSets end /v1/appStoreVersionLocalizations/52e7c3e9-0189-4aec-a3ca-02f9a2b375eb/appPreviewSets end /v1/appStoreVersionLocalizations/15e208e5-451a-4e88-9e1d-09cfb68bc416/appPreviewSets end /v1/appStoreVersionLocalizations/54d2e544-6b35-47f5-b49a-a12694dd0a95/appPreviewSets end /v1/appStoreVersionLocalizations/d9b5cd20-5985-4173-a539-c5fd30486c9c/appPreviewSets start /v1/appPreviewSets/2c2825e5-375f-4d8f-8664-0239f0552a87/appPreviews end /v1/appStoreVersionLocalizations/5d785f0d-3a6b-4239-b92c-0e6fc2c6b385/appPreviewSets end /v1/appStoreVersionLocalizations/f24c988e-0551-4bfb-acee-7bc0968a40e7/appPreviewSets end /v1/appStoreVersionLocalizations/1aa0bcda-4d55-4c87-8b5a-8d8582a1578d/appPreviewSets end /v1/appStoreVersionLocalizations/326f5d17-97de-4a95-9b81-be06499dda6e/appPreviewSets end /v1/appPreviewSets/2c2825e5-375f-4d8f-8664-0239f0552a87/appPreviews
Isn't this a sign that requests run in parallel?
Hi @nickasd 👋🏼 I'll chime in here. If ApiProvider is an actor and you make all the requests from a single ApiProvider instance I will expect them to be executed sequentially. Even if that's not the case I will prefer ApiProvider to not be an actor to continue support for non-async calls.
To follow @AvdLee's suggestion I think we can fix the underlying issue in JWTRequestsAuthenticator
with the following changes:
private let dispatchQueue = DispatchQueue(label: "JWTRequestsAuthenticator", attributes: .concurrent)
private func createToken() throws -> JWT.Token {
try dispatchQueue.sync(flags: .barrier) {
if let cachedToken = cachedToken, !cachedToken.isExpired {
return cachedToken
}
let token = try jwtCreator.signedToken(using: apiConfiguration.privateKey)
cachedToken = token
return token
}
}
I can make a PR to make this easier to read.
Let me know what you think 🙏🏼
Hey @mathiasemil, that should work as well. But why use a concurrent queue if you only submit barriers to it, and not use a standard serial queue?
I was just thinking, since what we want to protect here is concurrent read and write to the cachedToken
property, can't we instead assign cachedToken
once at the beginning, e.g. in apiConfiguration.didSet
?
Hey @mathiasemil, that should work as well. But why use a concurrent queue if you only submit barriers to it, and not use a standard serial queue?
I was just thinking, since what we want to protect here is concurrent read and write to the
cachedToken
property, can't we instead assigncachedToken
once at the beginning, e.g. inapiConfiguration.didSet
?
I guess in this case there is no reason to not use a serial queue instead. So that sounds like a better approach 👍🏼
I just realized now that it also checks for !cachedToken.isExpired
, so obviously the token cannot be created once at the beginning.
I'll update the PR.
Continued in #246.
Solves #238.