import { describe, expect, it, vi } from 'vitest'; import type { FFmpegAdapter } from '../../src/ffmpeg/ffmpeg.types'; import { describeMountedInputAccess, mountJobFiles, } from '../../src/ffmpeg/virtual-fs'; function createFilesystemAdapter( options: { keepWorkDirectory?: boolean; rejectWorkerFs?: boolean } = {} ) { const directories = new Set(['/input', '/work']); const files = new Set(); const adapter = { createDir: vi.fn(async (path: string) => { directories.add(path); }), mount: vi.fn(async () => { if (options.rejectWorkerFs) { throw new Error('WORKERFS unavailable'); } }), unmount: vi.fn(async () => undefined), writeFile: vi.fn(async (path: string) => { files.add(path); }), deleteFile: vi.fn(async (path: string) => { files.delete(path); }), deleteDir: vi.fn(async (path: string) => { if (options.keepWorkDirectory && path.startsWith('/work/job-')) return; directories.delete(path); }), listDir: vi.fn(async (path: string) => [...directories] .filter( (entry) => entry !== path && entry.slice(0, entry.lastIndexOf('/')) === path ) .map((entry) => ({ name: entry.split('/').at(-1) ?? '', isDir: true, isLink: false, })) ), }; return adapter as unknown as FFmpegAdapter; } describe('per-job FFmpeg filesystem', () => { it('uses generated paths and verifies complete cleanup', async () => { const adapter = createFilesystemAdapter(); const mounted = await mountJobFiles( adapter, '../../job with separators', [new File(['source'], '../../private name.MP4')], ['../unsafe result.mp4'] ); expect(mounted.inputPaths).toEqual([ '/input/job-job-with-separators/source-0.mp4', ]); expect(mounted.outputPaths).toEqual([ '/work/job-job-with-separators/output-0.mp4', ]); expect(mounted).toMatchObject({ inputMode: 'workerfs', inputBytes: 6, copiedInputBytes: 0, }); expect(describeMountedInputAccess(mounted)).toContain( '0 bytes copied into engine memory' ); expect(mounted.inputPaths[0]).not.toContain('private'); expect(await mounted.cleanup()).toBe(true); }); it('accounts for and explains the actual memory-copy fallback', async () => { const adapter = createFilesystemAdapter({ rejectWorkerFs: true }); const mounted = await mountJobFiles( adapter, 'copy-fallback', [new File(['1234'], 'one.mp4'), new File(['567'], 'two.mp4')], ['result.mp4'] ); expect(mounted).toMatchObject({ inputMode: 'memory-copy', inputBytes: 7, copiedInputBytes: 7, }); expect(adapter.writeFile).toHaveBeenCalledTimes(2); expect(describeMountedInputAccess(mounted)).toBe( 'Input compatibility fallback: WORKERFS mounting was unavailable, so 7 bytes were copied into engine memory.' ); expect(await mounted.cleanup()).toBe(true); }); it('reports a directory that survives cleanup', async () => { const adapter = createFilesystemAdapter({ keepWorkDirectory: true }); const mounted = await mountJobFiles( adapter, 'job', [new File(['source'], 'source.wav')], ['result.wav'] ); expect(await mounted.cleanup()).toBe(false); }); });