Path: blob/main/components/gitpod-protocol/src/util/queue.spec.ts
2500 views
/* eslint-disable @typescript-eslint/no-unsafe-argument */1/* eslint-disable @typescript-eslint/no-floating-promises */2/**3* Copyright (c) 2020 Gitpod GmbH. All rights reserved.4* Licensed under the GNU Affero General Public License (AGPL).5* See License.AGPL.txt in the project root for license information.6*/78import { suite, test, slow, timeout } from "@testdeck/mocha";9import * as chai from "chai";10const chaiSubset = require("chai-subset");11chai.use(chaiSubset);1213import { Queue } from "..";14import { fail } from "assert";15import { Deferred } from "./deferred";1617const expect = chai.expect;1819@suite20class QueueSpec {21queue: Queue;22seq: number[];2324before() {25this.queue = new Queue();26this.seq = [];27}2829async exec(seqNr: number, nextTick: boolean = false, sleep: number = 0) {30return this.queue.enqueue(async () => {31const push = async () => {32if (sleep > 0)33return new Promise((resolve) => {34setTimeout(() => {35this.seq.push(seqNr);36resolve(undefined);37}, sleep);38});39else this.seq.push(seqNr);40};4142if (nextTick)43return new Promise((resolve) => {44process.nextTick(() => {45push().then(resolve);46});47});48else await push();49});50}51execError(seqNr: number): Deferred<boolean> {52const deferred = new Deferred<boolean>();53this.queue54.enqueue(async () => {55this.seq.push(seqNr);56throw new Error("test error");57})58.then(() => {59deferred.reject(false);60})61.catch(() => {62deferred.resolve(true);63});6465return deferred;66}6768protected expectArray<T>(actual: T[], expected: T[]) {69expect(actual).to.have.lengthOf(expected.length);70const expIt = expected.entries();71for (const act of actual) {72const {73value: [, exp],74} = expIt.next();75expect(act).to.deep.equal(exp);76}77}7879@test public async isExecutedInOrder() {80this.exec(1);81await this.exec(2);8283this.expectArray(this.seq, [1, 2]);84}8586@test public async isExecutedInOrderSkipTick() {87this.exec(1, true);88await this.exec(2);8990this.expectArray(this.seq, [1, 2]);91}9293@test @timeout(3000) @slow(3000) public async isExecutedInOrderSleep() {94this.exec(1, false, 2000);95await this.exec(2);9697this.expectArray(this.seq, [1, 2]);98}99100@test public async continueDespiteError() {101this.exec(1);102const receivedError = this.execError(2);103await this.exec(3);104105expect(receivedError.isResolved).to.equal(true);106expect(await receivedError.promise).to.equal(true);107this.expectArray(this.seq, [1, 2, 3]);108}109110@test public async mustCatchError() {111const f = async () => {112throw new Error();113};114try {115const p = this.queue.enqueue(async () => {116return f();117});118119p.catch((err) => {120// Silence unhandled promise rejection messages121});122} catch (err) {123fail("We expect to catch no error");124}125}126127@test public async expectUncaughtError() {128const f = async () => {129throw new Error();130};131const p = this.queue.enqueue(async () => {132return f();133});134p.then((r) => {135fail("Expected to catch error!");136}).catch((err) => {137// Silence unhandled promise rejection messages138});139}140}141module.exports = new QueueSpec();142143144