@@ -41,15 +41,15 @@ final class StoreTests: XCTestCase {
41
41
42
42
override func tearDown( ) {
43
43
do {
44
- _ = try store. dispatch ( action: ClearAction ( ) ) . toBlocking ( timeout: 1 ) . single ( )
44
+ _ = try store. dispatch ( action: AppAction . clear ) . toBlocking ( timeout: 1 ) . single ( )
45
45
} catch {
46
46
XCTFail ( error. localizedDescription)
47
47
}
48
48
}
49
49
50
50
func testSynchronousAction( ) throws {
51
51
52
- let increaseAction = IncreaseAction ( increment: 10 )
52
+ let increaseAction = AppAction . increase ( increment: 10 )
53
53
54
54
let state = try store
55
55
. dispatch ( action: increaseAction)
@@ -66,7 +66,7 @@ final class StoreTests: XCTestCase {
66
66
67
67
func testSubstateSubscription( ) throws {
68
68
69
- let increaseAction = IncreaseAction ( increment: 10 )
69
+ let increaseAction = AppAction . increase ( increment: 10 )
70
70
71
71
let counterState = try store
72
72
. dispatch ( action: increaseAction) { $0. counterState }
@@ -82,7 +82,7 @@ final class StoreTests: XCTestCase {
82
82
83
83
func testAsynchronousAction( ) throws {
84
84
85
- let increaseAction = Observable< Action> . just( IncreaseAction ( increment: 10 ) )
85
+ let increaseAction = Observable< Action> . just( AppAction . increase ( increment: 10 ) )
86
86
87
87
let state = try store
88
88
. dispatch ( action: increaseAction)
@@ -99,7 +99,7 @@ final class StoreTests: XCTestCase {
99
99
100
100
func testArrayOfActionsWithObservable ( ) throws {
101
101
102
- let actions : [ Action ] = [ IncreaseAction ( increment: 10 ) , Observable< Action> . just( DecreaseAction ( decrement: 20 ) ) , LogUserAction ( user: " Spock " ) ]
102
+ let actions : [ Action ] = [ AppAction . increase ( increment: 10 ) , Observable< Action> . just( AppAction . decrease ( decrement: 20 ) ) , AppAction . logUser ( user: " Spock " ) ]
103
103
104
104
let statesToTest = try store. dispatch ( action: actions) . toBlocking ( ) . toArray ( )
105
105
@@ -121,7 +121,7 @@ final class StoreTests: XCTestCase {
121
121
func testStateObservable ( ) throws {
122
122
let exp = expectation ( description: " State Observable Expectation " )
123
123
124
- let increaseAction = IncreaseAction ( increment: 10 )
124
+ let increaseAction = AppAction . increase ( increment: 10 )
125
125
126
126
Observable . combineLatest ( self . store. dispatch ( action: increaseAction) , self . store. state) { ( newState1, newState2) -> ( TestState , TestState ) in
127
127
return ( newState1, newState2)
@@ -156,18 +156,18 @@ final class StoreTests: XCTestCase {
156
156
// Given
157
157
let exp = expectation ( description: " Queue expectation " )
158
158
exp. expectedFulfillmentCount = 3
159
- let actionObservable = Observable< Action> . just ( IncreaseAction ( increment: 10 ) )
159
+ let actionObservable = Observable< Action> . just ( AppAction . increase ( increment: 10 ) )
160
160
161
161
// When
162
162
actionObservable
163
- . map { action -> DecreaseAction in
163
+ . map { action -> AppAction in
164
164
if let queueName = OperationQueue . current? . name!,
165
165
queueName == " SUBSCRIBE_ON_QUEUE " {
166
166
exp. fulfill ( )
167
167
} else {
168
168
XCTFail ( " Subscribe on Wrong Queue " )
169
169
}
170
- return DecreaseAction ( decrement: 10 )
170
+ return AppAction . decrease ( decrement: 10 )
171
171
}
172
172
. flatMap { ( action) -> Observable < CounterState > in
173
173
@@ -194,4 +194,81 @@ final class StoreTests: XCTestCase {
194
194
// Then
195
195
waitForExpectations ( timeout: 1 )
196
196
}
197
+
198
+ func testDispatchActionSerialSynchronization ( ) throws {
199
+ // Given
200
+ let exp = expectation ( description: " Synchronization expectation " )
201
+ exp. expectedFulfillmentCount = 2
202
+ let concurrentQueue = DispatchQueue ( label: " com.rxswiftcommunity.rxreduce.concurrentqueue " , qos: . userInitiated, attributes: [ . concurrent] )
203
+ let sem = DispatchSemaphore ( value: 0 )
204
+ var firstReducerStartTime = DispatchTime . now ( )
205
+ var firstReducerEndTime = DispatchTime . now ( )
206
+ var secondReducerStartTime = DispatchTime . now ( )
207
+ var secondReducerEndTime = DispatchTime . now ( )
208
+
209
+ // Implements Reducers that have specific instructions for Thread lock and Time measurement
210
+ func userReducer ( state: TestState , action: Action ) -> UserState {
211
+ if case let AppAction . logUser( user) = action {
212
+ firstReducerStartTime = DispatchTime . now ( )
213
+ _ = sem. wait ( timeout: DispatchTime ( uptimeNanoseconds: 1000000000 ) )
214
+ exp. fulfill ( )
215
+ firstReducerEndTime = DispatchTime . now ( )
216
+ return UserState . loggedIn ( name: user)
217
+ }
218
+ return state. userState
219
+ }
220
+
221
+ func counterReducer ( state: TestState , action: Action ) -> CounterState {
222
+ if case let AppAction . increase( increment) = action {
223
+ secondReducerStartTime = DispatchTime . now ( )
224
+ _ = sem. wait ( timeout: DispatchTime ( uptimeNanoseconds: 1000000000 ) )
225
+ exp. fulfill ( )
226
+ secondReducerEndTime = DispatchTime . now ( )
227
+ return CounterState . increasing ( increment)
228
+ }
229
+ return state. counterState
230
+ }
231
+
232
+ // Instantiating Mutators and Store using those 2 Reducers
233
+ let userMutator = Mutator < TestState , UserState > ( lens: userLens,
234
+ reducer: userReducer)
235
+
236
+ let counterMutator = Mutator < TestState , CounterState > ( lens: counterLens,
237
+ reducer: counterReducer)
238
+
239
+ let syncTestsStore = Store < TestState > ( withState: TestState ( counterState: . empty, userState: . loggedOut) )
240
+ syncTestsStore. register ( mutator: userMutator)
241
+ syncTestsStore. register ( mutator: counterMutator)
242
+
243
+ // When
244
+ concurrentQueue. async {
245
+ do {
246
+ _ = try syncTestsStore. dispatch ( action: AppAction . increase ( increment: 10 ) ) . toBlocking ( ) . single ( )
247
+ } catch {
248
+ XCTFail ( )
249
+ }
250
+ }
251
+
252
+ concurrentQueue. async {
253
+ do {
254
+ _ = try syncTestsStore. dispatch ( action: AppAction . logUser ( user: " Spock " ) ) . toBlocking ( ) . single ( )
255
+ } catch {
256
+ XCTFail ( )
257
+ }
258
+ }
259
+
260
+ // Then
261
+ waitForExpectations ( timeout: 5 ) { error in
262
+ if let error = error {
263
+ XCTFail ( error. localizedDescription)
264
+ return
265
+ }
266
+
267
+ if firstReducerStartTime < secondReducerStartTime {
268
+ XCTAssertGreaterThanOrEqual ( secondReducerStartTime, firstReducerEndTime)
269
+ } else {
270
+ XCTAssertGreaterThanOrEqual ( firstReducerStartTime, secondReducerEndTime)
271
+ }
272
+ }
273
+ }
197
274
}
0 commit comments