mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-09-28 16:09:49 +01:00
Co-authored-by: trevor-signal <trevor@signal.org> Co-authored-by: jamiebuilds-signal <jamie@signal.org>
179 lines
5.1 KiB
TypeScript
179 lines
5.1 KiB
TypeScript
// Copyright 2022 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
import assert from 'assert';
|
|
|
|
import { PromiseQueue, assertJsonValue } from '../src/util';
|
|
|
|
describe('util', () => {
|
|
describe('PromiseQueue', () => {
|
|
it('should pushAndWait and shift', async () => {
|
|
const q = new PromiseQueue<number>({ name: 'test' });
|
|
|
|
const { promise } = q.pushAndWait(42);
|
|
|
|
assert.strictEqual(await q.shift(), 42);
|
|
await promise;
|
|
});
|
|
|
|
it('should push and shift', async () => {
|
|
const q = new PromiseQueue<number>({ name: 'test' });
|
|
|
|
q.push(42);
|
|
|
|
assert.strictEqual(await q.shift(), 42);
|
|
});
|
|
|
|
it('should shift and pushAndWait', async () => {
|
|
const q = new PromiseQueue<number>({ name: 'test' });
|
|
|
|
const shift = q.shift();
|
|
|
|
const { promise } = q.pushAndWait(23);
|
|
await promise;
|
|
|
|
assert.strictEqual(await shift, 23);
|
|
});
|
|
|
|
it('should shift and push', async () => {
|
|
const q = new PromiseQueue<number>({ name: 'test' });
|
|
|
|
const shift = q.shift();
|
|
|
|
q.push(23);
|
|
|
|
assert.strictEqual(await shift, 23);
|
|
});
|
|
|
|
it('should timeout on push', async () => {
|
|
const q = new PromiseQueue<number>({ name: 'test' });
|
|
|
|
await assert.rejects(
|
|
async () => {
|
|
const { promise } = q.pushAndWait(23, 10);
|
|
await promise;
|
|
},
|
|
{ message: 'PromiseQueue(test) pushAndWait timeout' },
|
|
);
|
|
});
|
|
|
|
it('should not timeout on push', async () => {
|
|
const q = new PromiseQueue<number>({ name: 'test' });
|
|
|
|
const { promise } = q.pushAndWait(15, 1000);
|
|
|
|
assert.strictEqual(await q.shift(), 15);
|
|
await promise;
|
|
});
|
|
|
|
it('should timeout on shift', async () => {
|
|
const q = new PromiseQueue<number>({ name: 'test' });
|
|
|
|
await assert.rejects(
|
|
async () => {
|
|
await q.shift(10);
|
|
},
|
|
{ message: 'PromiseQueue(test) shift timeout' },
|
|
);
|
|
});
|
|
|
|
it('should not timeout on shift', async () => {
|
|
const q = new PromiseQueue<number>({ name: 'test' });
|
|
|
|
const shift = q.shift(1000);
|
|
|
|
const { promise } = q.pushAndWait(17);
|
|
await promise;
|
|
|
|
assert.strictEqual(await shift, 17);
|
|
});
|
|
|
|
it('should apply default timeouts on push', async () => {
|
|
const q = new PromiseQueue<number>({ timeout: 10, name: 'test' });
|
|
|
|
await assert.rejects(
|
|
async () => {
|
|
const { promise } = q.pushAndWait(23);
|
|
await promise;
|
|
},
|
|
{ message: 'PromiseQueue(test) pushAndWait timeout' },
|
|
);
|
|
});
|
|
|
|
it('should apply default timeouts on shift', async () => {
|
|
const q = new PromiseQueue<number>({ timeout: 10, name: 'test' });
|
|
|
|
await assert.rejects(
|
|
async () => {
|
|
await q.shift();
|
|
},
|
|
{ message: 'PromiseQueue(test) shift timeout' },
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('assertJsonValue', () => {
|
|
function valid(value: unknown) {
|
|
assert.doesNotThrow(() => assertJsonValue(value));
|
|
}
|
|
|
|
function invalid(value: unknown, predicate: RegExp) {
|
|
assert.throws(() => assertJsonValue(value), predicate);
|
|
}
|
|
|
|
it('should accept valid json', () => {
|
|
valid(null);
|
|
valid(true);
|
|
valid(false);
|
|
valid(0);
|
|
valid(42);
|
|
valid(-42);
|
|
valid('');
|
|
valid('hi');
|
|
valid([]);
|
|
valid([null, true, 42, 'hi', [1, 2, 3], { a: 'b' }]);
|
|
valid([1, [2, [3, 4], 5], 6]);
|
|
valid({});
|
|
valid({ a: null, b: true, c: 42, d: 'hi', e: [1, 2, 3], f: { a: 'b' } });
|
|
valid({ a: undefined, b: { c: undefined } });
|
|
});
|
|
|
|
it('should not accept invalid json', () => {
|
|
invalid(undefined, /value: undefined/);
|
|
invalid(Number.NEGATIVE_INFINITY, /value: -Infinity/);
|
|
invalid(Number.POSITIVE_INFINITY, /value: Infinity/);
|
|
invalid(Number.NaN, /value: NaN/);
|
|
invalid(0n, /value: 0n/);
|
|
invalid(24n, /value: 24n/);
|
|
invalid([undefined], /value\.0: undefined/);
|
|
invalid([1, [42n]], /value\.1\.0: 42n/);
|
|
invalid({ a: 42n }, /value\.a: 42n/);
|
|
invalid({ a: { b: 42n } }, /value\.a\.b: 42n/);
|
|
invalid(() => 'hi', /value: \[Function \(anonymous\)\]/);
|
|
invalid(Buffer.from('hi'), /value: <Buffer 68 69>/);
|
|
invalid(new Uint8Array([68, 69]), /value: Uint8Array\(2\) \[ 68, 69 \]/);
|
|
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
|
invalid(class Foo {}, /value: \[class Foo\]/);
|
|
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
|
invalid(new (class Foo {})(), /value: Foo {}/);
|
|
invalid(42n, /value: 42n/);
|
|
});
|
|
|
|
it('should report multiple errors', () => {
|
|
assert.throws(
|
|
() => {
|
|
assertJsonValue({ a: 42n, b: { c: 42n, d: [42n, 42n] } });
|
|
},
|
|
(error) => {
|
|
assert(error instanceof TypeError);
|
|
assert.match(error.message, /value\.a: 42n/);
|
|
assert.match(error.message, /value\.b\.c: 42n/);
|
|
assert.match(error.message, /value\.b\.d\.0: 42n/);
|
|
assert.match(error.message, /value\.b\.d\.1: 42n/);
|
|
return true;
|
|
},
|
|
);
|
|
});
|
|
});
|
|
});
|