Files
rea/tests/acceptance/applications/androidRuntimeComponentHints.test.ts

63 lines
2.6 KiB
TypeScript
Raw Permalink Normal View History

import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import { TextReader, Uint8ArrayWriter, ZipWriter } from "@zip.js/zip.js";
import { expect } from "vitest";
import { androidApplicationProjectionResultSchema } from "../../../src/domain/android/androidApplication.js";
import { parseEvidence } from "../../../src/domain/evidence.js";
import { connectLocalToolsMcp } from "../../fixtures/localToolsMcp.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { cliTest } from "../../support/cli/cliFixture.js";
cliTest(
"Android runtime hints follow classified bytecode through CLI and MCP",
async ({ cli }) => {
const root = await createTestTempDirectory("rea-android-runtime-hints-");
const environment = { HOME: root, USERPROFILE: root };
const { call } = await connectLocalToolsMcp(environment);
for (const prefix of ["", "named"]) {
const writer = new ZipWriter(new Uint8ArrayWriter());
await writer.add("AndroidManifest.xml", new TextReader("fixture"));
for (const extension of ["dex", "class"])
await writer.add(
`assets/${prefix}.${extension}`,
new TextReader("ordinary text"),
);
const path = join(root, `${prefix || "dot-names"}.apk`);
await writeFile(path, await writer.close());
const inspected = await cli.run({
arguments: ["inspect-artifact", path, "--json"],
environment,
});
expect(inspected.exitCode, inspected.stderr).toBe(0);
const source = parseEvidence(inspected.json);
const input = { inventory_evidence: [source] };
const projected = await cli.run({
arguments: [
"project-android-application-graph",
JSON.stringify(input),
"--json",
],
environment,
});
expect(projected.exitCode, projected.stderr).toBe(0);
const evidence = parseEvidence(projected.json);
const graph = androidApplicationProjectionResultSchema.parse(
evidence.normalized_result,
);
expect(graph.components.dex.map(({ path }) => path)).toEqual(
prefix ? ["assets/named.dex"] : [],
);
expect(graph.components.jvm_classes.map(({ path }) => path)).toEqual(
prefix ? ["assets/named.class"] : [],
);
expect(graph.runtime_families).toEqual(
prefix ? ["dalvik-art", "java-kotlin"] : [],
);
const mcp = await call("project_android_application_graph", input);
expect(mcp.isError).not.toBe(true);
expect(parseEvidence(mcp.structuredContent)).toEqual(evidence);
}
},
);