Files

45 lines
1.6 KiB
TypeScript
Raw Permalink Normal View History

2026-10-14 12:12:13 +00:00
// @vitest-environment node
import { readFileSync } from "node:fs";
import { expect, it } from "vitest";
import { verifyAudioAsset } from "../src/audio/integrity";
// 신뢰 기준은 JS 번들에 고정한 manifest다. 요청 파일이 자기 해시를 선언할 수 없다.
it("109개 승인 WAV만 SHA-256·bytes·형식 검증을 통과한다", async () => {
let count = 0;
for (const directory of ["audio", "ambience"]) {
const manifest = JSON.parse(
readFileSync(`public/${directory}/manifest.json`, "utf8"),
);
for (const entry of manifest.files) {
const bytes = Uint8Array.from(
readFileSync(`public/${directory}/${entry.file}`),
).buffer;
await expect(
verifyAudioAsset(`/${directory}/${entry.file}?v=0.2.5`, bytes),
).resolves.toBeUndefined();
count++;
}
}
expect(count).toBe(109);
});
it("변조·다른 파일·외부 URL·이전 캐시·축약 응답은 decode 전에 거부한다", async () => {
const bytes = Uint8Array.from(readFileSync("public/ambience/street.wav"));
for (const url of [
"/ambience/rain.wav?v=0.2.5",
"/ambience/street.wav?v=0.2.3",
"https://external.example/ambience/street.wav?v=0.2.5",
"/ambience/unknown.wav?v=0.2.5",
]) {
await expect(verifyAudioAsset(url, bytes.slice().buffer)).rejects.toThrow();
}
const corrupt = bytes.slice();
corrupt[100] = corrupt[100]! ^ 1;
await expect(
verifyAudioAsset("/ambience/street.wav?v=0.2.5", corrupt.buffer),
).rejects.toThrow();
await expect(
verifyAudioAsset("/ambience/street.wav?v=0.2.5", bytes.slice(0, -2).buffer),
).rejects.toThrow();
});