mirror of
https://github.com/morluto/rea.git
synced 2026-11-14 18:52:48 +00:00
fix(native): retain dispatch reader failure during fallback
This commit is contained in:
1 parent
d97aa0849d
commit
e7884a704a
3 files changed
+141
-9
No files matched your search
@@ -0,0 +1,76 @@
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
AnalysisCapabilityUnavailableError,
|
||||
AnalysisOutputError,
|
||||
} from "../../domain/analysisErrorCore.js";
|
||||
import { projectAnalysisError } from "../../domain/analysisErrorProjection.js";
|
||||
import { err, ok } from "../../domain/result.js";
|
||||
import {
|
||||
createAnalysisExecution,
|
||||
type AnalysisOperationPort,
|
||||
} from "../AnalysisProvider.js";
|
||||
import { inspectNativeDispatch } from "./NativeDispatchMetadataInspection.js";
|
||||
|
||||
it("retains the binary reader refusal when the symbol fallback also fails", async () => {
|
||||
const direct = new AnalysisCapabilityUnavailableError(
|
||||
"native-macos",
|
||||
"inspect_native_dispatch_metadata",
|
||||
"Unsupported 32-bit Mach-O metadata",
|
||||
);
|
||||
const fallback = new AnalysisOutputError(
|
||||
"list_names",
|
||||
"symbol provider unavailable",
|
||||
);
|
||||
const analysis: AnalysisOperationPort = {
|
||||
execute: async (operation) =>
|
||||
err(operation === "list_names" ? fallback : direct),
|
||||
};
|
||||
const result = await inspectNativeDispatch(analysis, 10);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error).toBe(fallback);
|
||||
expect(result.error.secondaryFailures).toContain(direct);
|
||||
expect(projectAnalysisError(result.error)).toMatchObject({
|
||||
details: {
|
||||
diagnostics: {
|
||||
binary_metadata_failure: {
|
||||
details: { reason: expect.stringContaining("Unsupported 32-bit") },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("retains both the reader refusal and malformed symbol observation", async () => {
|
||||
const direct = new AnalysisCapabilityUnavailableError(
|
||||
"native-macos",
|
||||
"inspect_native_dispatch_metadata",
|
||||
"Unsupported 32-bit Mach-O metadata",
|
||||
);
|
||||
const analysis: AnalysisOperationPort = {
|
||||
execute: async (operation) =>
|
||||
operation === "list_names"
|
||||
? ok(
|
||||
createAnalysisExecution(
|
||||
{ invalid: true },
|
||||
{ id: "fixture", name: "Fixture", version: "1" },
|
||||
),
|
||||
)
|
||||
: err(direct),
|
||||
};
|
||||
const result = await inspectNativeDispatch(analysis, 10);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error.secondaryFailures).toContain(direct);
|
||||
expect(projectAnalysisError(result.error)).toMatchObject({
|
||||
details: {
|
||||
diagnostics: {
|
||||
binary_metadata_failure: {
|
||||
details: { reason: "Unsupported 32-bit Mach-O metadata" },
|
||||
},
|
||||
},
|
||||
partial_observation: expect.any(Object),
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
inspectNativeDispatchMetadata,
|
||||
} from "../../domain/native/objcSwiftMetadata.js";
|
||||
import { AnalysisOutputError } from "../../domain/analysisErrorCore.js";
|
||||
import { projectAnalysisError } from "../../domain/analysisErrorProjection.js";
|
||||
import { jsonValueSchema } from "../../domain/jsonValue.js";
|
||||
import { err, ok } from "../../domain/result.js";
|
||||
import type { AnalysisOperationPort } from "../AnalysisProvider.js";
|
||||
@@ -83,7 +84,12 @@ export const inspectNativeDispatch = async (
|
||||
{},
|
||||
signal === undefined ? {} : { signal },
|
||||
);
|
||||
if (!execution.ok) return err(execution.error);
|
||||
if (!execution.ok)
|
||||
return err(
|
||||
execution.error.retainSecondaryFailure(binaryMetadata.error, {
|
||||
binary_metadata_failure: projectAnalysisError(binaryMetadata.error),
|
||||
}),
|
||||
);
|
||||
const names = dispatchNameInventorySchema.safeParse(execution.value.result);
|
||||
if (!names.success)
|
||||
return err(
|
||||
@@ -91,14 +97,18 @@ export const inspectNativeDispatch = async (
|
||||
NATIVE_DISPATCH_METADATA_SOURCES.symbols,
|
||||
"provider returned an invalid inventory",
|
||||
{ cause: names.error },
|
||||
).retainPartialObservation(
|
||||
createAnalysisExecutionEvidence(
|
||||
NATIVE_DISPATCH_METADATA_SOURCES.symbols,
|
||||
{},
|
||||
execution.value,
|
||||
"observed",
|
||||
),
|
||||
),
|
||||
)
|
||||
.retainPartialObservation(
|
||||
createAnalysisExecutionEvidence(
|
||||
NATIVE_DISPATCH_METADATA_SOURCES.symbols,
|
||||
{},
|
||||
execution.value,
|
||||
"observed",
|
||||
),
|
||||
)
|
||||
.retainSecondaryFailure(binaryMetadata.error, {
|
||||
binary_metadata_failure: projectAnalysisError(binaryMetadata.error),
|
||||
}),
|
||||
);
|
||||
const result = inspectNativeDispatchMetadata(
|
||||
names.data.map((entry) => ({
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { expect } from "vitest";
|
||||
import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js";
|
||||
import { cliTest } from "../support/cli/cliFixture.js";
|
||||
|
||||
cliTest.skipIf(process.platform !== "darwin")(
|
||||
"retains the 32-bit reader refusal when symbol fallback is unavailable",
|
||||
async ({ cli }) => {
|
||||
const root = await createTestTempDirectory("rea-dispatch-width-");
|
||||
for (const cpu of [7, 12]) {
|
||||
const image = Buffer.alloc(28);
|
||||
image.writeUInt32LE(0xfeedface, 0);
|
||||
image.writeUInt32LE(cpu, 4);
|
||||
image.writeUInt32LE(cpu === 7 ? 3 : 9, 8);
|
||||
image.writeUInt32LE(2, 12);
|
||||
const path = join(root, `image-${cpu}`);
|
||||
await writeFile(path, image);
|
||||
const result = await cli.run({
|
||||
arguments: [
|
||||
"inspect-native-dispatch-metadata",
|
||||
path,
|
||||
"--format",
|
||||
"json",
|
||||
],
|
||||
environment: {
|
||||
...process.env,
|
||||
REA_ANALYSIS_PROVIDER: "auto",
|
||||
HOPPER_LAUNCHER_PATH: join(root, "missing-hopper"),
|
||||
GHIDRA_INSTALL_DIR: join(root, "missing-ghidra"),
|
||||
JAVA_HOME: join(root, "missing-java"),
|
||||
},
|
||||
});
|
||||
expect(result.exitCode).toBe(1);
|
||||
expect(result.json).toMatchObject({
|
||||
details: {
|
||||
diagnostics: {
|
||||
binary_metadata_failure: {
|
||||
details: { reason: expect.stringMatching(/32.bit/i) },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user