/** * Copyright (c) 2020 TypeFox GmbH. All rights reserved. * Licensed under the GNU Affero General Public License (AGPL). * See License-AGPL.txt in the project root for license information. */ import { suite, test, slow, timeout } from 'mocha-typescript' import * as chai from 'chai' const chaiSubset = require('chai-subset'); chai.use(chaiSubset); import { Queue } from '..'; import { fail } from 'assert'; import { Deferred } from './deferred'; const expect = chai.expect @suite class QueueSpec { queue: Queue; seq: number[]; before() { this.queue = new Queue(); this.seq = []; } async exec(seqNr: number, nextTick: boolean = false, sleep: number = 0) { return this.queue.enqueue(async () => { const push = async () => { if (sleep > 0) return new Promise((resolve) => { setTimeout(() => { this.seq.push(seqNr); resolve(); }, sleep); }); else this.seq.push(seqNr); }; if (nextTick) return new Promise((resolve) => { process.nextTick(() => { push().then(resolve); }); }); else await push(); }); } execError(seqNr: number): Deferred { const deferred = new Deferred(); this.queue.enqueue(async () => { this.seq.push(seqNr); throw new Error('test error'); }).then(() => { deferred.reject(false); }).catch(() => { deferred.resolve(true); }); return deferred; } protected expectArray(actual: T[], expected: T[]) { expect(actual).to.have.lengthOf(expected.length); const expIt = expected.entries(); for (const act of actual) { const { value: [, exp] } = expIt.next(); expect(act).to.deep.equal(exp); } } @test public async isExecutedInOrder() { this.exec(1); await this.exec(2); this.expectArray(this.seq, [1, 2]); } @test public async isExecutedInOrderSkipTick() { this.exec(1, true); await this.exec(2); this.expectArray(this.seq, [1, 2]); } @test @timeout(3000) @slow(3000) public async isExecutedInOrderSleep() { this.exec(1, false, 2000); await this.exec(2); this.expectArray(this.seq, [1, 2]); } @test public async continueDespiteError() { this.exec(1); const receivedError = this.execError(2); await this.exec(3); expect(receivedError.isResolved).to.equal(true); expect(await receivedError.promise).to.equal(true); this.expectArray(this.seq, [1, 2, 3]); } @test public async mustCatchError() { const f = async () => { throw new Error(); } try { const p = this.queue.enqueue(async () => { return f(); }); p.catch((err) => { // Silence unhandled promise rejection messages }); } catch (err) { fail("We expect to catch no error"); } } @test public async expectUncaughtError() { const f = async () => { throw new Error(); } const p = this.queue.enqueue(async () => { return f(); }); p.then((r) => { fail("Expected to catch error!"); }).catch((err) => { // Silence unhandled promise rejection messages }); } } module.exports = new QueueSpec();