mirror of
https://github.com/morluto/rea
synced 2026-10-25 22:08:11 -04:00
refactor(tests): keep fixture adapters outside runtime
This commit is contained in:
@@ -13,8 +13,10 @@ import { describe, expect, it } from "vitest";
|
||||
|
||||
import { createEvidence } from "../domain/evidence.js";
|
||||
import { createEvidenceBundle } from "../domain/evidenceBundle.js";
|
||||
import { emptyUnverifiedProcessCapture } from "../domain/process/processCapture.fixture.js";
|
||||
import { FINALIZED_PROCESS_CAPTURE_EXAMPLE } from "../domain/process/processCaptureExample.js";
|
||||
import {
|
||||
emptyUnverifiedProcessCapture,
|
||||
FINALIZED_PROCESS_CAPTURE_EXAMPLE,
|
||||
} from "../domain/process/processCapture.fixture.js";
|
||||
import { PROCESS_PROVIDER } from "../domain/process/processEvidenceProvider.js";
|
||||
import { parseProcessCapture } from "../domain/process/processCaptureParsing.js";
|
||||
import {
|
||||
|
||||
@@ -49,37 +49,6 @@ export interface RootInventorySource extends StableRegularFileDescriptor {
|
||||
readonly owner: OwnedFileHandle;
|
||||
}
|
||||
|
||||
/** Classify and hash one file root through the same stable open descriptor. */
|
||||
export const classifyAndHashRoot = async (
|
||||
path: string,
|
||||
directory: boolean,
|
||||
expectedMetadata: Stats,
|
||||
options: Pick<ArtifactInventoryOptions, "resourceScope" | "signal">,
|
||||
): Promise<RootClassification> => {
|
||||
return options.resourceScope.run(async () => {
|
||||
const result = await classifyAndHashRootForInventory(
|
||||
path,
|
||||
directory,
|
||||
expectedMetadata,
|
||||
options,
|
||||
);
|
||||
const rootSource = result.rootSource;
|
||||
if (rootSource !== undefined) {
|
||||
const owner: ArtifactResourceOwner = {
|
||||
kind: "file-handle",
|
||||
handle: rootSource.owner,
|
||||
resource: `root artifact descriptor for ${path}`,
|
||||
};
|
||||
const cleanupAttempt = await options.resourceScope.release(owner);
|
||||
if (cleanupAttempt.kind === "failed")
|
||||
throw options.resourceScope.cleanupFailure({ kind: "completed" }, [
|
||||
cleanupAttempt,
|
||||
]);
|
||||
}
|
||||
return { format: result.format, digest: result.digest };
|
||||
});
|
||||
};
|
||||
|
||||
/** Classify a root and retain its admitted ZIP descriptor for child inventory. */
|
||||
export const classifyAndHashRootForInventory = async (
|
||||
path: string,
|
||||
|
||||
@@ -180,91 +180,3 @@ export const CLI_COMMANDS = Object.freeze({
|
||||
|
||||
/** Ordered primary CLI inventory; aliases are intentionally excluded. */
|
||||
export const CLI_COMMAND_NAMES = Object.freeze(Object.values(CLI_COMMANDS));
|
||||
|
||||
/** Canonical MCP operations reached by CLI commands with different names. */
|
||||
export const CLI_COMMAND_TOOL_ALIASES = Object.freeze({
|
||||
"environment-build": ["export_environment_bundle"],
|
||||
analyze: ["binary_overview"],
|
||||
inspect: ["binary_overview"],
|
||||
decompile: ["procedure_pseudo_code"],
|
||||
function: ["analyze_function"],
|
||||
instructions: ["read_function_instructions"],
|
||||
trace: ["trace_feature"],
|
||||
search: ["search_strings", "search_procedures"],
|
||||
"capture-process": ["capture_process_scenario"],
|
||||
"compare-bundles": ["compare_bundles"],
|
||||
"list-objdump-architectures": ["inspect_with_objdump"],
|
||||
"debug-with-gdb": ["gdb_console"],
|
||||
"debug-with-rizin": ["rizin_debug_command"],
|
||||
});
|
||||
|
||||
/** MCP operations without a dedicated CLI command or direct command alias. */
|
||||
export const MCP_TOOLS_WITHOUT_DEDICATED_CLI = Object.freeze([
|
||||
// MCP session control selects a resource root; CLI resource commands take paths directly.
|
||||
"open_bundle_resources",
|
||||
"address_name",
|
||||
"comment",
|
||||
"current_address",
|
||||
"current_procedure",
|
||||
"current_document",
|
||||
"goto_address",
|
||||
"inline_comment",
|
||||
"list_bookmarks",
|
||||
"list_documents",
|
||||
"list_names",
|
||||
"list_procedures",
|
||||
"list_segments",
|
||||
"list_strings",
|
||||
"next_address",
|
||||
"prev_address",
|
||||
"procedure_address",
|
||||
"procedure_assembly",
|
||||
"procedure_callees",
|
||||
"procedure_callers",
|
||||
"procedure_info",
|
||||
"procedure_references",
|
||||
"resolve_containing_procedure",
|
||||
"set_address_name",
|
||||
"set_addresses_names",
|
||||
"set_bookmark",
|
||||
"set_comment",
|
||||
"set_inline_comment",
|
||||
"unset_bookmark",
|
||||
"get_objc_classes",
|
||||
"get_objc_protocols",
|
||||
"batch_decompile",
|
||||
"get_call_graph",
|
||||
"analyze_swift_types",
|
||||
"find_xrefs_to_name",
|
||||
"trace_call_path",
|
||||
"open_binary",
|
||||
"close_binary",
|
||||
"binary_session",
|
||||
"export_evidence_bundle",
|
||||
"import_evidence_bundle",
|
||||
"compare_artifacts",
|
||||
"compare_functions",
|
||||
"find_changed_behavior",
|
||||
"build_call_path",
|
||||
"correlate_static_and_runtime",
|
||||
"verify_reconstruction",
|
||||
"list_unknowns",
|
||||
"record_unknown",
|
||||
"update_unknown",
|
||||
"verify_unknown_resolution",
|
||||
"get_evidence_bundle",
|
||||
"get_navigation_context",
|
||||
"inspect_address_context",
|
||||
"start_gdb_session",
|
||||
"gdb_session_status",
|
||||
"close_gdb_session",
|
||||
"start_rizin_debug_session",
|
||||
"rizin_debug_session_status",
|
||||
"close_rizin_debug_session",
|
||||
"start_frida_session",
|
||||
"load_frida_script",
|
||||
"resume_frida_session",
|
||||
"unload_frida_script",
|
||||
"frida_session_status",
|
||||
"close_frida_session",
|
||||
]);
|
||||
|
||||
@@ -16,12 +16,6 @@ export const MAX_INSPECT_PE_LOAD_CONFIG_CALLBACKS = 4096;
|
||||
/** IMAGE_TLS_DIRECTORY byte width for each optional-header magic. */
|
||||
export const TLS_STRUCT_BYTES = { 32: 24, 64: 40 } as const;
|
||||
|
||||
/**
|
||||
* IMAGE_LOAD_CONFIG_DIRECTORY size through GuardMemcpyFunctionPointer.
|
||||
* Later fields stay unread; a larger Size does not fail the inspection.
|
||||
*/
|
||||
export const LOAD_CONFIG_KNOWN_STRUCT_BYTES = { 32: 192, 64: 320 } as const;
|
||||
|
||||
/** Complete bounded inspection of one PE TLS directory and load configuration. */
|
||||
export const inspectPeLoadConfigInputSchema = z.strictObject({
|
||||
path: absoluteLocalPathStringSchema.describe(
|
||||
|
||||
@@ -3,11 +3,44 @@ import { compareProcessCaptures } from "./processComparison.js";
|
||||
import { parseProcessCapture } from "./processCaptureParsing.js";
|
||||
import { EMPTY_PROCESS_CAPTURE_EXAMPLE } from "./processCaptureExample.js";
|
||||
import { hasCaptureTruncation } from "./processCaptureCoverage.js";
|
||||
import { digestProcessCommitment } from "./processScenario.js";
|
||||
import type { JsonValue } from "../jsonValue.js";
|
||||
|
||||
import {
|
||||
processCaptureSchema,
|
||||
type UnverifiedProcessCapture,
|
||||
} from "./processCapture.js";
|
||||
|
||||
const finalizedScenario = {
|
||||
...EMPTY_PROCESS_CAPTURE_EXAMPLE.manifest.scenario,
|
||||
finalization_ms: 1_500,
|
||||
};
|
||||
const finalizedComparisonContract = { finalization_ms: 1_500 };
|
||||
|
||||
/** Valid capture of a timeout that finalized: SIGTERM delivered, exit observed. */
|
||||
export const FINALIZED_PROCESS_CAPTURE_EXAMPLE = {
|
||||
...EMPTY_PROCESS_CAPTURE_EXAMPLE,
|
||||
manifest: {
|
||||
...EMPTY_PROCESS_CAPTURE_EXAMPLE.manifest,
|
||||
scenario: finalizedScenario,
|
||||
comparison_contract: finalizedComparisonContract,
|
||||
full_scenario_sha256: digestProcessCommitment(finalizedScenario),
|
||||
comparison_contract_sha256: digestProcessCommitment(
|
||||
finalizedComparisonContract,
|
||||
),
|
||||
},
|
||||
exit: {
|
||||
code: null,
|
||||
signal: 0,
|
||||
reason: "timeout",
|
||||
finalization: {
|
||||
requested_ms: 1_500,
|
||||
elapsed_ms: 12,
|
||||
exit_code: 0,
|
||||
signals: [{ signal: "SIGTERM", sent_at_ms: 0, delivery: "signaled" }],
|
||||
},
|
||||
},
|
||||
} satisfies JsonValue;
|
||||
/** Parse a detached valid empty capture for tests that need trusted evidence. */
|
||||
export const emptyProcessCapture = () =>
|
||||
parseProcessCapture(EMPTY_PROCESS_CAPTURE_EXAMPLE);
|
||||
|
||||
@@ -8,14 +8,14 @@ import {
|
||||
} from "./processCaptureParsing.js";
|
||||
import type { UnverifiedProcessCapture } from "./processCapture.js";
|
||||
import { partialProcessCaptureObservationSchema } from "./processCapture.js";
|
||||
import { FINALIZED_PROCESS_CAPTURE_EXAMPLE } from "./processCaptureExample.js";
|
||||
import { finalizationConsistencyIssue } from "./processCaptureValidation.js";
|
||||
import type { FilesystemCoverage } from "./processCaptureCoverage.js";
|
||||
import {
|
||||
FINALIZED_PROCESS_CAPTURE_EXAMPLE,
|
||||
compareUnverifiedProcessCaptures as compareProcessCaptures,
|
||||
emptyUnverifiedProcessCapture as emptyCapture,
|
||||
processCaptureIssues,
|
||||
} from "./processCapture.fixture.js";
|
||||
import { finalizationConsistencyIssue } from "./processCaptureValidation.js";
|
||||
import type { FilesystemCoverage } from "./processCaptureCoverage.js";
|
||||
|
||||
expectTypeOf<UnverifiedProcessCapture>().not.toExtend<ProcessCapture>();
|
||||
|
||||
|
||||
@@ -111,31 +111,3 @@ export const EMPTY_PROCESS_CAPTURE_EXAMPLE = {
|
||||
temporary_root: "removed",
|
||||
},
|
||||
} satisfies JsonValue;
|
||||
|
||||
const finalizedScenario = { ...scenario, finalization_ms: 1_500 };
|
||||
const finalizedComparisonContract = { finalization_ms: 1_500 };
|
||||
|
||||
/** Valid capture of a timeout that finalized: SIGTERM delivered, exit observed. */
|
||||
export const FINALIZED_PROCESS_CAPTURE_EXAMPLE = {
|
||||
...EMPTY_PROCESS_CAPTURE_EXAMPLE,
|
||||
manifest: {
|
||||
...EMPTY_PROCESS_CAPTURE_EXAMPLE.manifest,
|
||||
scenario: finalizedScenario,
|
||||
comparison_contract: finalizedComparisonContract,
|
||||
full_scenario_sha256: digestProcessCommitment(finalizedScenario),
|
||||
comparison_contract_sha256: digestProcessCommitment(
|
||||
finalizedComparisonContract,
|
||||
),
|
||||
},
|
||||
exit: {
|
||||
code: null,
|
||||
signal: 0,
|
||||
reason: "timeout",
|
||||
finalization: {
|
||||
requested_ms: 1_500,
|
||||
elapsed_ms: 12,
|
||||
exit_code: 0,
|
||||
signals: [{ signal: "SIGTERM", sent_at_ms: 0, delivery: "signaled" }],
|
||||
},
|
||||
},
|
||||
} satisfies JsonValue;
|
||||
|
||||
@@ -105,7 +105,7 @@ export const locateTrailingZipArchive = async (
|
||||
* is intentionally absent: the suffix also names HTTP Archive JSON, so a
|
||||
* Harmony shared archive is only established from verified ZIP bytes. The
|
||||
* HarmonyOS App Pack suffix `.app` is also absent here: it applies only to
|
||||
* root inputs (see `classifyAndHashRoot`), because a nested ZIP entry ending
|
||||
* root inputs (see `classifyAndHashRootForInventory`), because a nested ZIP entry ending
|
||||
* in `.app` inside another package, such as an IPA, is not an App Pack.
|
||||
*/
|
||||
export const zipPackageFormatForPath = (
|
||||
|
||||
@@ -268,24 +268,3 @@ function* referencedTypeCount(
|
||||
|
||||
/** Rows between cooperative yields while linking. */
|
||||
const LINK_BATCH = 256;
|
||||
|
||||
/** Synchronous linking for byte-level callers. */
|
||||
export const linkIl2cppBinary = (
|
||||
bytes: Buffer,
|
||||
metadata: Il2cppMetadataDecoded,
|
||||
facts: Il2cppMetadataLinkFacts,
|
||||
architecture?: string,
|
||||
options: Il2cppBinaryReadOptions = {},
|
||||
): Il2cppBinaryLink => {
|
||||
const steps = linkIl2cppBinarySteps(
|
||||
bytes,
|
||||
metadata,
|
||||
facts,
|
||||
architecture,
|
||||
options,
|
||||
);
|
||||
for (;;) {
|
||||
const step = steps.next();
|
||||
if (step.done) return step.value;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -969,23 +969,3 @@ function* readMetadataCoreSteps(
|
||||
link: tables.linkFacts,
|
||||
};
|
||||
}
|
||||
|
||||
const runSteps = <T>(steps: Generator<void, T>): T => {
|
||||
for (;;) {
|
||||
const step = steps.next();
|
||||
if (step.done) return step.value;
|
||||
}
|
||||
};
|
||||
|
||||
/** Synchronous consumption of the same decoder for byte-level callers. */
|
||||
export const readIl2cppMetadata = (
|
||||
bytes: Buffer,
|
||||
options: Il2cppMetadataReadOptions = {},
|
||||
): Il2cppMetadataDecoded => runSteps(readIl2cppMetadataSteps(bytes, options));
|
||||
|
||||
/** Synchronous decoding that also retains the typed row facts used for native linking. */
|
||||
export const readIl2cppMetadataForLinking = (
|
||||
bytes: Buffer,
|
||||
options: Il2cppMetadataReadOptions = {},
|
||||
): Il2cppMetadataForLinking =>
|
||||
runSteps(readIl2cppMetadataForLinkingSteps(bytes, options));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
LOAD_CONFIG_KNOWN_STRUCT_BYTES,
|
||||
loadConfigFieldLayout,
|
||||
} from "../../domain/native/peLoadConfig.js";
|
||||
import { loadConfigFieldLayout } from "../../domain/native/peLoadConfig.js";
|
||||
|
||||
/** Authored fixture directory sizes through GuardMemcpyFunctionPointer. */
|
||||
const LOAD_CONFIG_KNOWN_STRUCT_BYTES = { 32: 192, 64: 320 } as const;
|
||||
|
||||
/** File and RVA layout shared by the synthetic PE32 and PE32+ images. */
|
||||
export const PE_LOAD_CONFIG_FIXTURE = {
|
||||
|
||||
@@ -13,10 +13,8 @@ import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
||||
import { z } from "zod";
|
||||
|
||||
import { InvestigationRecords } from "../application/investigation/InvestigationRecords.js";
|
||||
import {
|
||||
EvidenceMcpServer,
|
||||
forgetPendingMcpRequest,
|
||||
} from "./EvidenceMcpServer.js";
|
||||
import { EvidenceMcpServer } from "./EvidenceMcpServer.js";
|
||||
import { forgetPendingMcpRequest } from "./EvidenceMcpServerCore.js";
|
||||
import { createToolResultDelivery } from "./toolResult.js";
|
||||
|
||||
const firstText = (result: {
|
||||
|
||||
@@ -13,10 +13,7 @@ import {
|
||||
type CompactInputSchemaPresentation,
|
||||
} from "./EvidenceMcpServerCore.js";
|
||||
|
||||
export {
|
||||
forgetPendingMcpRequest,
|
||||
type CompactInputSchemaPresentation,
|
||||
} from "./EvidenceMcpServerCore.js";
|
||||
export type { CompactInputSchemaPresentation } from "./EvidenceMcpServerCore.js";
|
||||
|
||||
/** Canonical composition retains the constructor's existing identity defaults. */
|
||||
export class EvidenceMcpServer extends EvidenceMcpServerCore {
|
||||
|
||||
@@ -3,11 +3,95 @@ import { describe, expect, it } from "vitest";
|
||||
import { createCli } from "../../../src/cli.js";
|
||||
import { createCliInventory } from "../../../scripts/lib/catalog-cli.mjs";
|
||||
import { TOOL_CONTRACTS } from "../../../src/contracts/toolContracts.js";
|
||||
import {
|
||||
CLI_COMMAND_NAMES,
|
||||
CLI_COMMAND_TOOL_ALIASES,
|
||||
MCP_TOOLS_WITHOUT_DEDICATED_CLI,
|
||||
} from "../../../src/cliCommandNames.js";
|
||||
import { CLI_COMMAND_NAMES } from "../../../src/cliCommandNames.js";
|
||||
|
||||
/** Canonical MCP operations reached by CLI commands with different names. */
|
||||
const CLI_COMMAND_TOOL_ALIASES = Object.freeze({
|
||||
"environment-build": ["export_environment_bundle"],
|
||||
analyze: ["binary_overview"],
|
||||
inspect: ["binary_overview"],
|
||||
decompile: ["procedure_pseudo_code"],
|
||||
function: ["analyze_function"],
|
||||
instructions: ["read_function_instructions"],
|
||||
trace: ["trace_feature"],
|
||||
search: ["search_strings", "search_procedures"],
|
||||
"capture-process": ["capture_process_scenario"],
|
||||
"compare-bundles": ["compare_bundles"],
|
||||
"list-objdump-architectures": ["inspect_with_objdump"],
|
||||
"debug-with-gdb": ["gdb_console"],
|
||||
"debug-with-rizin": ["rizin_debug_command"],
|
||||
});
|
||||
|
||||
/** MCP operations without a dedicated CLI command or direct command alias. */
|
||||
const MCP_TOOLS_WITHOUT_DEDICATED_CLI = Object.freeze([
|
||||
// MCP session control selects a resource root; CLI resource commands take paths directly.
|
||||
"open_bundle_resources",
|
||||
"address_name",
|
||||
"comment",
|
||||
"current_address",
|
||||
"current_procedure",
|
||||
"current_document",
|
||||
"goto_address",
|
||||
"inline_comment",
|
||||
"list_bookmarks",
|
||||
"list_documents",
|
||||
"list_names",
|
||||
"list_procedures",
|
||||
"list_segments",
|
||||
"list_strings",
|
||||
"next_address",
|
||||
"prev_address",
|
||||
"procedure_address",
|
||||
"procedure_assembly",
|
||||
"procedure_callees",
|
||||
"procedure_callers",
|
||||
"procedure_info",
|
||||
"procedure_references",
|
||||
"resolve_containing_procedure",
|
||||
"set_address_name",
|
||||
"set_addresses_names",
|
||||
"set_bookmark",
|
||||
"set_comment",
|
||||
"set_inline_comment",
|
||||
"unset_bookmark",
|
||||
"get_objc_classes",
|
||||
"get_objc_protocols",
|
||||
"batch_decompile",
|
||||
"get_call_graph",
|
||||
"analyze_swift_types",
|
||||
"find_xrefs_to_name",
|
||||
"trace_call_path",
|
||||
"open_binary",
|
||||
"close_binary",
|
||||
"binary_session",
|
||||
"export_evidence_bundle",
|
||||
"import_evidence_bundle",
|
||||
"compare_artifacts",
|
||||
"compare_functions",
|
||||
"find_changed_behavior",
|
||||
"build_call_path",
|
||||
"correlate_static_and_runtime",
|
||||
"verify_reconstruction",
|
||||
"list_unknowns",
|
||||
"record_unknown",
|
||||
"update_unknown",
|
||||
"verify_unknown_resolution",
|
||||
"get_evidence_bundle",
|
||||
"get_navigation_context",
|
||||
"inspect_address_context",
|
||||
"start_gdb_session",
|
||||
"gdb_session_status",
|
||||
"close_gdb_session",
|
||||
"start_rizin_debug_session",
|
||||
"rizin_debug_session_status",
|
||||
"close_rizin_debug_session",
|
||||
"start_frida_session",
|
||||
"load_frida_script",
|
||||
"resume_frida_session",
|
||||
"unload_frida_script",
|
||||
"frida_session_status",
|
||||
"close_frida_session",
|
||||
]);
|
||||
|
||||
describe("CLI canonical tool coverage", () => {
|
||||
it("accounts for every MCP tool on the CLI or marks it intentionally MCP-only", () => {
|
||||
|
||||
@@ -5,11 +5,12 @@ import {
|
||||
readUInt32,
|
||||
} from "../../../src/il2cpp/Il2cppBinaryImage.js";
|
||||
import { expect, it } from "vitest";
|
||||
import { linkIl2cppBinarySteps } from "../../../src/il2cpp/Il2cppBinaryFile.js";
|
||||
import {
|
||||
drain,
|
||||
linkIl2cppBinary,
|
||||
linkIl2cppBinarySteps,
|
||||
} from "../../../src/il2cpp/Il2cppBinaryFile.js";
|
||||
import { readIl2cppMetadataForLinking } from "../../../src/il2cpp/Il2cppMetadataFile.js";
|
||||
readIl2cppMetadataForLinking,
|
||||
} from "../../fixtures/il2cpp/readers.js";
|
||||
import {
|
||||
GENERIC_TABLE_LIMIT,
|
||||
linkGenericMethodsSteps,
|
||||
@@ -1673,13 +1674,6 @@ it("returns no instances for an empty genericMethodTable without picking a layou
|
||||
});
|
||||
});
|
||||
|
||||
const drain = <T>(steps: Generator<void, T>, onYield = () => {}): T => {
|
||||
for (;;) {
|
||||
const step = steps.next();
|
||||
if (step.done === true) return step.value;
|
||||
onYield();
|
||||
}
|
||||
};
|
||||
// Link a low-base image of generic tables only, recording yields and rows.
|
||||
const linkLowBase = (
|
||||
options: GenericRegistrationImageOptions = {},
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { expect, it, vi } from "vitest";
|
||||
import { linkIl2cppBinary } from "../../../src/il2cpp/Il2cppBinaryFile.js";
|
||||
import {
|
||||
isMapped,
|
||||
openImageSteps,
|
||||
@@ -7,7 +6,11 @@ import {
|
||||
readSlot,
|
||||
readUInt32,
|
||||
} from "../../../src/il2cpp/Il2cppBinaryImage.js";
|
||||
import { readIl2cppMetadataForLinking } from "../../../src/il2cpp/Il2cppMetadataFile.js";
|
||||
import {
|
||||
drain,
|
||||
linkIl2cppBinary,
|
||||
readIl2cppMetadataForLinking,
|
||||
} from "../../fixtures/il2cpp/readers.js";
|
||||
import {
|
||||
createElfFixture,
|
||||
createIl2cppBinaryFixture,
|
||||
@@ -20,12 +23,7 @@ const { metadata, link: facts } = readIl2cppMetadataForLinking(
|
||||
createLinkedIl2cppMetadataFixture().bytes,
|
||||
);
|
||||
const link = (bytes: Buffer) => linkIl2cppBinary(bytes, metadata, facts);
|
||||
const open = (bytes: Buffer) => {
|
||||
const steps = openImageSteps(bytes, undefined);
|
||||
let step = steps.next();
|
||||
while (!step.done) step = steps.next();
|
||||
return step.value;
|
||||
};
|
||||
const open = (bytes: Buffer) => drain(openImageSteps(bytes, undefined));
|
||||
|
||||
/** Replace PT_LOAD declarations, keeping the original PT_DYNAMIC and payload. */
|
||||
const withLoadRanges = (
|
||||
|
||||
@@ -6,10 +6,12 @@ import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
il2cppIndexWidth,
|
||||
il2cppMetadataRecordBytes,
|
||||
readIl2cppMetadata,
|
||||
readIl2cppMetadataForLinking,
|
||||
readIl2cppMetadataSteps,
|
||||
} from "../../../src/il2cpp/Il2cppMetadataFile.js";
|
||||
import {
|
||||
readIl2cppMetadata,
|
||||
readIl2cppMetadataForLinking,
|
||||
} from "../../fixtures/il2cpp/readers.js";
|
||||
import {
|
||||
createIl2cppMetadataFixture,
|
||||
FIXTURE_IMAGES,
|
||||
|
||||
@@ -7,10 +7,8 @@ import { expect, it, onTestFinished } from "vitest";
|
||||
|
||||
import { compareProcessEvidenceFiles } from "../../../src/application/process/ProcessCli.js";
|
||||
import { PROCESS_PROVIDER } from "../../../src/domain/process/processEvidenceProvider.js";
|
||||
import {
|
||||
EMPTY_PROCESS_CAPTURE_EXAMPLE,
|
||||
FINALIZED_PROCESS_CAPTURE_EXAMPLE,
|
||||
} from "../../../src/domain/process/processCaptureExample.js";
|
||||
import { EMPTY_PROCESS_CAPTURE_EXAMPLE } from "../../../src/domain/process/processCaptureExample.js";
|
||||
import { FINALIZED_PROCESS_CAPTURE_EXAMPLE } from "../../../src/domain/process/processCapture.fixture.js";
|
||||
import {
|
||||
capture,
|
||||
partialSpecification,
|
||||
|
||||
@@ -17,7 +17,7 @@ import { parseEvidence } from "../../../src/domain/evidence.js";
|
||||
import { compareProcessCaptures } from "../../../src/domain/process/processComparison.js";
|
||||
import { parseProcessCapture } from "../../../src/domain/process/processCaptureParsing.js";
|
||||
import { processScenarioSchema } from "../../../src/domain/process/processScenario.js";
|
||||
import { FINALIZED_PROCESS_CAPTURE_EXAMPLE } from "../../../src/domain/process/processCaptureExample.js";
|
||||
import { FINALIZED_PROCESS_CAPTURE_EXAMPLE } from "../../../src/domain/process/processCapture.fixture.js";
|
||||
import { createServer } from "../../../src/server/createServer.js";
|
||||
import { createTestBinarySession } from "../../fixtures/binarySession.js";
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
|
||||
Vendored
+26
-5
@@ -1,7 +1,10 @@
|
||||
import { ArtifactResourceScope } from "../../src/artifacts/ArtifactResourceScope.js";
|
||||
import {
|
||||
ArtifactResourceScope,
|
||||
type ArtifactResourceOwner,
|
||||
} from "../../src/artifacts/ArtifactResourceScope.js";
|
||||
import { onTestFinished } from "vitest";
|
||||
import { ArtifactReaderFailure } from "../../src/artifacts/ArtifactReader.js";
|
||||
import { classifyAndHashRoot as classifyAndHashRootOwned } from "../../src/artifacts/inventory/classify.js";
|
||||
import { classifyAndHashRootForInventory } from "../../src/artifacts/inventory/classify.js";
|
||||
import {
|
||||
inventoryArtifact as inventoryArtifactOwned,
|
||||
scanArtifactInventoryInScope,
|
||||
@@ -32,9 +35,27 @@ export const classifyAndHashRoot = (
|
||||
signal?: AbortSignal,
|
||||
) =>
|
||||
withArtifactResourceScope((resourceScope) =>
|
||||
classifyAndHashRootOwned(path, directory, expectedMetadata, {
|
||||
resourceScope,
|
||||
...(signal === undefined ? {} : { signal }),
|
||||
resourceScope.run(async () => {
|
||||
const result = await classifyAndHashRootForInventory(
|
||||
path,
|
||||
directory,
|
||||
expectedMetadata,
|
||||
{ resourceScope, ...(signal === undefined ? {} : { signal }) },
|
||||
);
|
||||
const rootSource = result.rootSource;
|
||||
if (rootSource !== undefined) {
|
||||
const owner: ArtifactResourceOwner = {
|
||||
kind: "file-handle",
|
||||
handle: rootSource.owner,
|
||||
resource: `root artifact descriptor for ${path}`,
|
||||
};
|
||||
const cleanupAttempt = await resourceScope.release(owner);
|
||||
if (cleanupAttempt.kind === "failed")
|
||||
throw resourceScope.cleanupFailure({ kind: "completed" }, [
|
||||
cleanupAttempt,
|
||||
]);
|
||||
}
|
||||
return { format: result.format, digest: result.digest };
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
import { linkIl2cppBinarySteps } from "../../../src/il2cpp/Il2cppBinaryFile.js";
|
||||
import {
|
||||
readIl2cppMetadataForLinkingSteps,
|
||||
readIl2cppMetadataSteps,
|
||||
} from "../../../src/il2cpp/Il2cppMetadataFile.js";
|
||||
|
||||
/** Consume production reader steps synchronously, optionally observing each yield. */
|
||||
export const drain = <T>(steps: Generator<void, T>, onYield = () => {}): T => {
|
||||
for (;;) {
|
||||
const step = steps.next();
|
||||
if (step.done === true) return step.value;
|
||||
onYield();
|
||||
}
|
||||
};
|
||||
|
||||
export const readIl2cppMetadata = (
|
||||
...parameters: Parameters<typeof readIl2cppMetadataSteps>
|
||||
) => drain(readIl2cppMetadataSteps(...parameters));
|
||||
|
||||
export const readIl2cppMetadataForLinking = (
|
||||
...parameters: Parameters<typeof readIl2cppMetadataForLinkingSteps>
|
||||
) => drain(readIl2cppMetadataForLinkingSteps(...parameters));
|
||||
|
||||
export const linkIl2cppBinary = (
|
||||
...parameters: Parameters<typeof linkIl2cppBinarySteps>
|
||||
) => drain(linkIl2cppBinarySteps(...parameters));
|
||||
Reference in New Issue
Block a user