101 lines
3.7 KiB
JavaScript
101 lines
3.7 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert');
|
|
const fs = require('fs');
|
|
const os = require('os');
|
|
const path = require('path');
|
|
const { detectKind, isVideoLikeKind, probeFileHead, summarizeFileStat } = require('../lib/file-probe');
|
|
|
|
function tmpWrite(name, buf) {
|
|
const p = path.join(os.tmpdir(), `mhu-probe-${Date.now()}-${name}`);
|
|
fs.writeFileSync(p, buf);
|
|
return p;
|
|
}
|
|
|
|
test('detectKind recognizes ISO-MP4 (ftyp box at offset 4)', () => {
|
|
const buf = Buffer.concat([Buffer.from([0x00, 0x00, 0x00, 0x20]), Buffer.from('ftypisom', 'ascii'), Buffer.alloc(8, 0)]);
|
|
assert.strictEqual(detectKind(buf), 'mp4-iso');
|
|
assert.strictEqual(isVideoLikeKind('mp4-iso'), true);
|
|
});
|
|
|
|
test('detectKind recognizes Matroska / WebM EBML header', () => {
|
|
const buf = Buffer.from([0x1A, 0x45, 0xDF, 0xA3, 0x01, 0x00]);
|
|
assert.strictEqual(detectKind(buf), 'matroska');
|
|
assert.strictEqual(isVideoLikeKind('matroska'), true);
|
|
});
|
|
|
|
test('detectKind recognizes AVI (RIFF...AVI )', () => {
|
|
const buf = Buffer.concat([Buffer.from('RIFF', 'ascii'), Buffer.from([0x00, 0x00, 0x00, 0x00]), Buffer.from('AVI ', 'ascii')]);
|
|
assert.strictEqual(detectKind(buf), 'avi');
|
|
});
|
|
|
|
test('detectKind recognizes FLV', () => {
|
|
const buf = Buffer.concat([Buffer.from('FLV', 'ascii'), Buffer.from([0x01])]);
|
|
assert.strictEqual(detectKind(buf), 'flv');
|
|
});
|
|
|
|
test('detectKind recognizes ASF (WMV)', () => {
|
|
const buf = Buffer.from([0x30, 0x26, 0xB2, 0x75, 0x00, 0x00]);
|
|
assert.strictEqual(detectKind(buf), 'asf-wmv');
|
|
});
|
|
|
|
test('detectKind recognizes MPEG-PS (00 00 01 BA)', () => {
|
|
const buf = Buffer.from([0x00, 0x00, 0x01, 0xBA, 0x00]);
|
|
assert.strictEqual(detectKind(buf), 'mpeg-ps');
|
|
});
|
|
|
|
test('detectKind recognizes JPEG (non-video)', () => {
|
|
const buf = Buffer.from([0xFF, 0xD8, 0xFF, 0xE0]);
|
|
assert.strictEqual(detectKind(buf), 'jpeg');
|
|
assert.strictEqual(isVideoLikeKind('jpeg'), false);
|
|
});
|
|
|
|
test('detectKind recognizes HTML response (non-video)', () => {
|
|
const buf = Buffer.from('<!DOCTYPE html><html><head>', 'ascii');
|
|
assert.strictEqual(detectKind(buf), 'html');
|
|
assert.strictEqual(isVideoLikeKind('html'), false);
|
|
});
|
|
|
|
test('detectKind returns empty for zero-length and unknown for noise', () => {
|
|
assert.strictEqual(detectKind(Buffer.alloc(0)), 'empty');
|
|
assert.strictEqual(detectKind(Buffer.from([0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF])), 'unknown');
|
|
});
|
|
|
|
test('probeFileHead reads first bytes and returns hex + kind for an MP4-like file', async () => {
|
|
const mp4Head = Buffer.concat([Buffer.from([0x00, 0x00, 0x00, 0x20]), Buffer.from('ftypisom', 'ascii'), Buffer.alloc(16, 0xAA)]);
|
|
const p = tmpWrite('fake.mp4', mp4Head);
|
|
try {
|
|
const res = await probeFileHead(p, 64);
|
|
assert.strictEqual(res.ok, true);
|
|
assert.strictEqual(res.kind, 'mp4-iso');
|
|
assert.strictEqual(res.isVideoLike, true);
|
|
assert.ok(res.headHex.startsWith('0000002066747970'));
|
|
assert.strictEqual(res.bytesRead, mp4Head.length);
|
|
} finally {
|
|
fs.unlinkSync(p);
|
|
}
|
|
});
|
|
|
|
test('probeFileHead returns ok:false with kind=unreadable for missing file', async () => {
|
|
const res = await probeFileHead(path.join(os.tmpdir(), `does-not-exist-${Date.now()}.mp4`), 32);
|
|
assert.strictEqual(res.ok, false);
|
|
assert.strictEqual(res.kind, 'unreadable');
|
|
assert.ok(res.error);
|
|
});
|
|
|
|
test('summarizeFileStat returns size + mtime for a real file', () => {
|
|
const p = tmpWrite('stat.bin', Buffer.alloc(123, 0xCC));
|
|
try {
|
|
const stat = summarizeFileStat(p);
|
|
assert.strictEqual(stat.size, 123);
|
|
assert.strictEqual(stat.isFile, true);
|
|
assert.ok(stat.mtime);
|
|
} finally {
|
|
fs.unlinkSync(p);
|
|
}
|
|
});
|
|
|
|
test('summarizeFileStat returns error for missing file', () => {
|
|
const stat = summarizeFileStat(path.join(os.tmpdir(), `does-not-exist-${Date.now()}.bin`));
|
|
assert.ok(stat.error);
|
|
});
|