107 lines
4.0 KiB
TypeScript
107 lines
4.0 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import {
|
|
HYSTERIA_HASHES_ASSET,
|
|
HYSTERIA_LINUX_AMD64_ASSET,
|
|
selectLatestStableRelease,
|
|
type GithubRelease,
|
|
} from "../src/build/hysteriaRelease";
|
|
|
|
function assetUrl(tag: string, name: string): string {
|
|
return `https://github.com/HyNetworks/hysteria/releases/download/${tag}/${name}`;
|
|
}
|
|
|
|
function release(tag: string): GithubRelease {
|
|
return {
|
|
tag_name: tag,
|
|
draft: false,
|
|
prerelease: false,
|
|
published_at: "2026-08-23T00:59:00Z",
|
|
assets: [
|
|
{
|
|
name: HYSTERIA_LINUX_AMD64_ASSET,
|
|
browser_download_url: assetUrl(tag, HYSTERIA_LINUX_AMD64_ASSET),
|
|
},
|
|
{
|
|
name: HYSTERIA_HASHES_ASSET,
|
|
browser_download_url: assetUrl(tag, HYSTERIA_HASHES_ASSET),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
function srcFile(...parts: string[]): string {
|
|
return readFileSync(join(import.meta.dir, "..", "src", ...parts), "utf8");
|
|
}
|
|
|
|
describe("release rollover", () => {
|
|
// Пакет A собран сегодня, пакет B — завтра. Выход новой upstream-версии
|
|
// не должен менять содержимое уже собранного пакета A.
|
|
const upstreamToday = [release("app/v2.12.1"), release("app/v2.12.2")];
|
|
const upstreamTomorrow = [...upstreamToday, release("app/v2.12.3")];
|
|
|
|
test("сборка сегодня закрепляет 2.12.2", () => {
|
|
expect(selectLatestStableRelease(upstreamToday).version).toBe("v2.12.2");
|
|
});
|
|
|
|
test("сборка завтра закрепляет 2.12.3", () => {
|
|
expect(selectLatestStableRelease(upstreamTomorrow).version).toBe("v2.12.3");
|
|
});
|
|
|
|
test("резолв чистый: тот же список всегда даёт тот же результат", () => {
|
|
const first = selectLatestStableRelease(upstreamToday);
|
|
const second = selectLatestStableRelease(upstreamToday);
|
|
expect(first).toEqual(second);
|
|
});
|
|
});
|
|
|
|
describe("install-time никогда не резолвит latest", () => {
|
|
// Гарантия acceptance-критерия: "latest" относится к моменту сборки,
|
|
// поэтому переустановка старого пакета обязана ставить старую версию.
|
|
const installTimeSources = [
|
|
["commands", "install.ts"],
|
|
["steps", "hysteria.ts"],
|
|
["lib", "packageMeta.ts"],
|
|
["commands", "reconfigure.ts"],
|
|
];
|
|
|
|
test("install-time код не импортирует build-time резолвер", () => {
|
|
for (const parts of installTimeSources) {
|
|
expect(srcFile(...parts)).not.toContain("build/hysteriaRelease");
|
|
}
|
|
});
|
|
|
|
test("install-time код не обращается к upstream API и не использует moving latest", () => {
|
|
for (const parts of installTimeSources) {
|
|
const source = srcFile(...parts);
|
|
expect(source).not.toContain("api.github.com");
|
|
expect(source).not.toContain("download.hysteria.network");
|
|
expect(source).not.toMatch(/releases\/latest/);
|
|
}
|
|
});
|
|
|
|
test("установка берёт версию, url и sha256 только из metadata пакета", () => {
|
|
const install = srcFile("commands", "install.ts");
|
|
for (const key of ["hysteria.version", "hysteria.url", "hysteria.sha256"]) {
|
|
expect(install).toMatch(
|
|
new RegExp(
|
|
`readPackageValue\\(\\s*options\\.packageDir,\\s*"${key.replace(".", "\\.")}"`,
|
|
),
|
|
);
|
|
}
|
|
});
|
|
|
|
test("отсутствие любой части lock-метаданных прерывает установку", () => {
|
|
expect(srcFile("commands", "install.ts")).toContain(
|
|
"missing Hysteria lock metadata in package",
|
|
);
|
|
});
|
|
|
|
test("установленный бинарник сверяется с закреплённой версией", () => {
|
|
const step = srcFile("steps", "hysteria.ts");
|
|
expect(step).toContain("installed Hysteria version mismatch");
|
|
expect(step).toContain("sha256sum -c -");
|
|
});
|
|
});
|