Spaces:
Paused
Paused
File size: 1,647 Bytes
2276d59 65fc551 2276d59 65fc551 2276d59 65fc551 2276d59 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | import { describe, it, expect, vi } from 'vitest';
import { EventEmitter } from 'node:events';
import { spawn } from 'node:child_process';
import { setupStreamListeners } from '../../src/utils/media/stream.util.js';
import { Response } from 'express';
import path from 'node:path';
import { Readable } from 'node:stream';
describe('FFmpeg Process Lifecycle & Sandbox Cleanup', () => {
it('Should systematically terminate active OS processes when client disconnects abruptly', async () => {
// spawn FFmpeg
// loop process
const fixturePath = path.resolve(
__dirname,
'../fixtures/audio/minimal_sine.mp3'
);
const dummyProcess = spawn(
'ffmpeg',
[
'-stream_loop',
'-1', // loop indefinitely
'-i',
fixturePath,
'-f',
'mp3',
'pipe:1',
],
{ detached: true }
);
const pid = dummyProcess.pid;
expect(pid).toBeGreaterThan(0);
// mock Response
const mockRes = new EventEmitter() as unknown as Response;
mockRes.writableEnded = false;
mockRes.write = vi.fn();
mockRes.end = vi.fn();
const totalBytes = { value: 0 };
// bind hooks
setupStreamListeners(
dummyProcess.stdout as unknown as Readable,
mockRes,
'test-client-id',
totalBytes
);
// wait init
await new Promise((resolve) => setTimeout(resolve, 50));
// trigger kill
dummyProcess.kill('SIGKILL');
// wait cleanup
await new Promise((resolve) => setTimeout(resolve, 150));
// verify death
// expect ESRCH
expect(() => process.kill(pid as number, 0)).toThrow();
});
});
|