@@ -16,6 +16,7 @@ package replication
16
16
17
17
import (
18
18
"context"
19
+ "encoding/json"
19
20
"errors"
20
21
"fmt"
21
22
"testing"
@@ -159,6 +160,20 @@ func newMockReplicator(ids []uint64) *mockFileReplicator {
159
160
}
160
161
}
161
162
163
+ func assertLastData (t * testing.T , data string , state string , stateID uint64 , availableStores []uint64 ) {
164
+ type status struct {
165
+ State string `json:"state"`
166
+ StateID uint64 `json:"state_id"`
167
+ AvailableStores []uint64 `json:"available_stores"`
168
+ }
169
+ var s status
170
+ err := json .Unmarshal ([]byte (data ), & s )
171
+ require .NoError (t , err )
172
+ require .Equal (t , state , s .State )
173
+ require .Equal (t , stateID , s .StateID )
174
+ require .Equal (t , availableStores , s .AvailableStores )
175
+ }
176
+
162
177
func TestStateSwitch (t * testing.T ) {
163
178
re := require .New (t )
164
179
ctx , cancel := context .WithCancel (context .Background ())
@@ -190,7 +205,7 @@ func TestStateSwitch(t *testing.T) {
190
205
stateID := rep .drAutoSync .StateID
191
206
re .NotEqual (uint64 (0 ), stateID )
192
207
rep .tickReplicateStatus ()
193
- re . Equal ( fmt . Sprintf ( `{"state":" sync","state_id":%d}` , stateID ), replicator . lastData [ 1 ] )
208
+ assertLastData ( t , replicator . lastData [ 1 ], " sync" , stateID , nil )
194
209
assertStateIDUpdate := func () {
195
210
re .NotEqual (stateID , rep .drAutoSync .StateID )
196
211
stateID = rep .drAutoSync .StateID
@@ -207,7 +222,7 @@ func TestStateSwitch(t *testing.T) {
207
222
re .Equal (drStateAsyncWait , rep .drGetState ())
208
223
assertStateIDUpdate ()
209
224
rep .tickReplicateStatus ()
210
- re . Equal ( fmt . Sprintf ( `{"state":" async_wait","state_id":%d,"available_stores":[1,2,3,4]}` , stateID ), replicator . lastData [ 1 ] )
225
+ assertLastData ( t , replicator . lastData [ 1 ], " async_wait" , stateID , [] uint64 { 1 , 2 , 3 , 4 } )
211
226
212
227
re .False (rep .GetReplicationStatus ().GetDrAutoSync ().GetPauseRegionSplit ())
213
228
conf .DRAutoSync .PauseRegionSplit = true
@@ -218,7 +233,7 @@ func TestStateSwitch(t *testing.T) {
218
233
rep .tickUpdateState ()
219
234
assertStateIDUpdate ()
220
235
rep .tickReplicateStatus ()
221
- re . Equal ( fmt . Sprintf ( `{"state":" async","state_id":%d,"available_stores":[1,2,3,4]}` , stateID ), replicator . lastData [ 1 ] )
236
+ assertLastData ( t , replicator . lastData [ 1 ], " async" , stateID , [] uint64 { 1 , 2 , 3 , 4 } )
222
237
223
238
// add new store in dr zone.
224
239
cluster .AddLabelsStore (5 , 1 , map [string ]string {"zone" : "zone2" })
@@ -268,18 +283,19 @@ func TestStateSwitch(t *testing.T) {
268
283
rep .tickUpdateState ()
269
284
re .Equal (drStateAsyncWait , rep .drGetState ())
270
285
assertStateIDUpdate ()
286
+
271
287
rep .tickReplicateStatus ()
272
- re . Equal ( fmt . Sprintf ( `{"state":" async_wait","state_id":%d,"available_stores":[1,2,3,4]}` , stateID ), replicator . lastData [ 1 ] )
288
+ assertLastData ( t , replicator . lastData [ 1 ], " async_wait" , stateID , [] uint64 { 1 , 2 , 3 , 4 } )
273
289
setStoreState (cluster , "down" , "up" , "up" , "up" , "down" , "down" )
274
290
rep .tickUpdateState ()
275
291
assertStateIDUpdate ()
276
292
rep .tickReplicateStatus ()
277
- re . Equal ( fmt . Sprintf ( `{"state":" async_wait","state_id":%d,"available_stores":[2,3,4]}` , stateID ), replicator . lastData [ 1 ] )
293
+ assertLastData ( t , replicator . lastData [ 1 ], " async_wait" , stateID , [] uint64 { 2 , 3 , 4 } )
278
294
setStoreState (cluster , "up" , "down" , "up" , "up" , "down" , "down" )
279
295
rep .tickUpdateState ()
280
296
assertStateIDUpdate ()
281
297
rep .tickReplicateStatus ()
282
- re . Equal ( fmt . Sprintf ( `{"state":" async_wait","state_id":%d,"available_stores":[1,3,4]}` , stateID ), replicator . lastData [ 1 ] )
298
+ assertLastData ( t , replicator . lastData [ 1 ], " async_wait" , stateID , [] uint64 { 1 , 3 , 4 } )
283
299
284
300
// async_wait -> async
285
301
rep .tickUpdateState ()
@@ -291,26 +307,32 @@ func TestStateSwitch(t *testing.T) {
291
307
rep .tickUpdateState ()
292
308
assertStateIDUpdate ()
293
309
rep .tickReplicateStatus ()
294
- re . Equal ( fmt . Sprintf ( `{"state":" async","state_id":%d,"available_stores":[1,3,4]}` , stateID ), replicator . lastData [ 1 ] )
310
+ assertLastData ( t , replicator . lastData [ 1 ], " async" , stateID , [] uint64 { 1 , 3 , 4 } )
295
311
296
312
// async -> async
297
313
setStoreState (cluster , "up" , "up" , "up" , "up" , "down" , "down" )
298
314
rep .tickUpdateState ()
299
315
// store 2 won't be available before it syncs status.
300
316
rep .tickReplicateStatus ()
301
- re . Equal ( fmt . Sprintf ( `{"state":" async","state_id":%d,"available_stores":[1,3,4]}` , stateID ), replicator . lastData [ 1 ] )
317
+ assertLastData ( t , replicator . lastData [ 1 ], " async" , stateID , [] uint64 { 1 , 3 , 4 } )
302
318
syncStoreStatus (1 , 2 , 3 , 4 )
303
319
rep .tickUpdateState ()
304
320
assertStateIDUpdate ()
305
321
rep .tickReplicateStatus ()
306
- re . Equal ( fmt . Sprintf ( `{"state":" async","state_id":%d,"available_stores":[1,2,3,4]}` , stateID ), replicator . lastData [ 1 ] )
322
+ assertLastData ( t , replicator . lastData [ 1 ], " async" , stateID , [] uint64 { 1 , 2 , 3 , 4 } )
307
323
308
324
// async -> sync_recover
309
325
setStoreState (cluster , "up" , "up" , "up" , "up" , "up" , "up" )
310
326
rep .tickUpdateState ()
311
327
re .Equal (drStateSyncRecover , rep .drGetState ())
312
328
assertStateIDUpdate ()
329
+
313
330
rep .drSwitchToAsync ([]uint64 {1 , 2 , 3 , 4 , 5 })
331
+ rep .config .DRAutoSync .WaitRecoverTimeout = typeutil .NewDuration (time .Hour )
332
+ rep .tickUpdateState ()
333
+ re .Equal (drStateAsync , rep .drGetState ()) // wait recover timeout
334
+
335
+ rep .config .DRAutoSync .WaitRecoverTimeout = typeutil .NewDuration (0 )
314
336
setStoreState (cluster , "down" , "up" , "up" , "up" , "up" , "up" )
315
337
rep .tickUpdateState ()
316
338
re .Equal (drStateSyncRecover , rep .drGetState ())
@@ -387,27 +409,27 @@ func TestReplicateState(t *testing.T) {
387
409
stateID := rep .drAutoSync .StateID
388
410
// replicate after initialized
389
411
rep .tickReplicateStatus ()
390
- re . Equal ( fmt . Sprintf ( `{"state":" sync","state_id":%d}` , stateID ), replicator . lastData [ 1 ] )
412
+ assertLastData ( t , replicator . lastData [ 1 ], " sync" , stateID , nil )
391
413
392
414
// repliate state to new member
393
415
replicator .memberIDs = append (replicator .memberIDs , 2 , 3 )
394
416
rep .tickReplicateStatus ()
395
- re . Equal ( fmt . Sprintf ( `{"state":" sync","state_id":%d}` , stateID ), replicator . lastData [ 2 ] )
396
- re . Equal ( fmt . Sprintf ( `{"state":" sync","state_id":%d}` , stateID ), replicator . lastData [ 3 ] )
417
+ assertLastData ( t , replicator . lastData [ 2 ], " sync" , stateID , nil )
418
+ assertLastData ( t , replicator . lastData [ 3 ], " sync" , stateID , nil )
397
419
398
420
// inject error
399
421
replicator .errors [2 ] = errors .New ("failed to persist" )
400
422
rep .tickUpdateState () // switch async_wait since there is only one zone
401
423
newStateID := rep .drAutoSync .StateID
402
424
rep .tickReplicateStatus ()
403
- re . Equal ( fmt . Sprintf ( `{"state":"async_wait","state_id":%d,"available_stores":[1,2]}` , newStateID ), replicator . lastData [ 1 ] )
404
- re . Equal ( fmt . Sprintf ( `{"state":" sync","state_id":%d}` , stateID ), replicator . lastData [ 2 ] )
405
- re . Equal ( fmt . Sprintf ( `{"state":" async_wait","state_id":%d,"available_stores":[1,2]}` , newStateID ), replicator . lastData [ 3 ] )
425
+ assertLastData ( t , replicator . lastData [ 1 ], "async_wait" , newStateID , [] uint64 { 1 , 2 } )
426
+ assertLastData ( t , replicator . lastData [ 2 ], " sync" , stateID , nil )
427
+ assertLastData ( t , replicator . lastData [ 3 ], " async_wait" , newStateID , [] uint64 { 1 , 2 } )
406
428
407
429
// clear error, replicate to node 2 next time
408
430
delete (replicator .errors , 2 )
409
431
rep .tickReplicateStatus ()
410
- re . Equal ( fmt . Sprintf ( `{"state":"async_wait","state_id":%d,"available_stores":[1,2]}` , newStateID ), replicator . lastData [ 2 ] )
432
+ assertLastData ( t , replicator . lastData [ 2 ], "async_wait" , newStateID , [] uint64 { 1 , 2 } )
411
433
}
412
434
413
435
func TestAsynctimeout (t * testing.T ) {
@@ -637,7 +659,7 @@ func TestComplexPlacementRules(t *testing.T) {
637
659
rep .tickUpdateState ()
638
660
re .Equal (drStateAsyncWait , rep .drGetState ())
639
661
rep .tickReplicateStatus ()
640
- re . Equal ( fmt . Sprintf ( `{"state":" async_wait","state_id":%d,"available_stores":[1,2,3,4,5,6]}` , rep . drAutoSync . StateID ), replicator . lastData [ 1 ] )
662
+ assertLastData ( t , replicator . lastData [ 1 ], " async_wait" , rep . drAutoSync . StateID , [] uint64 { 1 , 2 , 3 , 4 , 5 , 6 } )
641
663
642
664
// reset to sync
643
665
setStoreState (cluster , "up" , "up" , "up" , "up" , "up" , "up" , "up" , "up" , "up" , "up" )
@@ -698,7 +720,7 @@ func TestComplexPlacementRules2(t *testing.T) {
698
720
rep .tickUpdateState ()
699
721
re .Equal (drStateAsyncWait , rep .drGetState ())
700
722
rep .tickReplicateStatus ()
701
- re . Equal ( fmt . Sprintf ( `{"state":"async_wait","state_id":%d,"available_stores":[1,2,3,4]}` , rep .drAutoSync .StateID ), replicator . lastData [ 1 ] )
723
+ assertLastData ( t , replicator . lastData [ 1 ], "async_wait" , rep .drAutoSync .StateID , [] uint64 { 1 , 2 , 3 , 4 } )
702
724
}
703
725
704
726
func TestComplexPlacementRules3 (t * testing.T ) {
@@ -737,7 +759,7 @@ func TestComplexPlacementRules3(t *testing.T) {
737
759
rep .tickUpdateState ()
738
760
re .Equal (drStateAsyncWait , rep .drGetState ())
739
761
rep .tickReplicateStatus ()
740
- re . Equal ( fmt . Sprintf ( `{"state":"async_wait","state_id":%d,"available_stores":[1,2,3,4]}` , rep .drAutoSync .StateID ), replicator . lastData [ 1 ] )
762
+ assertLastData ( t , replicator . lastData [ 1 ], "async_wait" , rep .drAutoSync .StateID , [] uint64 { 1 , 2 , 3 , 4 } )
741
763
}
742
764
743
765
func genRegions (cluster * mockcluster.Cluster , stateID uint64 , n int ) []* core.RegionInfo {
0 commit comments