mirror of
https://github.com/morluto/rea.git
synced 2026-10-18 20:10:13 -05:00
fix(ci): align FAT fixtures and consolidate duplicated workflow helpers
Declare the synthetic 4 KiB Mach-O slice alignment accurately while preserving the IDA thinning scenario. Share web cleanup aggregation and process-trace fixture facts instead of duplicating them across consumers and tests; keep the 3% duplication threshold unchanged. Validation: npm run check:ci, test discovery, and 42 focused IDA, process-trace, web workflow and cleanup boundary tests. Duplication falls from 3.01% to 2.99%.
This commit is contained in:
1 parent
67c7a24e60
commit
a0317cf732
7 files changed
+87
-158
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import { closeOwnedWebResources } from "./closeOwnedWebResources.js";
|
||||
import { isAbsolute } from "node:path";
|
||||
import { z } from "zod";
|
||||
import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
@@ -271,21 +272,6 @@ export class WebModuleTraceService {
|
||||
}
|
||||
}
|
||||
|
||||
const closeOwnedWebResources = async (
|
||||
close: readonly ((() => Promise<void>) | undefined)[],
|
||||
message: string,
|
||||
): Promise<void> => {
|
||||
const results = await Promise.allSettled(
|
||||
close.flatMap((owner) =>
|
||||
owner === undefined ? [] : [Promise.resolve().then(owner)],
|
||||
),
|
||||
);
|
||||
const failures = results.flatMap((result) =>
|
||||
result.status === "rejected" ? [result.reason] : [],
|
||||
);
|
||||
if (failures.length > 0) throw new AggregateError(failures, message);
|
||||
};
|
||||
|
||||
const admitContext = (
|
||||
value: string,
|
||||
path: readonly string[],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { closeOwnedWebResources } from "./closeOwnedWebResources.js";
|
||||
import { createHash } from "node:crypto";
|
||||
import { isAbsolute } from "node:path";
|
||||
import { z } from "zod";
|
||||
@@ -181,20 +182,6 @@ export class WebSourceLocationService {
|
||||
}
|
||||
}
|
||||
|
||||
const closeOwnedWebResources = async (
|
||||
close: readonly ((() => Promise<void>) | undefined)[],
|
||||
message: string,
|
||||
): Promise<void> => {
|
||||
const results = await Promise.allSettled(
|
||||
close.flatMap((owner) =>
|
||||
owner === undefined ? [] : [Promise.resolve().then(owner)],
|
||||
),
|
||||
);
|
||||
const failures = results.flatMap((result) =>
|
||||
result.status === "rejected" ? [result.reason] : [],
|
||||
);
|
||||
if (failures.length > 0) throw new AggregateError(failures, message);
|
||||
};
|
||||
const invalidOutput = (message: string): Result<never, AnalysisError> =>
|
||||
err(new AnalysisOutputError(OPERATION, message));
|
||||
const invalid = (
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/** Attempt every web workflow cleanup owner and report all failures. */
|
||||
export const closeOwnedWebResources = async (
|
||||
close: readonly ((() => Promise<void>) | undefined)[],
|
||||
message: string,
|
||||
): Promise<void> => {
|
||||
const results = await Promise.allSettled(
|
||||
close.flatMap((owner) =>
|
||||
owner === undefined ? [] : [Promise.resolve().then(owner)],
|
||||
),
|
||||
);
|
||||
const failures = results.flatMap((result) =>
|
||||
result.status === "rejected" ? [result.reason] : [],
|
||||
);
|
||||
if (failures.length > 0) throw new AggregateError(failures, message);
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { ProcessTraceSpecification } from "./processTraceSpecification.js";
|
||||
import { compareProcessCaptures } from "./processComparison.js";
|
||||
import { parseProcessCapture } from "./processCaptureParsing.js";
|
||||
import { EMPTY_PROCESS_CAPTURE_EXAMPLE } from "./processCaptureExample.js";
|
||||
@@ -112,3 +113,56 @@ export const compareUnverifiedProcessCaptures = (
|
||||
parseProcessCapture(right),
|
||||
options,
|
||||
);
|
||||
|
||||
/** One journal and its matching declared trace, shared by domain and adapter checks. */
|
||||
export const processTraceCaptureFixture = () => {
|
||||
const capture = {
|
||||
...EMPTY_PROCESS_CAPTURE_EXAMPLE,
|
||||
event_journal: [
|
||||
{ capture_order: 0, collection: "filesystem_checkpoints", index: 0 },
|
||||
{ capture_order: 1, collection: "lifecycle", index: 0 },
|
||||
{ capture_order: 2, collection: "lifecycle", index: 1 },
|
||||
{ capture_order: 3, collection: "filesystem_checkpoints", index: 1 },
|
||||
],
|
||||
} as const;
|
||||
const [before, after] = capture.filesystem_checkpoints;
|
||||
if (before === undefined || after === undefined)
|
||||
throw new Error(
|
||||
"Trace fixture requires before and after filesystem checkpoints",
|
||||
);
|
||||
const traceSpecification: ProcessTraceSpecification = {
|
||||
events: [
|
||||
{
|
||||
id: "before",
|
||||
source: "filesystem",
|
||||
exact: before,
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
{
|
||||
id: "exit",
|
||||
source: "lifecycle",
|
||||
exact: { event: "exit", ...capture.exit },
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
{
|
||||
id: "settlement",
|
||||
source: "lifecycle",
|
||||
exact: { event: "settlement", ...capture.settlement },
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
{
|
||||
id: "after",
|
||||
source: "filesystem",
|
||||
exact: after,
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
],
|
||||
language: {
|
||||
kind: "finite_traces",
|
||||
variants: [
|
||||
{ id: "normal", trace: ["before", "exit", "settlement", "after"] },
|
||||
],
|
||||
},
|
||||
};
|
||||
return { capture, traceSpecification };
|
||||
};
|
||||
@@ -1,72 +1,13 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { EMPTY_PROCESS_CAPTURE_EXAMPLE } from "./processCaptureExample.js";
|
||||
import { accountFullyObservedProcessCapture } from "./processCapture.fixture.js";
|
||||
import {
|
||||
processTraceCaptureFixture,
|
||||
accountFullyObservedProcessCapture,
|
||||
} from "./processCapture.fixture.js";
|
||||
import { compareProcessCaptures } from "./processComparison.js";
|
||||
import { parseProcessCapture } from "./processCaptureParsing.js";
|
||||
import type { ProcessTraceSpecification } from "./processTraceSpecification.js";
|
||||
const beforeCheckpoint = {
|
||||
name: "before",
|
||||
at_ms: 0,
|
||||
files: [],
|
||||
effects: [],
|
||||
truncated: false,
|
||||
};
|
||||
const afterCheckpoint = {
|
||||
name: "after_settlement",
|
||||
at_ms: 50,
|
||||
files: [],
|
||||
effects: [],
|
||||
truncated: false,
|
||||
};
|
||||
|
||||
const capture = {
|
||||
...EMPTY_PROCESS_CAPTURE_EXAMPLE,
|
||||
event_journal: [
|
||||
{ capture_order: 0, collection: "filesystem_checkpoints", index: 0 },
|
||||
{ capture_order: 1, collection: "lifecycle", index: 0 },
|
||||
{ capture_order: 2, collection: "lifecycle", index: 1 },
|
||||
{ capture_order: 3, collection: "filesystem_checkpoints", index: 1 },
|
||||
],
|
||||
} as const;
|
||||
|
||||
const traceSpecification: ProcessTraceSpecification = {
|
||||
events: [
|
||||
{
|
||||
id: "before",
|
||||
source: "filesystem",
|
||||
exact: beforeCheckpoint,
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
{
|
||||
id: "exit",
|
||||
source: "lifecycle",
|
||||
exact: { event: "exit", ...capture.exit },
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
{
|
||||
id: "settlement",
|
||||
source: "lifecycle",
|
||||
exact: { event: "settlement", ...capture.settlement },
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
{
|
||||
id: "after",
|
||||
source: "filesystem",
|
||||
exact: afterCheckpoint,
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
],
|
||||
language: {
|
||||
kind: "finite_traces",
|
||||
variants: [
|
||||
{
|
||||
id: "normal",
|
||||
trace: ["before", "exit", "settlement", "after"],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const { capture, traceSpecification } = processTraceCaptureFixture();
|
||||
|
||||
describe("declared trace comparison nonconformance", () => {
|
||||
it("does not call identical captures changed when both violate the language", () => {
|
||||
|
||||
@@ -40,6 +40,7 @@ interface Layout {
|
||||
readonly cpu: number;
|
||||
readonly offset: number;
|
||||
readonly size: number;
|
||||
readonly alignmentExponent?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,12 +58,12 @@ const largeUniversalTarget = async (
|
||||
const bytes = Buffer.alloc(total);
|
||||
bytes.writeUInt32BE(0xcafebabe, 0);
|
||||
bytes.writeUInt32BE(layout.length, 4);
|
||||
layout.forEach(({ cpu, offset, size }, index) => {
|
||||
layout.forEach(({ cpu, offset, size, alignmentExponent = 14 }, index) => {
|
||||
const entry = 8 + index * 20;
|
||||
bytes.writeUInt32BE(cpu, entry);
|
||||
bytes.writeUInt32BE(offset, entry + 8);
|
||||
bytes.writeUInt32BE(size, entry + 12);
|
||||
bytes.writeUInt32BE(14, entry + 16);
|
||||
bytes.writeUInt32BE(alignmentExponent, entry + 16);
|
||||
bytes.fill(0x11 * (index + 1), offset, offset + size);
|
||||
thinMach(0xfeedfacf, cpu).copy(bytes, offset);
|
||||
});
|
||||
@@ -122,7 +123,12 @@ describe("IDA workspace input thinning", () => {
|
||||
async () => {
|
||||
const { bytes, target } = await largeUniversalTarget(
|
||||
[
|
||||
{ cpu: 0x01000007, offset: 4096, size: 8480 },
|
||||
{
|
||||
cpu: 0x01000007,
|
||||
offset: 4096,
|
||||
size: 8480,
|
||||
alignmentExponent: 12,
|
||||
},
|
||||
{ cpu: 0x0100000c, offset: 16384, size: 33464 },
|
||||
{ cpu: 0x00000007, offset: 65536, size: 33464 },
|
||||
],
|
||||
|
||||
@@ -9,76 +9,16 @@ import { createTestBinarySession } from "../../fixtures/binarySession.js";
|
||||
import type { AnalysisClient } from "../../../src/application/AnalysisProvider.js";
|
||||
import { compareProcessEvidenceFiles } from "../../../src/application/process/ProcessCli.js";
|
||||
import { PROCESS_PROVIDER } from "../../../src/domain/process/processEvidenceProvider.js";
|
||||
import { EMPTY_PROCESS_CAPTURE_EXAMPLE } from "../../../src/domain/process/processCaptureExample.js";
|
||||
import { processTraceCaptureFixture } from "../../../src/domain/process/processCapture.fixture.js";
|
||||
import { createEvidence, parseEvidence } from "../../../src/domain/evidence.js";
|
||||
import { jsonValueSchema } from "../../../src/domain/jsonValue.js";
|
||||
import type { ProcessTraceSpecification } from "../../../src/domain/process/processTraceSpecification.js";
|
||||
import { createServer } from "../../../src/server/createServer.js";
|
||||
import { observed as ok } from "../../fixtures/analysisExecution.js";
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
|
||||
const resources: Array<{ close(): Promise<void> }> = [];
|
||||
const temporaryRoots: string[] = [];
|
||||
const beforeCheckpoint = {
|
||||
name: "before",
|
||||
at_ms: 0,
|
||||
files: [],
|
||||
effects: [],
|
||||
truncated: false,
|
||||
};
|
||||
const afterCheckpoint = {
|
||||
name: "after_settlement",
|
||||
at_ms: 50,
|
||||
files: [],
|
||||
effects: [],
|
||||
truncated: false,
|
||||
};
|
||||
const capture = {
|
||||
...EMPTY_PROCESS_CAPTURE_EXAMPLE,
|
||||
event_journal: [
|
||||
{ capture_order: 0, collection: "filesystem_checkpoints", index: 0 },
|
||||
{ capture_order: 1, collection: "lifecycle", index: 0 },
|
||||
{ capture_order: 2, collection: "lifecycle", index: 1 },
|
||||
{ capture_order: 3, collection: "filesystem_checkpoints", index: 1 },
|
||||
],
|
||||
} as const;
|
||||
const traceSpecification: ProcessTraceSpecification = {
|
||||
events: [
|
||||
{
|
||||
id: "before",
|
||||
source: "filesystem",
|
||||
exact: beforeCheckpoint,
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
{
|
||||
id: "exit",
|
||||
source: "lifecycle",
|
||||
exact: { event: "exit", ...capture.exit },
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
{
|
||||
id: "settlement",
|
||||
source: "lifecycle",
|
||||
exact: { event: "settlement", ...capture.settlement },
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
{
|
||||
id: "after",
|
||||
source: "filesystem",
|
||||
exact: afterCheckpoint,
|
||||
cardinality: { kind: "required" },
|
||||
},
|
||||
],
|
||||
language: {
|
||||
kind: "finite_traces",
|
||||
variants: [
|
||||
{
|
||||
id: "normal",
|
||||
trace: ["before", "exit", "settlement", "after"],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const { capture, traceSpecification } = processTraceCaptureFixture();
|
||||
|
||||
const captureEvidence = (side: "left" | "right") =>
|
||||
createEvidence(undefined, PROCESS_PROVIDER, {
|
||||
|
||||
Reference in new issue
Block a user