1
1
import 'dart:async' ;
2
2
3
3
import 'package:checks/checks.dart' ;
4
+ import 'package:fake_async/fake_async.dart' ;
4
5
import 'package:flutter/foundation.dart' ;
5
6
import 'package:http/http.dart' as http;
6
7
import 'package:test/scaffolding.dart' ;
@@ -11,6 +12,7 @@ import 'package:zulip/api/route/messages.dart';
11
12
import 'package:zulip/model/store.dart' ;
12
13
import 'package:zulip/notifications/receive.dart' ;
13
14
15
+ import '../api/backoff_test.dart' ;
14
16
import '../api/fake_api.dart' ;
15
17
import '../api/model/model_checks.dart' ;
16
18
import '../example_data.dart' as eg;
@@ -425,6 +427,66 @@ void main() {
425
427
check (store.userSettings! .twentyFourHourTime).isTrue ();
426
428
}));
427
429
430
+ test ('reset BackoffMachine after a successful poll' , () {
431
+ Duration measureWait (FakeAsync async ) {
432
+ final duration = async .pendingTimers.first.duration;
433
+ async .flushTimers ();
434
+ return duration;
435
+ }
436
+
437
+ void prepareError () {
438
+ connection.prepare (httpStatus: 500 , body: 'splat' );
439
+ }
440
+ void prepareSuccess () {
441
+ connection.prepare (json: GetEventsResult (events: [
442
+ HeartbeatEvent (id: 2 ),
443
+ ], queueId: null ).toJson ());
444
+ }
445
+
446
+ verifyRandomizedDurations (
447
+ expectedMaxDurationsInMs: [100 , 200 , 400 , 800 , 1600 , 100 , 200 , 400 , 800 , 1600 ],
448
+ computeActualDurations: (expectedMaxDurations) => awaitFakeAsync ((async ) async {
449
+ await prepareStore ();
450
+ updateMachine.debugPauseLoop ();
451
+ updateMachine.poll ();
452
+ final results = < Duration > [];
453
+ int lastEventId = 1 ;
454
+ for (int i = 0 ; i < expectedMaxDurations.length; i++ ) {
455
+ check (async .pendingTimers).isEmpty ();
456
+ if (i > 0 && expectedMaxDurations[i] < expectedMaxDurations[i - 1 ]) {
457
+ // The backoff duration should get a reset when the poll was
458
+ // successful.
459
+ prepareSuccess ();
460
+ updateMachine.debugAdvanceLoop ();
461
+ async .flushTimers ();
462
+
463
+ checkLastRequest (lastEventId: lastEventId);
464
+ // Verify that the poll completes successfully.
465
+ lastEventId++ ;
466
+ check (updateMachine.lastEventId).equals (lastEventId);
467
+ }
468
+
469
+ // Make the request, inducing an error in it.
470
+ prepareError ();
471
+ updateMachine.debugAdvanceLoop ();
472
+
473
+ // Wait for the request to finish.
474
+ async .elapse (Duration .zero);
475
+ checkLastRequest (lastEventId: lastEventId);
476
+ check (updateMachine.lastEventId).equals (lastEventId);
477
+
478
+ // The backoff timer should be active now.
479
+ check (async .pendingTimers).single;
480
+ final duration = measureWait (async );
481
+ results.add (duration);
482
+ check (async .pendingTimers).isEmpty ();
483
+ check (connection.lastRequest).isNull ();
484
+ }
485
+
486
+ return results;
487
+ }));
488
+ });
489
+
428
490
void checkRetry (void Function () prepareError) {
429
491
awaitFakeAsync ((async ) async {
430
492
await prepareStore (lastEventId: 1 );
0 commit comments