| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
Add More OSes to Testing Matrix (#3545) * Add older iOS testing targets. * Move old iOS and concurrency to Firebreak, make macOS a matrix. * Fix labeling, matrix value interpolation. * Don't fail matrices, canImport(Combine). * Run Xcode 12.5 on macOS 11. * canImport(Combine) in tests. * Avoid iOS 11 and 12 tests for now. * Enable all resource tests on SPM. * Fix Swift 5.3 test build. * Use Xcode 13.2 / Swift 5.5.2 for most tests. * Update tvOS and watchOS test versions. * Turn off thread sanitizer on tvOS as well. * Do all iOS tests in parallel. * Add test matrices for tvOS and watchOS too. * Fix iOS destination. | 4 年前 | |
More Atomic Locking (#3984) ### Issue Link :link: Attempts to fix #3978 ### Goals :soccer: This PR is a speculative attempt to fix the continuation resumption crash seen in #3978. However, I was unable to reproduce that issues, even with more complicated test cases and over 50 million test iterations. So this PR makes a few parts of `Request`'s state management more atomic, especially around response serializer handling. It also removes `@dynamicMemberLookup` from `Protected`, which should encourage more atomic usage. ### Implementation Details :construction: This PR attempts to unify what were separate lock access in the same flow into single accesses that accomplish the same thing. Behaviorally should be the same but may prevent any intermediate accesses to state that might cause this issue. ### Testing Details :mag: No new test scenarios, as no reproduction could be found. | 10 个月前 | |
Replace Some Platform Checks With canImport Checks (#3756) ### Issue Link :link: This PR replaces #3741. ### Goals :soccer: This PR builds on #3741 to replace many platform `#if os` checks with `#if canImport` for the relevant frameworks. --------- Co-authored-by: brennobemoura <37243584+brennobemoura@users.noreply.github.com> | 3 年前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Swift 6 Native Builds (#3880) ### Goals :soccer: This PR tracks the implementation of full concurrency checking when building in Swift 6 mode. It's unknown whether all of these changes will be fully backward compatible. ### Implementation Details :construction: This PR largely consists of `Sendable` annotations, with a few logic changes to fix actual safety issues. ### Testing Details :mag: Tests updated with needed annotations, but mutation warnings need a larger overall refactor. | 1 年前 | |
Update CI for GHA Limitations (#3973) ### Goals :soccer: This PR updates CI for all Xcode versions and GHA's limited sim availability. | 10 个月前 | |
Fix 2020 and 2021 Deprecation Warnings (#3555) * Fix deprecations on newer OSes. * Update formatting. * Add documentation note. * Add fallback for newer mime type code. * Expose newer APIs only when building for Xcode 13. | 4 年前 | |
Prevent Duplicate Serializer Completion Calls (#3999) ### Issue Link :link: Fixes #3978 ### Goals :soccer: This PR fixes the possible duplicate completion handler calls that cause #3978. Due to multiple paths into `processNextResponseSerializer()` there was a logical race where the same response serializer could be completed multiple times when cancelled, leading to a concurrency runtime crash due to resuming a continuation more than once. ### Implementation Details :construction: Additional state was added to track whether a `Request` had currently enqueued a serializer which is checked upon entering `processNextResponseSerializer()`, allowing it to return early if a serializer is in flight. This ensures that no matter how many times `processNextResponseSerializer()` is called, only one attempt will enqueue a particular serializer and, potentially, its completion. ### Testing Details :mag: Additional test added which could locally reproduce the issue. | 7 个月前 | |
Swift 6 Native Builds (#3880) ### Goals :soccer: This PR tracks the implementation of full concurrency checking when building in Swift 6 mode. It's unknown whether all of these changes will be fully backward compatible. ### Implementation Details :construction: This PR largely consists of `Sendable` annotations, with a few logic changes to fix actual safety issues. ### Testing Details :mag: Tests updated with needed annotations, but mutation warnings need a larger overall refactor. | 1 年前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Lazy Requests, per-Request Features (#3996) ### Issue Link :link: Closes #3992, other feature requests. ### Goals :soccer: This PR includes four major new features: 1. By default, all `Request` set up is now fully lazy and does not start until the instance is resumed, whether automatically or manually. Virtually all users should be unimpacted by this change, aside from seeing fewer race conditions. For those that do see issues, the previous behavior can be restored by passing `requestSetup: .eager` to the `Session.init`. 2. Speaking of `resume()`, automatic resume is now controllable on a per-`Request` basis using the `shouldAutomaticallyResumeParameter`. By default this is `nil` an obeys the `Session` setting. 3. You can now add a `RequestAdapter`, `RequestRetrier`, or `RequestInterceptor` after `Request.init`, like any other chained Alamofire API. This is what necessitated the lazy start change, as adapters added in this manner are racy with eager `Request`s and may miss the appropriate lifetime events. 4. In addition to the interceptors, you can now add a per-`Request` `EventMonitor` that is composed after the `Session`'s event monitor. ```swift // shouldAutomaticallyResume defaults to nil, obeying the Session's setting, which // defaults to true. let request = <session>.request(<urlRequest>, shouldAutomaticallyResume: true) .adapt(using: <adapter>) .retry(using: <retrier>) .interceptor(<interceptor>) .eventMonitor(<monitor>) // request is inert until resumed or a response handler (when automatic resume is enabled) // is added. let response = await request.serializingDecoding(<Type>.self).response ``` ### Implementation Details :construction: Actual changes were rather minimal for the impact these features have. 1. Simple stored interceptor and monitor are now stored in the mutable state and new instance methods have been added to provide those values. 2. Internally, the previous `perform` method has been split between eager and lazy variants, and a new `RequestDelegate` method has been added to start the request when needed (upon resume). 3. Interceptors and EventMonitors are now composed `Session`-first, to guarantee that `Request`s can override `Session` interceptor behavior. ### Testing Details :mag: Tests against very specific `Request` lifetime timing were updated to use an `eager` `Session`, to replicate the previous behavior. However, these tests are almost always inherently racy, which made them flaky in CI, so this sort of breaking behavioral change is more of a bug fix. Users could never really rely on these event orderings before, as `Request` start and the events themselves would race. Additional tests added to cover the new APIs, and some tests have been converted to Swift Testing for performance and ergonomics. Additionally, the test target deployment targets have been bumped again, as the testing frameworks technically only deploy back to macOS 14, etc. | 8 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Adopt Swift 5.1 (#3066) * Adopt 5.1 formatting. * Turn Protector into Protected property wrapper, add tests. * Update README for Swift 5.1 / Xcode 11 requirement. * Formatting. * Fix build after master merge. * Build fixes after master merge. * Add Catalyst testing. * Get Catalyst testing working. * Fix tests on unavailable platforms. * Version to 5.1.0. | 6 年前 | |
Require Swift 5.3 (#3495) * Update to Swift 5.3. * Use correct target. | 4 年前 | |
Refactored frameworks, tests and example app to compile against Swift 2.0. | 11 年前 | |
Prevent Duplicate Serializer Completion Calls (#3999) ### Issue Link :link: Fixes #3978 ### Goals :soccer: This PR fixes the possible duplicate completion handler calls that cause #3978. Due to multiple paths into `processNextResponseSerializer()` there was a logical race where the same response serializer could be completed multiple times when cancelled, leading to a concurrency runtime crash due to resuming a continuation more than once. ### Implementation Details :construction: Additional state was added to track whether a `Request` had currently enqueued a serializer which is checked upon entering `processNextResponseSerializer()`, allowing it to return early if a serializer is in flight. This ensures that no matter how many times `processNextResponseSerializer()` is called, only one attempt will enqueue a particular serializer and, potentially, its completion. ### Testing Details :mag: Additional test added which could locally reproduce the issue. | 7 个月前 | |
Swift 6 Native Builds (#3880) ### Goals :soccer: This PR tracks the implementation of full concurrency checking when building in Swift 6 mode. It's unknown whether all of these changes will be fully backward compatible. ### Implementation Details :construction: This PR largely consists of `Sendable` annotations, with a few logic changes to fix actual safety issues. ### Testing Details :mag: Tests updated with needed annotations, but mutation warnings need a larger overall refactor. | 1 年前 | |
Swift 6 Native Builds (#3880) ### Goals :soccer: This PR tracks the implementation of full concurrency checking when building in Swift 6 mode. It's unknown whether all of these changes will be fully backward compatible. ### Implementation Details :construction: This PR largely consists of `Sendable` annotations, with a few logic changes to fix actual safety issues. ### Testing Details :mag: Tests updated with needed annotations, but mutation warnings need a larger overall refactor. | 1 年前 | |
Lazy Requests, per-Request Features (#3996) ### Issue Link :link: Closes #3992, other feature requests. ### Goals :soccer: This PR includes four major new features: 1. By default, all `Request` set up is now fully lazy and does not start until the instance is resumed, whether automatically or manually. Virtually all users should be unimpacted by this change, aside from seeing fewer race conditions. For those that do see issues, the previous behavior can be restored by passing `requestSetup: .eager` to the `Session.init`. 2. Speaking of `resume()`, automatic resume is now controllable on a per-`Request` basis using the `shouldAutomaticallyResumeParameter`. By default this is `nil` an obeys the `Session` setting. 3. You can now add a `RequestAdapter`, `RequestRetrier`, or `RequestInterceptor` after `Request.init`, like any other chained Alamofire API. This is what necessitated the lazy start change, as adapters added in this manner are racy with eager `Request`s and may miss the appropriate lifetime events. 4. In addition to the interceptors, you can now add a per-`Request` `EventMonitor` that is composed after the `Session`'s event monitor. ```swift // shouldAutomaticallyResume defaults to nil, obeying the Session's setting, which // defaults to true. let request = <session>.request(<urlRequest>, shouldAutomaticallyResume: true) .adapt(using: <adapter>) .retry(using: <retrier>) .interceptor(<interceptor>) .eventMonitor(<monitor>) // request is inert until resumed or a response handler (when automatic resume is enabled) // is added. let response = await request.serializingDecoding(<Type>.self).response ``` ### Implementation Details :construction: Actual changes were rather minimal for the impact these features have. 1. Simple stored interceptor and monitor are now stored in the mutable state and new instance methods have been added to provide those values. 2. Internally, the previous `perform` method has been split between eager and lazy variants, and a new `RequestDelegate` method has been added to start the request when needed (upon resume). 3. Interceptors and EventMonitors are now composed `Session`-first, to guarantee that `Request`s can override `Session` interceptor behavior. ### Testing Details :mag: Tests against very specific `Request` lifetime timing were updated to use an `eager` `Session`, to replicate the previous behavior. However, these tests are almost always inherently racy, which made them flaky in CI, so this sort of breaking behavioral change is more of a bug fix. Users could never really rely on these event orderings before, as `Request` start and the events themselves would race. Additional tests added to cover the new APIs, and some tests have been converted to Swift Testing for performance and ergonomics. Additionally, the test target deployment targets have been bumped again, as the testing frameworks technically only deploy back to macOS 14, etc. | 8 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Prevent Duplicate Serializer Completion Calls (#3999) ### Issue Link :link: Fixes #3978 ### Goals :soccer: This PR fixes the possible duplicate completion handler calls that cause #3978. Due to multiple paths into `processNextResponseSerializer()` there was a logical race where the same response serializer could be completed multiple times when cancelled, leading to a concurrency runtime crash due to resuming a continuation more than once. ### Implementation Details :construction: Additional state was added to track whether a `Request` had currently enqueued a serializer which is checked upon entering `processNextResponseSerializer()`, allowing it to return early if a serializer is in flight. This ensures that no matter how many times `processNextResponseSerializer()` is called, only one attempt will enqueue a particular serializer and, potentially, its completion. ### Testing Details :mag: Additional test added which could locally reproduce the issue. | 7 个月前 | |
Lazy Requests, per-Request Features (#3996) ### Issue Link :link: Closes #3992, other feature requests. ### Goals :soccer: This PR includes four major new features: 1. By default, all `Request` set up is now fully lazy and does not start until the instance is resumed, whether automatically or manually. Virtually all users should be unimpacted by this change, aside from seeing fewer race conditions. For those that do see issues, the previous behavior can be restored by passing `requestSetup: .eager` to the `Session.init`. 2. Speaking of `resume()`, automatic resume is now controllable on a per-`Request` basis using the `shouldAutomaticallyResumeParameter`. By default this is `nil` an obeys the `Session` setting. 3. You can now add a `RequestAdapter`, `RequestRetrier`, or `RequestInterceptor` after `Request.init`, like any other chained Alamofire API. This is what necessitated the lazy start change, as adapters added in this manner are racy with eager `Request`s and may miss the appropriate lifetime events. 4. In addition to the interceptors, you can now add a per-`Request` `EventMonitor` that is composed after the `Session`'s event monitor. ```swift // shouldAutomaticallyResume defaults to nil, obeying the Session's setting, which // defaults to true. let request = <session>.request(<urlRequest>, shouldAutomaticallyResume: true) .adapt(using: <adapter>) .retry(using: <retrier>) .interceptor(<interceptor>) .eventMonitor(<monitor>) // request is inert until resumed or a response handler (when automatic resume is enabled) // is added. let response = await request.serializingDecoding(<Type>.self).response ``` ### Implementation Details :construction: Actual changes were rather minimal for the impact these features have. 1. Simple stored interceptor and monitor are now stored in the mutable state and new instance methods have been added to provide those values. 2. Internally, the previous `perform` method has been split between eager and lazy variants, and a new `RequestDelegate` method has been added to start the request when needed (upon resume). 3. Interceptors and EventMonitors are now composed `Session`-first, to guarantee that `Request`s can override `Session` interceptor behavior. ### Testing Details :mag: Tests against very specific `Request` lifetime timing were updated to use an `eager` `Session`, to replicate the previous behavior. However, these tests are almost always inherently racy, which made them flaky in CI, so this sort of breaking behavioral change is more of a bug fix. Users could never really rely on these event orderings before, as `Request` start and the events themselves would race. Additional tests added to cover the new APIs, and some tests have been converted to Swift Testing for performance and ergonomics. Additionally, the test target deployment targets have been bumped again, as the testing frameworks technically only deploy back to macOS 14, etc. | 8 个月前 | |
Deprecate `NetworkReachabilityManager` (#3947) ### Issue Link :link: Fixes #3943 ### Goals :soccer: Apple's `SCNetworkReachability` types were deprecated in iOS 17.4 related OS versions. This PR deprecates `NetworkReachabilityManager` in favor of `NWPathMonitor` from Network.framework, which has been the better solution for many years now. This PR also updates various infrastructure bits, and deletes the `.swiftpm` directory to prevent Xcode from generating schemes when integrating the package. ### Implementation Details :construction: Class deprecated. ### Testing Details :mag: Tests deprecated. | 10 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Fix existential-any for Swift6 (#3881) ### Goals :soccer: Resolve `existential-any` build errors. ### Implementation Details :construction: Added `any` to each protocols. https://github.com/swiftlang/swift-evolution/blob/main/proposals/0335-existential-any.md Co-authored-by: Jon Shier <jon@jonshier.com> | 1 年前 | |
Prepare 5.7 (#3718) ### Goals :soccer: This PR prepares the 5.7 release. | 3 年前 | |
Prevent Duplicate Serializer Completion Calls (#3999) ### Issue Link :link: Fixes #3978 ### Goals :soccer: This PR fixes the possible duplicate completion handler calls that cause #3978. Due to multiple paths into `processNextResponseSerializer()` there was a logical race where the same response serializer could be completed multiple times when cancelled, leading to a concurrency runtime crash due to resuming a continuation more than once. ### Implementation Details :construction: Additional state was added to track whether a `Request` had currently enqueued a serializer which is checked upon entering `processNextResponseSerializer()`, allowing it to return early if a serializer is in flight. This ensures that no matter how many times `processNextResponseSerializer()` is called, only one attempt will enqueue a particular serializer and, potentially, its completion. ### Testing Details :mag: Additional test added which could locally reproduce the issue. | 7 个月前 | |
Swift 6 Native Builds (#3880) ### Goals :soccer: This PR tracks the implementation of full concurrency checking when building in Swift 6 mode. It's unknown whether all of these changes will be fully backward compatible. ### Implementation Details :construction: This PR largely consists of `Sendable` annotations, with a few logic changes to fix actual safety issues. ### Testing Details :mag: Tests updated with needed annotations, but mutation warnings need a larger overall refactor. | 1 年前 | |
Fix 2020 and 2021 Deprecation Warnings (#3555) * Fix deprecations on newer OSes. * Update formatting. * Add documentation note. * Add fallback for newer mime type code. * Expose newer APIs only when building for Xcode 13. | 4 年前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Improve Test Reliability in AuthenticationInterceptorTests (#3551) * Store Session. * Use the same queue for the monitor and Session. * Move credential set to validator. * Make tests more reliable, avoid GHA censoring. * Turn off iOS 11 / tvOS 11 tests. * Fully remove older OS testing. * Turn off thread sanitizer on old tvOS. | 4 年前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Prevent Duplicate Serializer Completion Calls (#3999) ### Issue Link :link: Fixes #3978 ### Goals :soccer: This PR fixes the possible duplicate completion handler calls that cause #3978. Due to multiple paths into `processNextResponseSerializer()` there was a logical race where the same response serializer could be completed multiple times when cancelled, leading to a concurrency runtime crash due to resuming a continuation more than once. ### Implementation Details :construction: Additional state was added to track whether a `Request` had currently enqueued a serializer which is checked upon entering `processNextResponseSerializer()`, allowing it to return early if a serializer is in flight. This ensures that no matter how many times `processNextResponseSerializer()` is called, only one attempt will enqueue a particular serializer and, potentially, its completion. ### Testing Details :mag: Additional test added which could locally reproduce the issue. | 7 个月前 | |
Swift 6 Native Builds (#3880) ### Goals :soccer: This PR tracks the implementation of full concurrency checking when building in Swift 6 mode. It's unknown whether all of these changes will be fully backward compatible. ### Implementation Details :construction: This PR largely consists of `Sendable` annotations, with a few logic changes to fix actual safety issues. ### Testing Details :mag: Tests updated with needed annotations, but mutation warnings need a larger overall refactor. | 1 年前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 | |
Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 4 年前 | ||
| 10 个月前 | ||
| 3 年前 | ||
| 4 个月前 | ||
| 1 年前 | ||
| 10 个月前 | ||
| 4 年前 | ||
| 7 个月前 | ||
| 1 年前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 8 个月前 | ||
| 4 个月前 | ||
| 6 年前 | ||
| 4 年前 | ||
| 11 年前 | ||
| 7 个月前 | ||
| 1 年前 | ||
| 1 年前 | ||
| 8 个月前 | ||
| 4 个月前 | ||
| 7 个月前 | ||
| 8 个月前 | ||
| 10 个月前 | ||
| 4 个月前 | ||
| 1 年前 | ||
| 3 年前 | ||
| 7 个月前 | ||
| 1 年前 | ||
| 4 年前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 年前 | ||
| 4 个月前 | ||
| 7 个月前 | ||
| 1 年前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 个月前 |