diff --git a/src/application/ReconstructionObligationCandidates.test.ts b/src/application/ReconstructionObligationCandidates.test.ts index 759a060e8f..9051685d8b 100644 --- a/src/application/ReconstructionObligationCandidates.test.ts +++ b/src/application/ReconstructionObligationCandidates.test.ts @@ -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 { diff --git a/src/artifacts/inventory/classify.ts b/src/artifacts/inventory/classify.ts index 6bc93137b3..466ada17b2 100644 --- a/src/artifacts/inventory/classify.ts +++ b/src/artifacts/inventory/classify.ts @@ -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, -): Promise => { - 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, diff --git a/src/cliCommandNames.ts b/src/cliCommandNames.ts index f1e8cf0132..b56abae118 100644 --- a/src/cliCommandNames.ts +++ b/src/cliCommandNames.ts @@ -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", -]); diff --git a/src/domain/native/peLoadConfig.ts b/src/domain/native/peLoadConfig.ts index f6a23fb750..7b3f8ff07c 100644 --- a/src/domain/native/peLoadConfig.ts +++ b/src/domain/native/peLoadConfig.ts @@ -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( diff --git a/src/domain/process/processCapture.fixture.ts b/src/domain/process/processCapture.fixture.ts index a8f2e669f8..abe269f968 100644 --- a/src/domain/process/processCapture.fixture.ts +++ b/src/domain/process/processCapture.fixture.ts @@ -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); diff --git a/src/domain/process/processCapture.validation.test.ts b/src/domain/process/processCapture.validation.test.ts index e0f2f72e75..325cfe37ed 100644 --- a/src/domain/process/processCapture.validation.test.ts +++ b/src/domain/process/processCapture.validation.test.ts @@ -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().not.toExtend(); diff --git a/src/domain/process/processCaptureExample.ts b/src/domain/process/processCaptureExample.ts index 8259f38501..0b01a0e03f 100644 --- a/src/domain/process/processCaptureExample.ts +++ b/src/domain/process/processCaptureExample.ts @@ -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; diff --git a/src/domain/zipPackageFormat.ts b/src/domain/zipPackageFormat.ts index 1601166804..93bd1b9461 100644 --- a/src/domain/zipPackageFormat.ts +++ b/src/domain/zipPackageFormat.ts @@ -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 = ( diff --git a/src/il2cpp/Il2cppBinaryFile.ts b/src/il2cpp/Il2cppBinaryFile.ts index 0bcd18d74c..9dc93f4e3a 100644 --- a/src/il2cpp/Il2cppBinaryFile.ts +++ b/src/il2cpp/Il2cppBinaryFile.ts @@ -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; - } -}; diff --git a/src/il2cpp/Il2cppMetadataFile.ts b/src/il2cpp/Il2cppMetadataFile.ts index d98d317b0a..b20ce0e81f 100644 --- a/src/il2cpp/Il2cppMetadataFile.ts +++ b/src/il2cpp/Il2cppMetadataFile.ts @@ -969,23 +969,3 @@ function* readMetadataCoreSteps( link: tables.linkFacts, }; } - -const runSteps = (steps: Generator): 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)); diff --git a/src/native/pe/PeLoadConfig.fixture.ts b/src/native/pe/PeLoadConfig.fixture.ts index ed3cdb6f52..a0f447c79e 100644 --- a/src/native/pe/PeLoadConfig.fixture.ts +++ b/src/native/pe/PeLoadConfig.fixture.ts @@ -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 = { diff --git a/src/server/EvidenceMcpServer.test.ts b/src/server/EvidenceMcpServer.test.ts index f55ab9e450..a5b69e279e 100644 --- a/src/server/EvidenceMcpServer.test.ts +++ b/src/server/EvidenceMcpServer.test.ts @@ -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: { diff --git a/src/server/EvidenceMcpServer.ts b/src/server/EvidenceMcpServer.ts index 5d18cf0501..bd7c78331d 100644 --- a/src/server/EvidenceMcpServer.ts +++ b/src/server/EvidenceMcpServer.ts @@ -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 { diff --git a/tests/boundary/cli/cliToolCoverage.test.ts b/tests/boundary/cli/cliToolCoverage.test.ts index 5067e001ce..8b4f71346d 100644 --- a/tests/boundary/cli/cliToolCoverage.test.ts +++ b/tests/boundary/cli/cliToolCoverage.test.ts @@ -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", () => { diff --git a/tests/boundary/il2cpp/il2cppBinaryFile.test.ts b/tests/boundary/il2cpp/il2cppBinaryFile.test.ts index cf918e9812..830de01553 100644 --- a/tests/boundary/il2cpp/il2cppBinaryFile.test.ts +++ b/tests/boundary/il2cpp/il2cppBinaryFile.test.ts @@ -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 = (steps: Generator, 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 = {}, diff --git a/tests/boundary/il2cpp/il2cppMappingOwnership.test.ts b/tests/boundary/il2cpp/il2cppMappingOwnership.test.ts index 908b835a53..a166ca7dfa 100644 --- a/tests/boundary/il2cpp/il2cppMappingOwnership.test.ts +++ b/tests/boundary/il2cpp/il2cppMappingOwnership.test.ts @@ -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 = ( diff --git a/tests/boundary/il2cpp/il2cppMetadataFile.test.ts b/tests/boundary/il2cpp/il2cppMetadataFile.test.ts index 6fdc381cd0..41770d777b 100644 --- a/tests/boundary/il2cpp/il2cppMetadataFile.test.ts +++ b/tests/boundary/il2cpp/il2cppMetadataFile.test.ts @@ -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, diff --git a/tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts b/tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts index b4fe9c8fdf..d9554cd390 100644 --- a/tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts +++ b/tests/boundary/mcp/processComparisonDiagnosticsMcp.test.ts @@ -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, diff --git a/tests/boundary/process/processFilesystemCoverageAdapters.test.ts b/tests/boundary/process/processFilesystemCoverageAdapters.test.ts index 086b38ca8e..1772af643c 100644 --- a/tests/boundary/process/processFilesystemCoverageAdapters.test.ts +++ b/tests/boundary/process/processFilesystemCoverageAdapters.test.ts @@ -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"; diff --git a/tests/fixtures/artifactInventory.ts b/tests/fixtures/artifactInventory.ts index 948289a415..709946bebd 100644 --- a/tests/fixtures/artifactInventory.ts +++ b/tests/fixtures/artifactInventory.ts @@ -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 }; }), ); diff --git a/tests/fixtures/il2cpp/readers.ts b/tests/fixtures/il2cpp/readers.ts new file mode 100644 index 0000000000..5ee91b467f --- /dev/null +++ b/tests/fixtures/il2cpp/readers.ts @@ -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 = (steps: Generator, onYield = () => {}): T => { + for (;;) { + const step = steps.next(); + if (step.done === true) return step.value; + onYield(); + } +}; + +export const readIl2cppMetadata = ( + ...parameters: Parameters +) => drain(readIl2cppMetadataSteps(...parameters)); + +export const readIl2cppMetadataForLinking = ( + ...parameters: Parameters +) => drain(readIl2cppMetadataForLinkingSteps(...parameters)); + +export const linkIl2cppBinary = ( + ...parameters: Parameters +) => drain(linkIl2cppBinarySteps(...parameters));