diff options
Diffstat (limited to 'polygerrit-ui/app/services/scheduler/retry-scheduler_test.ts')
-rw-r--r-- | polygerrit-ui/app/services/scheduler/retry-scheduler_test.ts | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/polygerrit-ui/app/services/scheduler/retry-scheduler_test.ts b/polygerrit-ui/app/services/scheduler/retry-scheduler_test.ts new file mode 100644 index 0000000000..988b167071 --- /dev/null +++ b/polygerrit-ui/app/services/scheduler/retry-scheduler_test.ts @@ -0,0 +1,122 @@ +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import '../../test/common-test-setup-karma.js'; +import {assertFails} from '../../test/test-utils.js'; +import {Scheduler} from './scheduler'; +import {RetryScheduler, RetryError} from './retry-scheduler'; +import {FakeScheduler} from './fake-scheduler'; +import {SinonFakeTimers} from 'sinon'; + +suite('retry scheduler', () => { + let clock: SinonFakeTimers; + let fakeScheduler: FakeScheduler<number>; + let scheduler: Scheduler<number>; + setup(() => { + clock = sinon.useFakeTimers(); + fakeScheduler = new FakeScheduler<number>(); + scheduler = new RetryScheduler<number>(fakeScheduler, 3, 50, 1); + }); + + async function waitForRetry(ms: number) { + // Flush the promise so that we can reach untilTimeout + await flush(); + // Advance the clock. + clock.tick(ms); + // Flush the promise that waits for the clock. + await flush(); + } + + test('executes tasks', async () => { + const promise = scheduler.schedule(async () => 1); + assert.equal(fakeScheduler.scheduled.length, 1); + fakeScheduler.resolve(); + assert.equal(fakeScheduler.scheduled.length, 0); + const val = await promise; + assert.equal(val, 1); + }); + + test('propagates task errors', async () => { + const error = new Error('This is an error'); + const promise = scheduler.schedule(async () => { + throw error; + }); + assert.equal(fakeScheduler.scheduled.length, 1); + assertFails(promise, error); + fakeScheduler.resolve(); + assert.equal(fakeScheduler.scheduled.length, 0); + await promise.catch((reason: Error) => { + assert.equal(reason, error); + }); + }); + + test('propagates subscheduler errors', async () => { + const error = new Error('This is an error'); + const promise = scheduler.schedule(async () => 1); + assert.equal(fakeScheduler.scheduled.length, 1); + assertFails(promise, error); + fakeScheduler.reject(error); + assert.equal(fakeScheduler.scheduled.length, 0); + await promise.catch((reason: Error) => { + assert.equal(reason, error); + }); + }); + + test('retries on retryable error', async () => { + let retries = 1; + const promise = scheduler.schedule(async () => { + if (retries-- > 0) throw new RetryError('Retrying'); + return 1; + }); + assert.equal(fakeScheduler.scheduled.length, 1); + fakeScheduler.resolve(); + assert.equal(fakeScheduler.scheduled.length, 0); + await waitForRetry(50); + assert.equal(fakeScheduler.scheduled.length, 1); + fakeScheduler.resolve(); + const val = await promise; + assert.equal(val, 1); + }); + + test('retries up to 3 times', async () => { + let retries = 3; + const promise = scheduler.schedule(async () => { + if (retries-- > 0) throw new RetryError('Retrying'); + return 1; + }); + assert.equal(fakeScheduler.scheduled.length, 1); + for (let i = 0; i < 3; i++) { + fakeScheduler.resolve(); + assert.equal(fakeScheduler.scheduled.length, 0); + await waitForRetry(50); + assert.equal(fakeScheduler.scheduled.length, 1); + } + fakeScheduler.resolve(); + const val = await promise; + assert.equal(val, 1); + }); + + test('fails after more than 3 times', async () => { + let retries = 4; + const promise = scheduler.schedule(async () => { + if (retries-- > 0) throw new RetryError(retries, `Retrying ${retries}`); + return 1; + }); + assert.equal(fakeScheduler.scheduled.length, 1); + for (let i = 0; i < 3; i++) { + fakeScheduler.resolve(); + assert.equal(fakeScheduler.scheduled.length, 0); + await waitForRetry(50); + assert.equal(fakeScheduler.scheduled.length, 1); + } + fakeScheduler.resolve(); + assertFails(promise); + // The error we get back should be the last error. + await promise.catch((reason: RetryError<number>) => { + assert.equal(reason.payload, 0); + assert.equal(reason.message, 'Retrying 0'); + }); + }); +}); |