test: retain completed binary observations on late cancellation

This commit is contained in:
morluto committed 2026-11-10 16:02:00 -05:00
1 parent ddb8abf855
commit b899c35419
8 files changed
+88 -32

No files matched your search

@@ -1,3 +1,4 @@
import { parseEvidence } from "../../domain/evidence.js";
import { expect, it } from "vitest";
import { AppleIpsService } from "./AppleIpsService.js";
import { APPLE_IPS_PROVIDER } from "../../domain/investigationProviders.js";
@@ -232,12 +233,13 @@ it.each([
},
);
it("discards an observation if the caller cancels while the provider completes", async () => {
it("retains a completed observation when the caller cancels as the provider completes", async () => {
const controller = new AbortController();
const reason = { request: "late AppleIps cancellation" };
const service = new AppleIpsService({
identity,
inspect: () => {
controller.abort();
controller.abort(reason);
return Promise.resolve(ok(report));
},
});
@@ -245,8 +247,13 @@ it("discards an observation if the caller cancels while the provider completes",
{ path: report.artifact.path },
{ signal: controller.signal },
);
expect(result.ok).toBe(false);
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisCancelledError);
if (result.ok) throw new Error("Expected late cancellation");
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
expect(result.error.cause).toBe(reason);
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
operation: "inspect_apple_ips",
normalized_result: report,
});
});
it.each([
@@ -1,3 +1,4 @@
import { parseEvidence } from "../../domain/evidence.js";
import { expect, it } from "vitest";
import { DevicetreeService } from "./DevicetreeService.js";
import { DEVICETREE_PROVIDER } from "../../domain/investigationProviders.js";
@@ -72,12 +73,13 @@ it("validates caller paths before invoking the provider", async () => {
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisInputError);
expect(calls).toBe(0);
});
it("rejects cancellation at provider completion", async () => {
it("retains a completed observation when the caller cancels as the provider completes", async () => {
const controller = new AbortController();
const reason = { request: "late Devicetree cancellation" };
const service = new DevicetreeService({
identity: DEVICETREE_PROVIDER,
inspect: () => {
controller.abort();
controller.abort(reason);
return Promise.resolve(ok(report()));
},
});
@@ -85,8 +87,13 @@ it("rejects cancellation at provider completion", async () => {
{ path: "/board.dtb" },
{ signal: controller.signal },
);
expect(result.ok).toBe(false);
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisCancelledError);
if (result.ok) throw new Error("Expected late cancellation");
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
expect(result.error.cause).toBe(reason);
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
operation: "inspect_devicetree",
normalized_result: report(),
});
});
it("rejects provider coverage and source-range inconsistencies", async () => {
for (const change of [
@@ -1,3 +1,4 @@
import { parseEvidence } from "../../domain/evidence.js";
import { expect, it } from "vitest";
import { ElfNotesService } from "./ElfNotesService.js";
import { ELF_NOTES_PROVIDER } from "../../domain/investigationProviders.js";
@@ -106,12 +107,13 @@ it("retains an examined empty table and rejects an uncounted table", async () =>
}
});
it("discards an observation if the caller cancels while the provider completes", async () => {
it("retains a completed observation when the caller cancels as the provider completes", async () => {
const controller = new AbortController();
const reason = { request: "late ElfNotes cancellation" };
const service = new ElfNotesService({
identity,
inspect: () => {
controller.abort();
controller.abort(reason);
return Promise.resolve(ok(report));
},
});
@@ -119,6 +121,11 @@ it("discards an observation if the caller cancels while the provider completes",
{ path: report.artifact.path },
{ signal: controller.signal },
);
expect(result.ok).toBe(false);
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisCancelledError);
if (result.ok) throw new Error("Expected late cancellation");
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
expect(result.error.cause).toBe(reason);
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
operation: "inspect_elf_notes",
normalized_result: report,
});
});
@@ -1,3 +1,4 @@
import { parseEvidence } from "../../domain/evidence.js";
import { expect, it } from "vitest";
import { ElfUnwindRangesService } from "./ElfUnwindRangesService.js";
import { ELF_UNWIND_RANGES_PROVIDER } from "../../domain/investigationProviders.js";
@@ -406,12 +407,13 @@ it("rejects a report that fails the output schema", async () => {
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisOutputError);
});
it("discards an observation if the caller cancels while the provider completes", async () => {
it("retains a completed observation when the caller cancels as the provider completes", async () => {
const controller = new AbortController();
const reason = { request: "late ElfUnwindRanges cancellation" };
const service = new ElfUnwindRangesService({
identity,
inspect: () => {
controller.abort();
controller.abort(reason);
return Promise.resolve(ok(report));
},
});
@@ -419,6 +421,11 @@ it("discards an observation if the caller cancels while the provider completes",
{ path: report.artifact.path },
{ signal: controller.signal },
);
expect(result.ok).toBe(false);
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisCancelledError);
if (result.ok) throw new Error("Expected late cancellation");
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
expect(result.error.cause).toBe(reason);
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
operation: "inspect_elf_unwind_ranges",
normalized_result: report,
});
});
@@ -1,3 +1,4 @@
import { parseEvidence } from "../../domain/evidence.js";
import { expect, it } from "vitest";
import { NativeInitializersService } from "./NativeInitializersService.js";
import { NATIVE_INITIALIZERS_PROVIDER } from "../../domain/investigationProviders.js";
@@ -113,12 +114,13 @@ it("rejects a slot offset outside the artifact", async () => {
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisOutputError);
});
it("discards an observation if the caller cancels while the provider completes", async () => {
it("retains a completed observation when the caller cancels as the provider completes", async () => {
const controller = new AbortController();
const reason = { request: "late NativeInitializers cancellation" };
const service = new NativeInitializersService({
identity,
inspect: () => {
controller.abort();
controller.abort(reason);
return Promise.resolve(ok(report));
},
});
@@ -126,6 +128,11 @@ it("discards an observation if the caller cancels while the provider completes",
{ path: report.artifact.path },
{ signal: controller.signal },
);
expect(result.ok).toBe(false);
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisCancelledError);
if (result.ok) throw new Error("Expected late cancellation");
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
expect(result.error.cause).toBe(reason);
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
operation: "inspect_native_initializers",
normalized_result: report,
});
});
@@ -1,3 +1,4 @@
import { parseEvidence } from "../../domain/evidence.js";
import { createHash } from "node:crypto";
import { inspectPeCertificatesInputSchema } from "../../domain/native/peCertificates.js";
import { peCertificateFixture } from "../../native/pe/PeCertificates.fixture.js";
@@ -49,12 +50,13 @@ it("rejects a relative path and extra arguments before reading", async () => {
expect(calls).toBe(0);
});
it("discards an observation if the caller cancels while the provider completes", async () => {
it("retains a completed observation when the caller cancels as the provider completes", async () => {
const controller = new AbortController();
const reason = { request: "late PeCertificates cancellation" };
const service = new PeCertificatesService({
identity,
inspect: () => {
controller.abort();
controller.abort(reason);
return Promise.resolve(ok(report));
},
});
@@ -62,8 +64,13 @@ it("discards an observation if the caller cancels while the provider completes",
{ path: report.artifact.path },
{ signal: controller.signal },
);
expect(result.ok).toBe(false);
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisCancelledError);
if (result.ok) throw new Error("Expected late cancellation");
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
expect(result.error.cause).toBe(reason);
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
operation: "inspect_pe_certificates",
normalized_result: report,
});
});
it("retains complete certificate provenance from the production parser", async () => {
@@ -1,3 +1,4 @@
import { parseEvidence } from "../../domain/evidence.js";
import { expect, it } from "vitest";
import { PeImportsService } from "./PeImportsService.js";
import { PE_IMPORTS_PROVIDER } from "../../domain/investigationProviders.js";
@@ -116,12 +117,13 @@ it.each(["import_directory", "delay_import_directory"] as const)(
},
);
it("discards an observation if the caller cancels while the provider completes", async () => {
it("retains a completed observation when the caller cancels as the provider completes", async () => {
const controller = new AbortController();
const reason = { request: "late PeImports cancellation" };
const service = new PeImportsService({
identity,
inspect: () => {
controller.abort();
controller.abort(reason);
return Promise.resolve(ok(report));
},
});
@@ -129,8 +131,13 @@ it("discards an observation if the caller cancels while the provider completes",
{ path: report.artifact.path },
{ signal: controller.signal },
);
expect(result.ok).toBe(false);
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisCancelledError);
if (result.ok) throw new Error("Expected late cancellation");
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
expect(result.error.cause).toBe(reason);
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
operation: "inspect_pe_imports",
normalized_result: report,
});
});
it("publishes every consumed directory span as its own Evidence location", async () => {
@@ -1,3 +1,4 @@
import { parseEvidence } from "../../domain/evidence.js";
import { expect, it } from "vitest";
import { WindowsShortcutService } from "./WindowsShortcutService.js";
import { WINDOWS_SHORTCUT_PROVIDER } from "../../domain/investigationProviders.js";
@@ -143,12 +144,13 @@ it("rejects complete coverage that still lists issues", async () => {
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisOutputError);
});
it("discards an observation if the caller cancels while the provider completes", async () => {
it("retains a completed observation when the caller cancels as the provider completes", async () => {
const controller = new AbortController();
const reason = { request: "late WindowsShortcut cancellation" };
const service = new WindowsShortcutService({
identity,
inspect: () => {
controller.abort();
controller.abort(reason);
return Promise.resolve(ok(report));
},
});
@@ -156,6 +158,11 @@ it("discards an observation if the caller cancels while the provider completes",
{ path: report.artifact.path },
{ signal: controller.signal },
);
expect(result.ok).toBe(false);
if (!result.ok) expect(result.error).toBeInstanceOf(AnalysisCancelledError);
if (result.ok) throw new Error("Expected late cancellation");
expect(result.error).toBeInstanceOf(AnalysisCancelledError);
expect(result.error.cause).toBe(reason);
expect(parseEvidence(result.error.partialObservation)).toMatchObject({
operation: "inspect_windows_shortcut",
normalized_result: report,
});
});