Skip to content

Commit fc5cbee

Browse files
Infrastructure: Address concurrency warnings in tests (#3438)
* Infrastructure: Address concurrency warnings in tests * wip --------- Co-authored-by: Brandon Williams <[email protected]>
1 parent f43a154 commit fc5cbee

14 files changed

+76
-43
lines changed

Sources/ComposableArchitecture/Effect.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import Combine
1+
@preconcurrency import Combine
22
import Foundation
33
import SwiftUI
44

5-
public struct Effect<Action> {
5+
public struct Effect<Action>: Sendable {
66
@usableFromInline
7-
enum Operation {
7+
enum Operation: Sendable {
88
case none
99
case publisher(AnyPublisher<Action, Never>)
1010
case run(TaskPriority? = nil, @Sendable (_ send: Send<Action>) async -> Void)

Tests/ComposableArchitectureTests/BindingLocalTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
@testable import ComposableArchitecture
55

66
final class BindingLocalTests: BaseTCATestCase {
7+
@MainActor
78
public func testBindingLocalIsActive() {
89
XCTAssertFalse(BindingLocal.isActive)
910

Tests/ComposableArchitectureTests/CompatibilityTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ final class CompatibilityTests: BaseTCATestCase {
66
// Actions can be re-entrantly sent into the store if an action is sent that holds an object
77
// which sends an action on deinit. In order to prevent a simultaneous access exception for this
88
// case we need to use `withExtendedLifetime` on the buffered actions when clearing them out.
9+
@MainActor
910
func testCaseStudy_ActionReentranceFromClearedBufferCausingDeinitAction() {
1011
let cancelID = UUID()
1112

@@ -78,6 +79,7 @@ final class CompatibilityTests: BaseTCATestCase {
7879
// In particular, this means that in the implementation of `Store.send` we need to flip
7980
// `isSending` to false _after_ the store's state mutation is made so that re-entrant actions
8081
// are buffered rather than immediately handled.
82+
@MainActor
8183
func testCaseStudy_ActionReentranceFromStateObservation() {
8284
var cancellables: Set<AnyCancellable> = []
8385
defer { _ = cancellables }

Tests/ComposableArchitectureTests/CurrentValueRelayTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
await withTaskGroup(of: Void.self) { group in
1717
for index in 1...1_000 {
18-
group.addTask {
18+
group.addTask { @Sendable in
1919
subject.send(index)
2020
}
2121
}

Tests/ComposableArchitectureTests/EffectTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ final class EffectTests: BaseTCATestCase {
4747
}
4848

4949
func testConcatenateOneEffect() async {
50-
await withMainSerialExecutor {
50+
await withMainSerialExecutor { [mainQueue] in
5151
let values = LockIsolated<[Int]>([])
5252

5353
let effect = Effect<Int>.concatenate(
54-
.publisher { Just(1).delay(for: 1, scheduler: self.mainQueue) }
54+
.publisher { Just(1).delay(for: 1, scheduler: mainQueue) }
5555
)
5656

5757
let task = Task {
@@ -62,10 +62,10 @@ final class EffectTests: BaseTCATestCase {
6262

6363
XCTAssertEqual(values.value, [])
6464

65-
await self.mainQueue.advance(by: 1)
65+
await mainQueue.advance(by: 1)
6666
XCTAssertEqual(values.value, [1])
6767

68-
await self.mainQueue.run()
68+
await mainQueue.run()
6969
XCTAssertEqual(values.value, [1])
7070

7171
await task.value

Tests/ComposableArchitectureTests/Reducers/BindingReducerTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ final class BindingTests: BaseTCATestCase {
4747
)
4848
}
4949

50+
@MainActor
5051
func testViewEquality() {
5152
struct Feature: Reducer {
5253
struct State: Equatable {

Tests/ComposableArchitectureTests/ScopeCacheTests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ final class ScopeCacheTests: BaseTCATestCase {
3535
store.send(.child(.dismiss))
3636
}
3737

38+
@MainActor
3839
func testOptionalScope_CachedStore() {
3940
#if DEBUG
4041
let store = StoreOf<Feature>(initialState: Feature.State(child: Feature.State())) {
@@ -46,6 +47,7 @@ final class ScopeCacheTests: BaseTCATestCase {
4647
#endif
4748
}
4849

50+
@MainActor
4951
func testOptionalScope_StoreIfLet() {
5052
#if DEBUG
5153
let store = StoreOf<Feature>(initialState: Feature.State(child: Feature.State())) {
@@ -62,6 +64,7 @@ final class ScopeCacheTests: BaseTCATestCase {
6264
}
6365

6466
@available(*, deprecated)
67+
@MainActor
6568
func testOptionalScope_StoreIfLet_UncachedStore() {
6669
let store = StoreOf<Feature>(initialState: Feature.State(child: Feature.State())) {
6770
}
@@ -93,6 +96,7 @@ final class ScopeCacheTests: BaseTCATestCase {
9396
}
9497
}
9598

99+
@MainActor
96100
func testIdentifiedArrayScope_CachedStore() {
97101
#if DEBUG
98102
let store = StoreOf<Feature>(initialState: Feature.State(rows: [Feature.State()])) {
@@ -108,6 +112,7 @@ final class ScopeCacheTests: BaseTCATestCase {
108112
}
109113

110114
@available(*, deprecated)
115+
@MainActor
111116
func testIdentifiedArrayScope_UncachedStore() {
112117
let store = StoreOf<Feature>(initialState: Feature.State(rows: [Feature.State()])) {
113118
Feature()

Tests/ComposableArchitectureTests/SharedTests.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,11 @@ final class SharedTests: XCTestCase {
9696
XCTAssertEqual(store.state.sharedCount, 2)
9797
}
9898

99+
@MainActor
99100
func testMultiSharing() async {
100101
@Shared(Stats()) var stats
101102

102-
let store = await TestStore(
103+
let store = TestStore(
103104
initialState: SharedFeature.State(
104105
profile: Shared(Profile(stats: $stats)),
105106
sharedCount: Shared(0),
@@ -721,7 +722,7 @@ final class SharedTests: XCTestCase {
721722

722723
func testSharedDefaults_Used() {
723724
let didAccess = LockIsolated(false)
724-
let logDefault: () -> Bool = {
725+
let logDefault: @Sendable () -> Bool = {
725726
didAccess.setValue(true)
726727
return true
727728
}
@@ -732,7 +733,7 @@ final class SharedTests: XCTestCase {
732733

733734
func testSharedDefaults_Unused() {
734735
let didAccess = LockIsolated(false)
735-
let logDefault: () -> Bool = {
736+
let logDefault: @Sendable () -> Bool = {
736737
didAccess.setValue(true)
737738
return true
738739
}
@@ -761,7 +762,7 @@ final class SharedTests: XCTestCase {
761762
func testSharedOverrideDefault() {
762763
let accessedActive1 = LockIsolated(false)
763764
let accessedDefault = LockIsolated(false)
764-
let logDefault: () -> Bool = {
765+
let logDefault: @Sendable () -> Bool = {
765766
accessedDefault.setValue(true)
766767
return true
767768
}
@@ -796,7 +797,7 @@ final class SharedTests: XCTestCase {
796797
func testSharedReaderOverrideDefault() {
797798
let accessedActive1 = LockIsolated(false)
798799
let accessedDefault = LockIsolated(false)
799-
let logDefault: () -> Bool = {
800+
let logDefault: @Sendable () -> Bool = {
800801
accessedDefault.setValue(true)
801802
return true
802803
}
@@ -1141,7 +1142,7 @@ private struct SimpleFeature {
11411142
}
11421143

11431144
@Perceptible
1144-
class SharedObject {
1145+
class SharedObject: @unchecked Sendable {
11451146
var count = 0
11461147
}
11471148

@@ -1244,7 +1245,7 @@ extension PersistenceReaderKey where Self == PersistenceKeyDefault<AppStorageKey
12441245
PersistenceKeyDefault(.appStorage("isOn"), false)
12451246
}
12461247

1247-
static func isActive(default keyDefault: @escaping () -> Bool) -> Self {
1248+
static func isActive(default keyDefault: @escaping @Sendable () -> Bool) -> Self {
12481249
PersistenceKeyDefault(.appStorage("isActive"), keyDefault())
12491250
}
12501251
}

Tests/ComposableArchitectureTests/StoreFilterTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Combine
33
import XCTest
44

55
final class StoreInvalidationTests: BaseTCATestCase {
6+
@MainActor
67
func testInvalidation() {
78
var cancellables: Set<AnyCancellable> = []
89

Tests/ComposableArchitectureTests/StoreLifetimeTests.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import XCTest
44

55
final class StoreLifetimeTests: BaseTCATestCase {
66
@available(*, deprecated)
7+
@MainActor
78
func testStoreCaching() {
89
let grandparentStore = Store(initialState: Grandparent.State()) {
910
Grandparent()
@@ -21,6 +22,7 @@ final class StoreLifetimeTests: BaseTCATestCase {
2122
}
2223

2324
@available(*, deprecated)
25+
@MainActor
2426
func testStoreInvalidation() {
2527
let grandparentStore = Store(initialState: Grandparent.State()) {
2628
Grandparent()
@@ -48,6 +50,7 @@ final class StoreLifetimeTests: BaseTCATestCase {
4850
}
4951

5052
#if DEBUG
53+
@MainActor
5154
func testStoreDeinit() {
5255
Logger.shared.isEnabled = true
5356
do {

0 commit comments

Comments
 (0)