mirror of
https://github.com/video-dev/hls.js.git
synced 2026-06-16 13:34:44 +00:00
359197f20b
* chore(deps): update dependency prettier to v3 * run prettier --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Tom Jenkinson <tom@tjenkinson.me>
166 lines
4.7 KiB
TypeScript
166 lines
4.7 KiB
TypeScript
import BufferOperationQueue from '../../../src/controller/buffer-operation-queue';
|
|
import type { BufferOperation, SourceBuffers } from '../../../src/types/buffer';
|
|
|
|
import sinon from 'sinon';
|
|
import chai from 'chai';
|
|
import sinonChai from 'sinon-chai';
|
|
|
|
chai.use(sinonChai);
|
|
const expect = chai.expect;
|
|
const queueNames = ['audio', 'video'];
|
|
|
|
describe('BufferOperationQueue tests', function () {
|
|
const sandbox = sinon.createSandbox();
|
|
let operationQueue;
|
|
const sbMock = {
|
|
audio: {
|
|
updating: false,
|
|
},
|
|
video: {
|
|
updating: false,
|
|
},
|
|
} as any as SourceBuffers;
|
|
|
|
beforeEach(function () {
|
|
operationQueue = new BufferOperationQueue(sbMock);
|
|
});
|
|
|
|
afterEach(function () {
|
|
sandbox.restore();
|
|
});
|
|
|
|
it('initializes with an audio and video queue', function () {
|
|
expect(operationQueue.queues.video).to.exist;
|
|
expect(operationQueue.queues.audio).to.exist;
|
|
});
|
|
|
|
describe('append', function () {
|
|
it('appends and executes if the queue is empty', function () {
|
|
const execute = sandbox.spy();
|
|
const operation: BufferOperation = {
|
|
execute,
|
|
onStart: () => {},
|
|
onComplete: () => {},
|
|
onError: () => {},
|
|
};
|
|
|
|
queueNames.forEach((name, i) => {
|
|
operationQueue.append(operation, name);
|
|
expect(
|
|
execute,
|
|
`The ${name} queue operation should have been executed`,
|
|
).to.have.callCount(i + 1);
|
|
expect(
|
|
operationQueue.queues[name],
|
|
`The ${name} queue should have a length of 1`,
|
|
).to.have.length(1);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('appends but does not execute if the queue has at least one operation enqueued', function () {
|
|
queueNames.forEach((name) => {
|
|
operationQueue.queues[name].push({});
|
|
});
|
|
|
|
const execute = sandbox.spy();
|
|
const operation: BufferOperation = {
|
|
execute,
|
|
onStart: () => {},
|
|
onComplete: () => {},
|
|
onError: () => {},
|
|
};
|
|
|
|
queueNames.forEach((name) => {
|
|
operationQueue.append(operation, name);
|
|
expect(
|
|
execute,
|
|
`The ${name} queue operation should not have been executed`,
|
|
).to.have.not.been.called;
|
|
expect(
|
|
operationQueue.queues[name],
|
|
`The ${name} queue should have a length of 2`,
|
|
).to.have.length(2);
|
|
});
|
|
});
|
|
|
|
describe('appendBlocker', function () {
|
|
it('appends a blocking promise, which resolves upon execution', function () {
|
|
const promises: Promise<{}>[] = [];
|
|
queueNames.forEach((name) => {
|
|
promises.push(operationQueue.appendBlocker(name));
|
|
});
|
|
return Promise.all(promises).then(() => {
|
|
queueNames.forEach((name) => {
|
|
expect(
|
|
operationQueue.queues[name],
|
|
`The ${name} queue should have a length of 1`,
|
|
).to.have.length(1);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('executeNext', function () {
|
|
it('does nothing if executing against an empty queue', function () {
|
|
queueNames.forEach((name) => {
|
|
expect(operationQueue.executeNext(name)).to.not.throw;
|
|
});
|
|
});
|
|
|
|
it('should execute the onError callback and shift the operation if it throws an unhandled exception', function () {
|
|
const onError = sandbox.spy();
|
|
const error = new Error();
|
|
const operation: BufferOperation = {
|
|
execute: () => {
|
|
throw error;
|
|
},
|
|
onStart: () => {},
|
|
onComplete: () => {},
|
|
onError,
|
|
};
|
|
queueNames.forEach((name, i) => {
|
|
operationQueue.append(operation, name);
|
|
expect(onError, 'onError should have been called').to.have.callCount(
|
|
i + 1,
|
|
);
|
|
expect(
|
|
onError,
|
|
'onError should have been called with the thrown exception',
|
|
).to.have.been.calledWith(error);
|
|
expect(
|
|
operationQueue.queues[name],
|
|
`The ${name} queue should have a length of 0`,
|
|
).to.have.length(0);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('shiftAndExecute', function () {
|
|
const execute = sandbox.spy();
|
|
const operation: BufferOperation = {
|
|
execute,
|
|
onStart: () => {},
|
|
onComplete: () => {},
|
|
onError: () => {},
|
|
};
|
|
it('should dequeue the current operation and execute the next', function () {
|
|
queueNames.forEach((name) => {
|
|
operationQueue.queues[name].push({}, operation);
|
|
});
|
|
|
|
queueNames.forEach((name, i) => {
|
|
operationQueue.shiftAndExecuteNext(name);
|
|
expect(
|
|
execute,
|
|
`The ${name} queue operation should have been executed`,
|
|
).to.have.callCount(i + 1);
|
|
expect(
|
|
operationQueue.queues[name],
|
|
`The ${name} queue should have a length of 1`,
|
|
).to.have.length(1);
|
|
});
|
|
});
|
|
});
|
|
});
|