fix11: runtime contracts and smoke stability

This commit is contained in:
2026-04-30 21:50:03 +05:00
parent 4a0d9569d1
commit a41f14067b
10 changed files with 105 additions and 88 deletions
+42 -9
View File
@@ -2,6 +2,27 @@ import type { RuntimeContext } from "../types/context";
import { info } from "../lib/log";
import { runHidden, runSecret, runVisible } from "../lib/process";
async function retry<T>(
attempts: number,
delayMs: number,
action: () => Promise<T>,
validate: (value: T) => boolean,
errorFactory: (value: T) => Error,
): Promise<T> {
let lastValue: T | undefined;
for (let i = 0; i < attempts; i += 1) {
const value = await action();
lastValue = value;
if (validate(value)) {
return value;
}
if (i < attempts - 1) {
await runHidden`sleep ${Math.max(1, Math.ceil(delayMs / 1000))}`;
}
}
throw errorFactory(lastValue as T);
}
export async function smoke(context: RuntimeContext): Promise<void> {
if (context.options.skipStart) {
info("service start and smoke checks skipped by flag");
@@ -40,10 +61,13 @@ export async function smoke(context: RuntimeContext): Promise<void> {
await runVisible`ss -H -lun | grep -q '0.0.0.0:${context.config.hysteriaPort} '`;
await runVisible`! ss -H -ltn | grep -q '\[::\]:${context.config.uiPort} '`;
await runVisible`! ss -H -lun | grep -q '\[::\]:${context.config.hysteriaPort} '`;
const invalidAuthResponse = await runSecret`curl -sS --max-time 5 -X POST -H 'Content-Type: application/json' --data '{"addr":"127.0.0.1:12345","auth":"invalid","tx":"0"}' http://127.0.0.1:${context.config.uiPort}/hui/hysteria2/auth`;
if (!/"ok"\s*:\s*false/.test(invalidAuthResponse)) {
throw new Error(`unexpected auth response for invalid credentials: ${invalidAuthResponse}`);
}
const invalidAuthResponse = await retry(
5,
1000,
async () => runSecret`curl -sS --max-time 5 -X POST -H 'Content-Type: application/json' --data '{"addr":"127.0.0.1:12345","auth":"invalid","tx":"0"}' http://127.0.0.1:${context.config.uiPort}/hui/hysteria2/auth`,
(response) => /"ok"\s*:\s*false/.test(response),
(response) => new Error(`unexpected auth response for invalid credentials: ${response}`),
);
for (let i = 0; i < 10; i += 1) {
const response = await runSecret`curl -sS --max-time 5 -X POST -H 'Content-Type: application/json' --data '{"addr":"127.0.0.1:12345","auth":"invalid","tx":"0"}' http://127.0.0.1:${context.config.uiPort}/hui/hysteria2/auth`;
@@ -57,12 +81,21 @@ export async function smoke(context: RuntimeContext): Promise<void> {
throw new Error("admin connection password is empty in bootstrap secret file");
}
const validAuthResponse = await runSecret`curl -sS --max-time 5 -X POST -H 'Content-Type: application/json' --data '{"addr":"127.0.0.1:12345","auth":"${adminConPass}","tx":"0"}' http://127.0.0.1:${context.config.uiPort}/hui/hysteria2/auth`;
if (!/"ok"\s*:\s*true/.test(validAuthResponse)) {
throw new Error(`unexpected auth response for valid credentials`);
}
const validAuthResponse = await retry(
10,
1000,
async () => runSecret`curl -sS --max-time 5 -X POST -H 'Content-Type: application/json' --data '{"addr":"127.0.0.1:12345","auth":"${adminConPass}","tx":"0"}' http://127.0.0.1:${context.config.uiPort}/hui/hysteria2/auth`,
(response) => /"ok"\s*:\s*true/.test(response),
() => new Error("unexpected auth response for valid credentials"),
);
await runHidden`curl -fsS --max-time 5 -H 'Authorization: ${context.config.hysteriaTrafficStatsSecret}' http://127.0.0.1:${context.config.hysteriaTrafficStatsPort}/online >/dev/null`;
await retry(
10,
1000,
async () => runSecret`curl -sS --max-time 5 -o /dev/null -w '%{http_code}' -H 'Authorization: ${context.config.hysteriaTrafficStatsSecret}' http://127.0.0.1:${context.config.hysteriaTrafficStatsPort}/online`,
(code) => /^2\d\d$/.test(code.trim()),
(code) => new Error(`unexpected trafficStats status for valid secret: ${code}`),
);
const deniedCode = await runSecret`curl -sS --max-time 5 -o /dev/null -w '%{http_code}' -H 'Authorization: invalid-hy2xs-secret' http://127.0.0.1:${context.config.hysteriaTrafficStatsPort}/online`;
if (!/(401|403)/.test(deniedCode)) {
throw new Error(`unexpected trafficStats status for invalid secret: ${deniedCode}`);