test(kuna): scope short deadlines to hanging decompile work

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
This commit is contained in:
N0zoM1z0andgensokyo-dev authored and gensokyo-dev committed 2026-11-11 21:19:01 +08:00
1 parent 2127cff82d
commit 04042cf540
3 files changed
+97 -26

No files matched your search

@@ -32,7 +32,7 @@ it("runs a cold independent request without starting a project export", async ()
{
REA_KUNA_COMMAND: kuna,
REA_KUNA_CACHE_DIR: join(root, "cache"),
REA_KUNA_TIMEOUT_MS: "300",
REA_KUNA_TIMEOUT_MS: "10000",
},
{ platform: process.platform },
);
@@ -67,6 +67,11 @@ it("runs a cold independent request without starting a project export", async ()
functions: FUNCTIONS,
decompile: "hang",
});
await call("update_analysis_settings", {
changes: [
{ setting: "kuna.function_timeout_ms", action: "set", value: 300 },
],
});
const timeout = await harness.client.callTool({
name: "procedure_pseudo_code",
arguments: { procedure: "main", analysis: "independent_fresh" },
@@ -84,6 +89,7 @@ it("runs a cold independent request without starting a project export", async ()
limit: {
setting: "kuna.function_timeout_ms",
effective_value: 300,
source: "runtime",
update_mode: "runtime",
pending_restart: false,
minimum: 1,
@@ -96,6 +102,9 @@ it("runs a cold independent request without starting a project export", async ()
({ argv }) => argv[0] === "decompile-project",
),
).toHaveLength(0);
await call("update_analysis_settings", {
changes: [{ setting: "kuna.function_timeout_ms", action: "reset" }],
});
await setFakeKunaBehavior(kuna, { functions: FUNCTIONS });
await call("procedure_assembly", { procedure: "main" });
expect(
@@ -231,7 +240,7 @@ it("retains the independent run slot until an unproven stop is resolved", async
{
REA_KUNA_COMMAND: kuna,
REA_KUNA_CACHE_DIR: join(root, "cache"),
REA_KUNA_TIMEOUT_MS: "300",
REA_KUNA_TIMEOUT_MS: "10000",
},
{
platform: process.platform,
@@ -266,6 +275,15 @@ it("retains the independent run slot until an unproven stop is resolved", async
expect(
(await call("procedure_assembly", { procedure: "broken" })).isError,
).not.toBe(true);
expect(
(
await call("update_analysis_settings", {
changes: [
{ setting: "kuna.function_timeout_ms", action: "set", value: 300 },
],
})
).isError,
).not.toBe(true);
const first = await call("procedure_pseudo_code", {
procedure: "broken",
analysis: "independent_fresh",
@@ -314,6 +332,13 @@ it("retains the independent run slot until an unproven stop is resolved", async
expect((await call("close_binary", {})).isError).toBe(true);
unproven.release();
expect((await call("close_binary", {})).isError).not.toBe(true);
expect(
(
await call("update_analysis_settings", {
changes: [{ setting: "kuna.function_timeout_ms", action: "reset" }],
})
).isError,
).not.toBe(true);
await setFakeKunaBehavior(kuna, { functions: FUNCTIONS });
expect(
(await call("open_binary", { path: target, provider_id: "kuna" }))
@@ -1032,25 +1032,34 @@ it("keeps reporting a failed close and succeeds once a retry proves the stop", a
const { open } = await session(
"rea-kuna-close-retry-",
{ project: "hang", decompile: "hang" },
{ REA_KUNA_TIMEOUT_MS: "300" },
{ REA_KUNA_TIMEOUT_MS: "10000" },
unproven.launcher,
);
const client = open();
expect(
await client.execute("procedure_pseudo_code", { procedure: "main" }),
).toMatchObject({ ok: false, error: { cleanupIncomplete: true } });
const first = await client.close();
expect(first).toMatchObject({
ok: false,
error: { diagnostics: { reason: "decompile stop unproven" } },
});
// A retry that still cannot prove the stop keeps failing.
expect((await client.close()).ok).toBe(false);
try {
expect((await client.execute("list_procedures", {})).ok).toBe(true);
expect(
await runWithAnalysisOperationSnapshot(
{ revision: 1, overrides: { "kuna.function_timeout_ms": 300 } },
() => client.execute("procedure_pseudo_code", { procedure: "main" }),
),
).toMatchObject({ ok: false, error: { cleanupIncomplete: true } });
const first = await client.close();
expect(first).toMatchObject({
ok: false,
error: { diagnostics: { reason: "decompile stop unproven" } },
});
// A retry that still cannot prove the stop keeps failing.
expect((await client.close()).ok).toBe(false);
unproven.release();
expect(await client.close()).toEqual({ ok: true, value: null });
expect(await client.close()).toEqual({ ok: true, value: null });
unproven.release();
expect(await client.close()).toEqual({ ok: true, value: null });
expect(await client.close()).toEqual({ ok: true, value: null });
} finally {
unproven.release();
expect((await client.close()).ok).toBe(true);
}
});
it("reports an abandoned export's unproven cleanup from close", async () => {
@@ -1,4 +1,5 @@
import { expect, it as test, vi } from "vitest";
import { runWithAnalysisOperationSnapshot } from "../../../../src/domain/analysisOperationSnapshot.js";
import { awaitAcknowledgement } from "../../../fixtures/lifecycleAcknowledgement.js";
import { KunaRunSlots } from "../../../../src/kuna/KunaRunSlots.js";
@@ -183,29 +184,57 @@ it("keeps the slot of a run whose stop is unproven until close proves it", async
const { kuna, open } = await session(
"rea-kuna-single-retained-slot-",
{ project: "hang", decompile: "hang" },
{ REA_KUNA_TIMEOUT_MS: "300" },
{ REA_KUNA_TIMEOUT_MS: "10000" },
unproven.launcher,
1,
);
const client = open();
const waiter = new AbortController();
let queued: ReturnType<typeof client.execute> | undefined;
let restoreAcquire: (() => void) | undefined;
try {
expect((await client.execute("list_procedures", {})).ok).toBe(true);
expect(
await client.execute("procedure_pseudo_code", { procedure: "main" }),
await runWithAnalysisOperationSnapshot(
{ revision: 1, overrides: { "kuna.function_timeout_ms": 300 } },
() => client.execute("procedure_pseudo_code", { procedure: "main" }),
),
).toMatchObject({ ok: false, error: { cleanupIncomplete: true } });
// The timed-out tree may still run, so the next run must not start.
const queued = client.execute(
const admission = deferred<void>();
const acquire = KunaRunSlots.prototype.acquire;
let granted = false;
const requests = vi
.spyOn(KunaRunSlots.prototype, "acquire")
.mockImplementation(function (this: KunaRunSlots, signal) {
const pending = acquire.call(this, signal);
void pending.then(() => {
granted = true;
});
admission.resolve();
return pending;
});
restoreAcquire = () => requests.mockRestore();
queued = client.execute(
"procedure_pseudo_code",
{ procedure: "parse" },
{ signal: waiter.signal },
);
await new Promise((resolve) => setTimeout(resolve, 300));
await awaitAcknowledgement(
admission.promise,
queued,
"retained single-function slot",
);
await new Promise<void>((resolve) => setImmediate(resolve));
expect(granted).toBe(false);
expect(await decompilesOf(kuna)).toHaveLength(1);
waiter.abort();
expect(await queued).toMatchObject({
ok: false,
error: { _tag: "AnalysisCancelledError" },
});
restoreAcquire();
restoreAcquire = undefined;
expect((await client.close()).ok).toBe(false);
unproven.release();
expect(await client.close()).toEqual({ ok: true, value: null });
@@ -225,6 +254,8 @@ it("keeps the slot of a run whose stop is unproven until close proves it", async
waiter.abort();
unproven.release();
await client.close();
await Promise.allSettled([queued]);
restoreAcquire?.();
}
});
@@ -343,13 +374,17 @@ it("does not keep a failed run, so a repeat runs again", async () => {
const { kuna, open } = await session(
"rea-kuna-single-failed-not-kept-",
{ project: "hang", decompile: "hang" },
{ REA_KUNA_TIMEOUT_MS: "200" },
{ REA_KUNA_TIMEOUT_MS: "10000" },
);
const client = open();
try {
expect((await client.execute("list_procedures", {})).ok).toBe(true);
for (let repeat = 0; repeat < 2; repeat += 1)
expect(
await client.execute("procedure_pseudo_code", { procedure: "main" }),
await runWithAnalysisOperationSnapshot(
{ revision: 1, overrides: { "kuna.function_timeout_ms": 200 } },
() => client.execute("procedure_pseudo_code", { procedure: "main" }),
),
).toMatchObject({ ok: false });
expect(await decompilesOf(kuna)).toHaveLength(2);
} finally {
@@ -390,13 +425,15 @@ it("names the setting that owns a single-function deadline", async () => {
const { open } = await session(
"rea-kuna-function-deadline-",
{ project: "hang", decompile: "hang" },
{ REA_KUNA_TIMEOUT_MS: "300" },
{ REA_KUNA_TIMEOUT_MS: "10000" },
);
const client = open();
try {
const result = await client.execute("procedure_pseudo_code", {
procedure: "main",
});
expect((await client.execute("list_procedures", {})).ok).toBe(true);
const result = await runWithAnalysisOperationSnapshot(
{ revision: 1, overrides: { "kuna.function_timeout_ms": 300 } },
() => client.execute("procedure_pseudo_code", { procedure: "main" }),
);
if (result.ok) throw new Error("the hanging run answered");
expect(projectAnalysisError(result.error)).toMatchObject({
code: "provider_timeout",