Files

154 lines
5.0 KiB
TypeScript
Raw Permalink Normal View History

/**
* Expanded format detection tests covering uncovered magic byte branches:
* - CR3 (Canon ISOBMFF RAW with ftyp "crx ")
* - DPX reverse byte order
* - Cineon
* - Fujifilm RAF
* - Sigma X3F
* - Minolta MRW
* - RIFF with buffer too short for WEBP check
* - AVIF ftyp with buffer exactly 12 bytes (edge case)
* - CR3 ftyp with buffer too short
*/
import { detectFormat } from "@snapotter/image-engine";
import { describe, expect, it } from "vitest";
describe("detectFormat expanded magic byte branches", () => {
it("detects CR3 magic bytes (ftyp at offset 4 with crx brand)", async () => {
const buf = Buffer.alloc(16);
// ftyp at offset 4
buf[4] = 0x66;
buf[5] = 0x74;
buf[6] = 0x79;
buf[7] = 0x70;
// brand "crx " at offset 8
buf[8] = 0x63;
buf[9] = 0x72;
buf[10] = 0x78;
buf[11] = 0x20;
const format = await detectFormat(buf);
expect(format).toBe("cr3");
});
it("rejects ftyp box with non-CR3 brand when CR3 entry is checked", async () => {
const buf = Buffer.alloc(16);
buf[4] = 0x66;
buf[5] = 0x74;
buf[6] = 0x79;
buf[7] = 0x70;
// "mp41" brand -- not AVIF and not CR3
buf[8] = 0x6d;
buf[9] = 0x70;
buf[10] = 0x34;
buf[11] = 0x31;
const format = await detectFormat(buf);
// Should not be cr3 or avif
expect(format).not.toBe("cr3");
expect(format).not.toBe("avif");
});
it("rejects CR3 ftyp when buffer is too short for brand (< 12 bytes)", async () => {
const buf = Buffer.alloc(8);
buf[4] = 0x66;
buf[5] = 0x74;
buf[6] = 0x79;
buf[7] = 0x70;
const format = await detectFormat(buf);
expect(format).not.toBe("cr3");
});
it("detects DPX reverse byte order magic bytes", async () => {
const buf = Buffer.from([0x58, 0x50, 0x44, 0x53, 0, 0, 0, 0, 0, 0, 0, 0]);
const format = await detectFormat(buf);
expect(format).toBe("dpx");
});
it("detects Cineon magic bytes", async () => {
const buf = Buffer.from([0x80, 0x2a, 0x5f, 0xd7, 0, 0, 0, 0, 0, 0, 0, 0]);
const format = await detectFormat(buf);
expect(format).toBe("cin");
});
it("detects Fujifilm RAF magic bytes", async () => {
// "FUJIFILMCCD-RAW" = 15 bytes
const signature = Buffer.from("FUJIFILMCCD-RAW", "ascii");
const buf = Buffer.alloc(20);
signature.copy(buf, 0);
const format = await detectFormat(buf);
expect(format).toBe("raf");
});
it("detects Sigma X3F magic bytes (FOVb)", async () => {
const buf = Buffer.from([0x46, 0x4f, 0x56, 0x62, 0, 0, 0, 0, 0, 0, 0, 0]);
const format = await detectFormat(buf);
expect(format).toBe("x3f");
});
it("detects Minolta MRW magic bytes", async () => {
const buf = Buffer.from([0x00, 0x4d, 0x52, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0]);
const format = await detectFormat(buf);
expect(format).toBe("mrw");
});
it("RIFF header in 8-byte buffer is handled (Sharp may detect or magic bytes skip)", async () => {
// RIFF header in only 8 bytes -- the WEBP magic byte check requires 12 bytes,
// but Sharp's metadata() may still detect it as webp from the RIFF header alone.
const buf = Buffer.alloc(8);
buf[0] = 0x52;
buf[1] = 0x49;
buf[2] = 0x46;
buf[3] = 0x46;
const format = await detectFormat(buf);
// Sharp may report "webp" from the RIFF header, or magic bytes may skip it.
// Either way the function should not throw.
expect(typeof format).toBe("string");
});
it("detects AVIF ftyp with exactly 12-byte buffer (minimum for brand check)", async () => {
const buf = Buffer.alloc(12);
buf[4] = 0x66;
buf[5] = 0x74;
buf[6] = 0x79;
buf[7] = 0x70;
buf[8] = 0x61;
buf[9] = 0x76;
buf[10] = 0x69;
buf[11] = 0x66;
const format = await detectFormat(buf);
expect(format).toBe("avif");
});
it("buffer with only magic byte prefix but too short for full match returns unknown", async () => {
// PNG magic needs 4 bytes but buffer is only 3
const buf = Buffer.from([0x89, 0x50, 0x4e]);
const format = await detectFormat(buf);
expect(format).toBe("unknown");
});
it("buffer with ICO-like bytes but too short", async () => {
// ICO needs 4 bytes: 00 00 01 00
const buf = Buffer.from([0x00, 0x00, 0x01]);
const format = await detectFormat(buf);
expect(format).toBe("unknown");
});
it("two-byte buffer matching only first two bytes of a 4-byte signature", async () => {
// BMP starts with 0x42 0x4D (2 bytes) but needs at least 2 for match
const buf = Buffer.from([0x42, 0x4d]);
const format = await detectFormat(buf);
expect(format).toBe("bmp");
});
it("FITS magic needs 6 bytes, 5-byte buffer is too short", async () => {
const buf = Buffer.from([0x53, 0x49, 0x4d, 0x50, 0x4c]);
const format = await detectFormat(buf);
expect(format).toBe("unknown");
});
it("EPS ASCII magic needs 10 bytes, 9-byte buffer is too short", async () => {
const buf = Buffer.from([0x25, 0x21, 0x50, 0x53, 0x2d, 0x41, 0x64, 0x6f, 0x62]);
const format = await detectFormat(buf);
expect(format).toBe("unknown");
});
});