From 3e1f70096b89211f886c38683a1076b129c58577 Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Mon, 9 Nov 2026 19:42:06 +0800 Subject: [PATCH] fix(cli): retain selected IL2CPP binary path (#9623) --- src/cli/il2cppCommands.ts | 3 + tests/boundary/cli/il2cppCallerPath.test.ts | 81 +++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 tests/boundary/cli/il2cppCallerPath.test.ts diff --git a/src/cli/il2cppCommands.ts b/src/cli/il2cppCommands.ts index 4dc4a6ca2c..f1c414daeb 100644 --- a/src/cli/il2cppCommands.ts +++ b/src/cli/il2cppCommands.ts @@ -63,6 +63,9 @@ export const registerIl2cppCommands = ( const service = createIl2cppMetadataService(); return deliverCliAnalysisEvidence({ callerInputPath: args.path, + ...(options.binary === undefined + ? {} + : { callerInputPaths: { binary_path: options.binary } }), run: () => { const input = { path: absoluteCallerPath(args.path), diff --git a/tests/boundary/cli/il2cppCallerPath.test.ts b/tests/boundary/cli/il2cppCallerPath.test.ts new file mode 100644 index 0000000000..1b3884dc39 --- /dev/null +++ b/tests/boundary/cli/il2cppCallerPath.test.ts @@ -0,0 +1,81 @@ +import { writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { expect } from "vitest"; +import { parseEvidence } from "../../../src/domain/evidence.js"; +import { readEvidenceBundle } from "../../../src/application/EvidenceBundleFiles.js"; +import { createLinkedIl2cppMetadataFixture } from "../../fixtures/il2cpp/metadata.js"; +import { createIl2cppDyldBindFixture } from "../../fixtures/il2cpp/binary.js"; +import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; +import { cliTest, runFileCli } from "../../support/cli/cliFixture.js"; + +cliTest( + "preserves both selected IL2CPP input spellings in inline and bundled Evidence", + async ({ cli }) => { + const root = await createTestTempDirectory("rea-il2cpp-selected-paths-"); + await writeFile( + join(root, "metadata.dat"), + createLinkedIl2cppMetadataFixture().bytes, + ); + await writeFile( + join(root, "GameAssembly.dylib"), + createIl2cppDyldBindFixture(0n), + ); + const input = "./metadata.dat"; + const binary = "./GameAssembly.dylib"; + const inline = await runFileCli(cli, { + cwd: root, + arguments: [ + "inspect-il2cpp-metadata", + input, + "--binary", + binary, + "--json", + ], + }); + expect(inline.exitCode, inline.stderr).toBe(0); + const evidence = parseEvidence(inline.json); + expect(evidence.caller_input_path).toBe(input); + expect(evidence.caller_input_paths).toEqual({ binary_path: binary }); + const summaryArgs = [ + "inspect-il2cpp-metadata", + input, + "--binary", + binary, + "--detail", + "summary", + "--evidence_output", + "./evidence.json", + "--json", + ]; + const summary = await runFileCli(cli, { + cwd: root, + arguments: summaryArgs, + }); + expect(summary.exitCode, summary.stderr).toBe(0); + expect( + parseEvidence((summary.json as { summary: unknown }).summary) + .caller_input_paths, + ).toEqual({ binary_path: binary }); + const refused = await runFileCli(cli, { + cwd: root, + arguments: summaryArgs, + }); + expect(refused.exitCode).toBe(1); + expect(refused.json).toMatchObject({ + details: { + partial_observation: { caller_input_paths: { binary_path: binary } }, + }, + }); + const saved = await readEvidenceBundle(join(root, "evidence.json")); + if (!saved.ok) throw saved.error; + expect(saved.value.records[0]?.caller_input_paths).toEqual({ + binary_path: binary, + }); + const without = await runFileCli(cli, { + cwd: root, + arguments: ["inspect-il2cpp-metadata", input, "--json"], + }); + expect(without.exitCode, without.stderr).toBe(0); + expect(parseEvidence(without.json).caller_input_paths).toBeUndefined(); + }, +);