mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-08-22 03:18:54 +08:00
80 lines
2.7 KiB
TypeScript
80 lines
2.7 KiB
TypeScript
import { describe, expect, it } from "bun:test";
|
|
import { isBinaryContent } from "../src/mcp/binary-detection";
|
|
|
|
describe("isBinaryContent", () => {
|
|
describe("text content", () => {
|
|
it("treats ASCII as text", () => {
|
|
expect(isBinaryContent(Buffer.from("hello world\n"))).toBe(false);
|
|
});
|
|
|
|
it("treats multibyte UTF-8 as text", () => {
|
|
expect(isBinaryContent(Buffer.from("café — 日本語 🎉\n"))).toBe(false);
|
|
});
|
|
|
|
it("treats an empty file as text", () => {
|
|
expect(isBinaryContent(Buffer.from(""))).toBe(false);
|
|
});
|
|
|
|
it("treats CRLF and tabs as text", () => {
|
|
expect(isBinaryContent(Buffer.from("a\tb\r\nc\r\n"))).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("binary content", () => {
|
|
// The extensions below are the ones the previous allowlist covered, so
|
|
// these files were already committed correctly.
|
|
it("detects PNG", () => {
|
|
expect(
|
|
isBinaryContent(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a])),
|
|
).toBe(true);
|
|
});
|
|
|
|
// These are the regression cases: binary formats that were not on the
|
|
// allowlist and got decoded as UTF-8, corrupting the committed bytes.
|
|
it("detects BMP", () => {
|
|
expect(
|
|
isBinaryContent(Buffer.from([0x42, 0x4d, 0x36, 0x00, 0x00, 0x00])),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("detects SQLite databases", () => {
|
|
expect(isBinaryContent(Buffer.from("SQLite format 3\0", "binary"))).toBe(
|
|
true,
|
|
);
|
|
});
|
|
|
|
it("detects WebAssembly modules", () => {
|
|
expect(
|
|
isBinaryContent(Buffer.from([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00])),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("detects arbitrary invalid UTF-8 without NUL bytes", () => {
|
|
// Lone continuation bytes: no NUL, but not decodable as UTF-8 either.
|
|
expect(isBinaryContent(Buffer.from([0xc3, 0x28, 0xa0, 0xa1]))).toBe(true);
|
|
});
|
|
|
|
it("detects a truncated multibyte sequence", () => {
|
|
// First two bytes of a 3-byte character, cut short.
|
|
expect(isBinaryContent(Buffer.from([0xe6, 0x97]))).toBe(true);
|
|
});
|
|
});
|
|
|
|
it("round-trips text through UTF-8 without loss", () => {
|
|
const original = "acentuação, emoji 🚀, símbolos ±≠";
|
|
const buffer = Buffer.from(original);
|
|
|
|
expect(isBinaryContent(buffer)).toBe(false);
|
|
expect(buffer.toString("utf-8")).toBe(original);
|
|
});
|
|
|
|
it("preserves bytes that a UTF-8 decode would have replaced", () => {
|
|
const bytes = Buffer.from([0xff, 0xd8, 0xff, 0xe0, 0x10, 0x4a]);
|
|
|
|
expect(isBinaryContent(bytes)).toBe(true);
|
|
// What the old text path would have produced, versus base64.
|
|
expect(Buffer.from(bytes.toString("utf-8"), "utf-8")).not.toEqual(bytes);
|
|
expect(Buffer.from(bytes.toString("base64"), "base64")).toEqual(bytes);
|
|
});
|
|
});
|