Files
cms-website/tests/unit/magic-bytes.test.ts
T

76 lines
3.6 KiB
TypeScript
Raw Normal View History

2026-10-21 18:38:10 +08:00
// magic-bytes 单测(Plan 3 Task 4 Step 1):六类签名各正例 + 伪签名 null 例 +
// SVG 大小写不敏感 + 窗口边界(1KB 外不检出)+ 二进制签名优先于文本特征。
// 期望值全部手写字面量(与实现零共享——对拍而非引用)。
import { describe, expect, it } from 'vitest'
import { detectMediaType } from '../../apps/api/src/modules/import/magic-bytes.js'
const PNG_SIG = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])
describe('detectMediaType 手写签名表', () => {
it('六类二进制签名正例:PNG/JPEG/GIF87a/GIF89a/WEBP/PDF', () => {
expect(detectMediaType(Buffer.concat([PNG_SIG, Buffer.from('rest-of-png')]))).toStrictEqual({
type: 'image/png',
svg: false,
})
expect(detectMediaType(Buffer.from([0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10]))).toStrictEqual({
type: 'image/jpeg',
svg: false,
})
expect(detectMediaType(Buffer.from('GIF87a-more-gif'))).toStrictEqual({ type: 'image/gif', svg: false })
expect(detectMediaType(Buffer.from('GIF89a-more-gif'))).toStrictEqual({ type: 'image/gif', svg: false })
expect(
detectMediaType(Buffer.concat([Buffer.from('RIFF'), Buffer.from([0x24, 0x00, 0x00, 0x00]), Buffer.from('WEBPVP8 ')])),
).toStrictEqual({ type: 'image/webp', svg: false })
expect(detectMediaType(Buffer.from('%PDF-1.7\n%fake-payload'))).toStrictEqual({
type: 'application/pdf',
svg: false,
})
})
it('SVG 文本特征:大小写不敏感(<svg / <SVG / <Svg,含 xml 声明前导),svg=true', () => {
expect(detectMediaType(Buffer.from('<svg xmlns="http://www.w3.org/2000/svg"/>'))).toStrictEqual({
type: 'image/svg+xml',
svg: true,
})
expect(detectMediaType(Buffer.from('<?xml version="1.0"?><SVG onload="x()">'))).toStrictEqual({
type: 'image/svg+xml',
svg: true,
})
expect(detectMediaType(Buffer.from('<!-- c --><Svg width="1">'))).toStrictEqual({
type: 'image/svg+xml',
svg: true,
})
})
it('伪签名 / 纯文本 / 空缓冲 → null(未知签名不猜格式)', () => {
expect(detectMediaType(Buffer.from('hello plain text note'))).toBe(null)
expect(detectMediaType(Buffer.from([0x00, 0x01, 0x02, 0x03]))).toBe(null)
expect(detectMediaType(Buffer.alloc(0))).toBe(null)
})
it('RIFF 非 WEBP(WAV)不误报 webp → null', () => {
expect(
detectMediaType(Buffer.concat([Buffer.from('RIFF'), Buffer.from([0x24, 0x00, 0x00, 0x00]), Buffer.from('WAVEfmt ')])),
).toBe(null)
})
it('二进制签名优先:PNG 头 + 尾部 <svg 片段仍判 PNG(文本窗口只对非二进制生效)', () => {
const sneaky = Buffer.concat([PNG_SIG, Buffer.from('<svg onload="alert(1)"> trailing')])
expect(detectMediaType(sneaky)).toStrictEqual({ type: 'image/png', svg: false })
})
it('SVG 窗口 1KB 钉死:<svg 出现在 1KB 之后不检出 → null', () => {
const beyond = Buffer.concat([Buffer.alloc(1200, 0x20), Buffer.from('<svg>')])
expect(detectMediaType(beyond)).toBe(null)
})
it('SVG 窗口边界逐字节对拍:<svg 恰好收在 1024 字节内 → 检出;起点 1021 被截断 → null', () => {
// '<svg' 起点索引 1020:占 1020-1023,末字节恰在窗口(0-1023)内 → 检出
const flush = Buffer.concat([Buffer.alloc(1020, 0x20), Buffer.from('<svg')])
expect(detectMediaType(flush)).toStrictEqual({ type: 'image/svg+xml', svg: true })
// 起点索引 1021:窗口只含 '<sv','g' 被截在窗外 → 不检出
const truncated = Buffer.concat([Buffer.alloc(1021, 0x20), Buffer.from('<svg')])
expect(detectMediaType(truncated)).toBe(null)
})
2026-10-21 18:38:10 +08:00
})