178 lines
5.3 KiB
TypeScript
178 lines
5.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
parseGoModuleBytes,
|
|
parseGoModuleText,
|
|
} from "../../../src/go/GoModuleText.js";
|
|
|
|
describe("Go producer module text", () => {
|
|
it("preserves local replacements, empty fields and ordered duplicate build settings", () => {
|
|
const parsed = parseGoModuleText(
|
|
"path\texample.invalid/app\nmod\texample.invalid/app\t(devel)\t\ndep\texample.invalid/lib\tv1.2.3\th1:bytes\n=>\t../local lib\t\t\nbuild\tGOOS=linux\nbuild\tGOOS=custom\nbuild\t__proto__=kept\n",
|
|
);
|
|
expect(parsed).toMatchObject({
|
|
path: "example.invalid/app",
|
|
main: { version: "(devel)", sum: "" },
|
|
dependencies: [
|
|
{
|
|
path: "example.invalid/lib",
|
|
version: "v1.2.3",
|
|
sum: "h1:bytes",
|
|
replacement: { path: "../local lib", version: "", sum: "" },
|
|
},
|
|
],
|
|
settings: [
|
|
{ key: "GOOS", value: "linux" },
|
|
{ key: "GOOS", value: "custom" },
|
|
{ key: "__proto__", value: "kept" },
|
|
],
|
|
complete: true,
|
|
unparsed_lines: [],
|
|
unparsed_line_bytes_base64: [],
|
|
});
|
|
});
|
|
|
|
it("decodes Go quoting including byte, octal and Unicode escapes without JSON substitution", () => {
|
|
const text =
|
|
String.raw`build\t"key=quoted"="\a\v\xC3\xA9\303\251\u263a\U0001F680"`.replace(
|
|
"\\t",
|
|
"\t",
|
|
) +
|
|
"\n" +
|
|
"build\traw=`a\rb`\n";
|
|
expect(parseGoModuleText(text)).toMatchObject({
|
|
settings: [
|
|
{ key: "key=quoted", value: "\x07\x0béé☺🚀" },
|
|
{ key: "raw", value: "ab" },
|
|
],
|
|
complete: true,
|
|
});
|
|
});
|
|
|
|
it("reports unparsed records and malformed escaped bytes while retaining observed fields", () => {
|
|
const text =
|
|
'path\tapp\nmod\tapp\t(devel)\nbuild\tbad="\\xff"\nfuture\tdata\nbuild\tGOARCH=amd64';
|
|
expect(parseGoModuleText(text)).toMatchObject({
|
|
path: "app",
|
|
main: { sum: null },
|
|
settings: [],
|
|
complete: false,
|
|
unparsed_lines: [
|
|
'build\tbad="\\xff"',
|
|
"future\tdata",
|
|
"build\tGOARCH=amd64",
|
|
],
|
|
});
|
|
});
|
|
|
|
it("does not attach a replacement after a malformed module declaration", () => {
|
|
const parsed = parseGoModuleText(
|
|
"dep\tfirst\tv1\ndep\tmalformed\n=>\tlocal\t\t\n",
|
|
);
|
|
expect(parsed.dependencies).toEqual([
|
|
{ path: "first", version: "v1", sum: null, replacement: null },
|
|
]);
|
|
expect(parsed.complete).toBe(false);
|
|
});
|
|
|
|
it("preserves duplicate singleton declarations as unknown instead of silently overwriting", () => {
|
|
expect(
|
|
parseGoModuleText(
|
|
"path\tfirst\npath\tsecond\nmod\tfirst\tv1\nmod\tsecond\tv2\n",
|
|
),
|
|
).toMatchObject({
|
|
path: "first",
|
|
main: { path: "first", version: "v1" },
|
|
unparsed_lines: ["path\tsecond", "mod\tsecond\tv2"],
|
|
complete: false,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Go producer module bytes", () => {
|
|
it("retains byte-valued producer settings and parses surrounding UTF-8 records", () => {
|
|
const setting = Buffer.concat([
|
|
Buffer.from("build\t-tags="),
|
|
Buffer.from([0xff]),
|
|
]);
|
|
const trailing = Buffer.from([0xfe]);
|
|
const parsed = parseGoModuleBytes(
|
|
Buffer.concat([
|
|
Buffer.from("path\tapp\nmod\tapp\t(devel)\t\nbuild\tGOOS=linux\n"),
|
|
setting,
|
|
Buffer.from("\nbuild\tGOARCH=amd64\n"),
|
|
trailing,
|
|
]),
|
|
);
|
|
expect(parsed).toEqual({
|
|
path: "app",
|
|
main: { path: "app", version: "(devel)", sum: "", replacement: null },
|
|
dependencies: [],
|
|
settings: [
|
|
{ key: "GOOS", value: "linux" },
|
|
{ key: "GOARCH", value: "amd64" },
|
|
],
|
|
unparsed_lines: [],
|
|
unparsed_line_bytes_base64: [
|
|
setting.toString("base64"),
|
|
trailing.toString("base64"),
|
|
],
|
|
complete: false,
|
|
});
|
|
});
|
|
|
|
it.each(["mod", "dep", "=>"])(
|
|
"does not bind a replacement through an undecodable %s record",
|
|
(record) => {
|
|
const invalid = Buffer.concat([
|
|
Buffer.from(`${record}\t`),
|
|
Buffer.from([0xff]),
|
|
Buffer.from("\tv2\t"),
|
|
]);
|
|
expect(
|
|
parseGoModuleBytes(
|
|
Buffer.concat([
|
|
Buffer.from("dep\tfirst\tv1\n"),
|
|
invalid,
|
|
Buffer.from("\n=>\tlocal\t\t\n"),
|
|
]),
|
|
),
|
|
).toMatchObject({
|
|
dependencies: [
|
|
{ path: "first", version: "v1", sum: null, replacement: null },
|
|
],
|
|
unparsed_lines: ["=>\tlocal\t\t"],
|
|
unparsed_line_bytes_base64: [invalid.toString("base64")],
|
|
complete: false,
|
|
});
|
|
},
|
|
);
|
|
|
|
it.each(["build\t-tags=", "future\t"])(
|
|
"preserves replacement context through an undecodable %s record",
|
|
(prefix) => {
|
|
const invalid = Buffer.concat([Buffer.from(prefix), Buffer.from([0xff])]);
|
|
expect(
|
|
parseGoModuleBytes(
|
|
Buffer.concat([
|
|
Buffer.from("dep\tfirst\tv1\n"),
|
|
invalid,
|
|
Buffer.from("\n=>\tlocal\t\t\n"),
|
|
]),
|
|
),
|
|
).toMatchObject({
|
|
dependencies: [
|
|
{
|
|
path: "first",
|
|
version: "v1",
|
|
sum: null,
|
|
replacement: { path: "local", version: "", sum: "" },
|
|
},
|
|
],
|
|
unparsed_lines: [],
|
|
unparsed_line_bytes_base64: [invalid.toString("base64")],
|
|
complete: false,
|
|
});
|
|
},
|
|
);
|
|
});
|