Initial Commit
This commit is contained in:
110
packages/foundation/data/bytes/src/encoding/encoding.test.ts
Normal file
110
packages/foundation/data/bytes/src/encoding/encoding.test.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
import fc from "fast-check";
|
||||
import {
|
||||
base64ToBytes,
|
||||
bytesToBase64,
|
||||
bytesToHex,
|
||||
bytesToUtf8,
|
||||
hexToBytes,
|
||||
utf8ToBytes,
|
||||
} from "./encoding.js";
|
||||
|
||||
describe("bytesToHex / hexToBytes", () => {
|
||||
it("round-trips arbitrary bytes", { timeout: 5000 }, () => {
|
||||
const input = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
|
||||
expect(hexToBytes(bytesToHex(input))).toEqual(input);
|
||||
});
|
||||
|
||||
it("bytesToHex produces lowercase hex", { timeout: 5000 }, () => {
|
||||
expect(bytesToHex(new Uint8Array([255]))).toBe("ff");
|
||||
});
|
||||
|
||||
it("bytesToHex handles empty array", { timeout: 5000 }, () => {
|
||||
expect(bytesToHex(new Uint8Array())).toBe("");
|
||||
});
|
||||
|
||||
it("hexToBytes handles empty string", { timeout: 5000 }, () => {
|
||||
expect(hexToBytes("")).toEqual(new Uint8Array());
|
||||
});
|
||||
|
||||
it("hexToBytes rejects odd-length string", { timeout: 5000 }, () => {
|
||||
expect(() => hexToBytes("abc")).toThrow();
|
||||
});
|
||||
|
||||
it("hexToBytes rejects non-hex chars", { timeout: 5000 }, () => {
|
||||
expect(() => hexToBytes("zz")).toThrow();
|
||||
});
|
||||
|
||||
it("hexToBytes rejects uppercase letters that are not hex", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
expect(() => hexToBytes("GG")).toThrow();
|
||||
});
|
||||
|
||||
it("hexToBytes accepts uppercase hex letters", { timeout: 5000 }, () => {
|
||||
expect(hexToBytes("FF")).toEqual(new Uint8Array([255]));
|
||||
});
|
||||
|
||||
it("hex round-trip for arbitrary bytes", { timeout: 30000 }, () => {
|
||||
fc.assert(
|
||||
fc.property(fc.uint8Array(), (bytes) => {
|
||||
expect(hexToBytes(bytesToHex(bytes))).toEqual(bytes);
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("bytesToBase64 / base64ToBytes", () => {
|
||||
it("round-trips arbitrary bytes", { timeout: 5000 }, () => {
|
||||
const input = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
expect(base64ToBytes(bytesToBase64(input))).toEqual(input);
|
||||
});
|
||||
|
||||
it("handles empty array", { timeout: 5000 }, () => {
|
||||
expect(bytesToBase64(new Uint8Array())).toBe("");
|
||||
expect(base64ToBytes("")).toEqual(new Uint8Array());
|
||||
});
|
||||
|
||||
it("rejects invalid base64", { timeout: 5000 }, () => {
|
||||
expect(() => base64ToBytes("not!valid@base64")).toThrow();
|
||||
});
|
||||
|
||||
it("rejects syntactically valid but malformed base64 (bad padding)", {
|
||||
timeout: 5000,
|
||||
}, () => {
|
||||
// "a=" passes the regex but atob rejects it (requires groups of 4 chars)
|
||||
expect(() => base64ToBytes("a=")).toThrow();
|
||||
});
|
||||
|
||||
it("base64 round-trip for arbitrary bytes", { timeout: 30000 }, () => {
|
||||
fc.assert(
|
||||
fc.property(fc.uint8Array(), (bytes) => {
|
||||
expect(base64ToBytes(bytesToBase64(bytes))).toEqual(bytes);
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("bytesToUtf8 / utf8ToBytes", () => {
|
||||
it("round-trips ASCII", { timeout: 5000 }, () => {
|
||||
const text = "Hello, world!";
|
||||
expect(bytesToUtf8(utf8ToBytes(text))).toBe(text);
|
||||
});
|
||||
|
||||
it("round-trips multibyte characters", { timeout: 5000 }, () => {
|
||||
const text = "こんにちは";
|
||||
expect(bytesToUtf8(utf8ToBytes(text))).toBe(text);
|
||||
});
|
||||
|
||||
it("handles empty string", { timeout: 5000 }, () => {
|
||||
expect(bytesToUtf8(utf8ToBytes(""))).toBe("");
|
||||
});
|
||||
|
||||
it("utf8 round-trip for arbitrary strings", { timeout: 30000 }, () => {
|
||||
fc.assert(
|
||||
fc.property(fc.string(), (str) => {
|
||||
expect(bytesToUtf8(utf8ToBytes(str))).toBe(str);
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user