UNPKG

mediasoup

Version:

Cutting Edge WebRTC Video Conferencing

219 lines (218 loc) 9.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const os = require("node:os"); const process = require("node:process"); const path = require("node:path"); const mediasoup = require("../"); const enhancedEvents_1 = require("../enhancedEvents"); const errors_1 = require("../errors"); test('Worker.workerBin matches mediasoup-worker absolute path', () => { const workerBin = process.env.MEDIASOUP_WORKER_BIN ? process.env.MEDIASOUP_WORKER_BIN : process.env.MEDIASOUP_BUILDTYPE === 'Debug' ? path.join(__dirname, '..', '..', '..', 'worker', 'out', 'Debug', 'mediasoup-worker') : path.join(__dirname, '..', '..', '..', 'worker', 'out', 'Release', 'mediasoup-worker'); expect(mediasoup.workerBin).toBe(workerBin); }); test('createWorker() succeeds', async () => { const onObserverNewWorker = jest.fn(); mediasoup.observer.once('newworker', onObserverNewWorker); const worker1 = await mediasoup.createWorker(); expect(onObserverNewWorker).toHaveBeenCalledTimes(1); expect(onObserverNewWorker).toHaveBeenCalledWith(worker1); expect(worker1.constructor.name).toBe('Worker'); expect(typeof worker1.pid).toBe('number'); expect(worker1.closed).toBe(false); expect(worker1.died).toBe(false); worker1.close(); await (0, enhancedEvents_1.enhancedOnce)(worker1, 'subprocessclose'); expect(worker1.closed).toBe(true); expect(worker1.died).toBe(false); const worker2 = await mediasoup.createWorker({ logLevel: 'debug', logTags: ['info'], rtcMinPort: 0, rtcMaxPort: 9999, dtlsCertificateFile: path.join(__dirname, 'data', 'dtls-cert.pem'), dtlsPrivateKeyFile: path.join(__dirname, 'data', 'dtls-key.pem'), libwebrtcFieldTrials: 'WebRTC-Bwe-AlrLimitedBackoff/Disabled/', appData: { foo: 456 }, }); expect(worker2.constructor.name).toBe('Worker'); expect(typeof worker2.pid).toBe('number'); expect(worker2.closed).toBe(false); expect(worker2.died).toBe(false); expect(worker2.appData).toEqual({ foo: 456 }); worker2.close(); await (0, enhancedEvents_1.enhancedOnce)(worker2, 'subprocessclose'); expect(worker2.closed).toBe(true); expect(worker2.died).toBe(false); }, 2000); test('createWorker() with wrong settings rejects with TypeError', async () => { // @ts-ignore await expect(mediasoup.createWorker({ logLevel: 'chicken' })).rejects.toThrow(TypeError); await expect(mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 999 })).rejects.toThrow(TypeError); // Port is from 0 to 65535. await expect(mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 65536 })).rejects.toThrow(TypeError); await expect(mediasoup.createWorker({ dtlsCertificateFile: '/notfound/cert.pem' })).rejects.toThrow(TypeError); await expect(mediasoup.createWorker({ dtlsPrivateKeyFile: '/notfound/priv.pem' })).rejects.toThrow(TypeError); await expect( // @ts-ignore mediasoup.createWorker({ appData: 'NOT-AN-OBJECT' })).rejects.toThrow(TypeError); }, 2000); test('worker.updateSettings() succeeds', async () => { const worker = await mediasoup.createWorker(); await expect(worker.updateSettings({ logLevel: 'debug', logTags: ['ice'] })).resolves.toBeUndefined(); worker.close(); await (0, enhancedEvents_1.enhancedOnce)(worker, 'subprocessclose'); }, 2000); test('worker.updateSettings() with wrong settings rejects with TypeError', async () => { const worker = await mediasoup.createWorker(); // @ts-ignore await expect(worker.updateSettings({ logLevel: 'chicken' })).rejects.toThrow(TypeError); worker.close(); await (0, enhancedEvents_1.enhancedOnce)(worker, 'subprocessclose'); }, 2000); test('worker.updateSettings() rejects with InvalidStateError if closed', async () => { const worker = await mediasoup.createWorker(); worker.close(); await (0, enhancedEvents_1.enhancedOnce)(worker, 'subprocessclose'); await expect(worker.updateSettings({ logLevel: 'error' })).rejects.toThrow(errors_1.InvalidStateError); }, 2000); test('worker.dump() succeeds', async () => { const worker = await mediasoup.createWorker(); await expect(worker.dump()).resolves.toMatchObject({ pid: worker.pid, webRtcServerIds: [], routerIds: [], channelMessageHandlers: { channelRequestHandlers: [], channelNotificationHandlers: [], }, }); worker.close(); }, 2000); test('worker.dump() rejects with InvalidStateError if closed', async () => { const worker = await mediasoup.createWorker(); worker.close(); await (0, enhancedEvents_1.enhancedOnce)(worker, 'subprocessclose'); await expect(worker.dump()).rejects.toThrow(errors_1.InvalidStateError); }, 2000); test('worker.getResourceUsage() succeeds', async () => { const worker = await mediasoup.createWorker(); await expect(worker.getResourceUsage()).resolves.toMatchObject({}); worker.close(); await (0, enhancedEvents_1.enhancedOnce)(worker, 'subprocessclose'); }, 2000); test('worker.close() succeeds', async () => { const worker = await mediasoup.createWorker({ logLevel: 'warn' }); const onObserverClose = jest.fn(); worker.observer.once('close', onObserverClose); worker.close(); await (0, enhancedEvents_1.enhancedOnce)(worker, 'subprocessclose'); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(worker.closed).toBe(true); expect(worker.died).toBe(false); }, 2000); test('Worker emits "died" if worker process died unexpectedly', async () => { let onDied; let onObserverClose; const worker1 = await mediasoup.createWorker({ logLevel: 'warn' }); onDied = jest.fn(); onObserverClose = jest.fn(); worker1.observer.once('close', onObserverClose); await new Promise((resolve, reject) => { worker1.on('died', () => { onDied(); if (onObserverClose.mock.calls.length > 0) { reject(new Error('observer "close" event emitted before worker "died" event')); } else if (worker1.closed) { resolve(); } else { reject(new Error('worker.closed is false')); } }); process.kill(worker1.pid, 'SIGINT'); }); if (!worker1.subprocessClosed) { await (0, enhancedEvents_1.enhancedOnce)(worker1, 'subprocessclose'); } expect(onDied).toHaveBeenCalledTimes(1); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(worker1.closed).toBe(true); expect(worker1.died).toBe(true); const worker2 = await mediasoup.createWorker({ logLevel: 'warn' }); onDied = jest.fn(); onObserverClose = jest.fn(); worker2.observer.once('close', onObserverClose); await new Promise((resolve, reject) => { worker2.on('died', () => { onDied(); if (onObserverClose.mock.calls.length > 0) { reject(new Error('observer "close" event emitted before worker "died" event')); } else if (worker2.closed) { resolve(); } else { reject(new Error('worker.closed is false')); } }); process.kill(worker2.pid, 'SIGTERM'); }); if (!worker2.subprocessClosed) { await (0, enhancedEvents_1.enhancedOnce)(worker2, 'subprocessclose'); } expect(onDied).toHaveBeenCalledTimes(1); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(worker2.closed).toBe(true); expect(worker2.died).toBe(true); const worker3 = await mediasoup.createWorker({ logLevel: 'warn' }); onDied = jest.fn(); onObserverClose = jest.fn(); worker3.observer.once('close', onObserverClose); await new Promise((resolve, reject) => { worker3.on('died', () => { onDied(); if (onObserverClose.mock.calls.length > 0) { reject(new Error('observer "close" event emitted before worker "died" event')); } else if (worker3.closed) { resolve(); } else { reject(new Error('worker.closed is false')); } }); process.kill(worker3.pid, 'SIGKILL'); }); if (!worker3.subprocessClosed) { await (0, enhancedEvents_1.enhancedOnce)(worker3, 'subprocessclose'); } expect(onDied).toHaveBeenCalledTimes(1); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(worker3.closed).toBe(true); expect(worker3.died).toBe(true); }, 5000); // Windows doesn't have some signals such as SIGPIPE, SIGALRM, SIGUSR1, SIGUSR2 // so we just skip this test in Windows. if (os.platform() !== 'win32') { test('worker process ignores PIPE, HUP, ALRM, USR1 and USR2 signals', async () => { const worker = await mediasoup.createWorker({ logLevel: 'warn' }); await new Promise((resolve, reject) => { worker.on('died', reject); process.kill(worker.pid, 'SIGPIPE'); process.kill(worker.pid, 'SIGHUP'); process.kill(worker.pid, 'SIGALRM'); process.kill(worker.pid, 'SIGUSR1'); process.kill(worker.pid, 'SIGUSR2'); setTimeout(() => { expect(worker.closed).toBe(false); worker.close(); worker.on('subprocessclose', resolve); }, 2000); }); }, 3000); }