mirror of
https://github.com/morluto/rea.git
synced 2026-11-13 18:22:42 +00:00
135 lines
4.0 KiB
TypeScript
135 lines
4.0 KiB
TypeScript
import { expect, it } from "vitest";
|
|
import { Ajv } from "ajv";
|
|
import type { AnySchema } from "ajv";
|
|
|
|
import { aotFixtureImage } from "../../../src/flutter/FlutterBuild.fixture.js";
|
|
import { flutterInputSchemas } from "../../../src/domain/flutter/flutterBuildAnalysis.js";
|
|
import { createFlutterApk } from "../../fixtures/flutterApk.js";
|
|
import { serveCli } from "./cliServeHarness.js";
|
|
|
|
it.each(["identify-flutter-build", "inspect-dart-aot"])(
|
|
"%s advertises a schema through the public CLI",
|
|
async (command) => {
|
|
const result = await serveCli([command, "--schema", "--json"]);
|
|
expect(result.exitCode).toBe(0);
|
|
expect(JSON.parse(result.stdout)).toBeTruthy();
|
|
},
|
|
);
|
|
|
|
it("reports an unreadable target with an input refusal", async () => {
|
|
const result = await serveCli([
|
|
"identify-flutter-build",
|
|
"/nonexistent/app.apk",
|
|
"--json",
|
|
]);
|
|
expect(result.stdout).toContain("invalid_request");
|
|
});
|
|
|
|
it.each(["identify-flutter-build", "inspect-dart-aot"])(
|
|
"%s uses canonical local-path validation before provider admission",
|
|
async (command) => {
|
|
const result = await serveCli([command, "fixture\u0000.apk", "--json"]);
|
|
expect(JSON.parse(result.stdout)).toMatchObject({
|
|
code: "VALIDATION_ERROR",
|
|
fieldErrors: [
|
|
expect.objectContaining({
|
|
path: "path",
|
|
message: expect.stringContaining("NUL"),
|
|
}),
|
|
],
|
|
});
|
|
},
|
|
);
|
|
|
|
it("advertises and validates one ABI selector grammar with field correction guidance", async () => {
|
|
const advertised = await serveCli(["inspect-dart-aot", "--schema", "--json"]);
|
|
expect(advertised.exitCode).toBe(0);
|
|
const schema = JSON.parse(advertised.stdout) as { options: AnySchema };
|
|
const ajv = new Ajv({ strict: false });
|
|
expect(ajv.validateSchema(schema.options)).toBe(true);
|
|
const accepts = ajv.compile(schema.options);
|
|
const abiSchema = flutterInputSchemas.inspect_dart_aot.shape.abi;
|
|
for (const abi of [
|
|
"ARM64-V8A",
|
|
"ARM64",
|
|
"arm64.v8a",
|
|
"A",
|
|
"a",
|
|
"abi\\label",
|
|
"abi\nlabel",
|
|
"l".repeat(1010),
|
|
"😀".repeat(1010),
|
|
]) {
|
|
expect(accepts({ abi })).toBe(true);
|
|
expect(abiSchema.safeParse(abi).success).toBe(true);
|
|
}
|
|
for (const abi of [
|
|
"",
|
|
"lib/x86_64",
|
|
"l".repeat(1011),
|
|
"😀".repeat(1011),
|
|
"l".repeat(1010) + "\n",
|
|
]) {
|
|
expect(accepts({ abi })).toBe(false);
|
|
expect(abiSchema.safeParse(abi).success).toBe(false);
|
|
const rejected = await serveCli([
|
|
"inspect-dart-aot",
|
|
"/nonexistent/app.apk",
|
|
"--abi",
|
|
abi,
|
|
"--json",
|
|
]);
|
|
expect(JSON.parse(rejected.stdout)).toMatchObject({
|
|
code: "VALIDATION_ERROR",
|
|
fieldErrors: [
|
|
expect.objectContaining({
|
|
path: "abi",
|
|
message: expect.stringContaining("ABI"),
|
|
}),
|
|
],
|
|
});
|
|
}
|
|
});
|
|
|
|
it("inspects the caller-selected nonstandard ABI through the public CLI", async () => {
|
|
const path = await createFlutterApk("selector.apk", [
|
|
{ path: "lib/ARM64-V8A/libapp.so", bytes: aotFixtureImage("a".repeat(32)) },
|
|
{ path: "lib/x86_64/libapp.so", bytes: aotFixtureImage("b".repeat(32)) },
|
|
]);
|
|
const selected = await serveCli([
|
|
"inspect-dart-aot",
|
|
path,
|
|
"--abi",
|
|
"ARM64-V8A",
|
|
"--pool-policy",
|
|
'{"contains":"package:animations/","uri_limit":1}',
|
|
"--json",
|
|
]);
|
|
expect(selected.exitCode).toBe(0);
|
|
expect(JSON.parse(selected.stdout)).toMatchObject({
|
|
caller_input_path: path,
|
|
parameters: {
|
|
path,
|
|
abi: "ARM64-V8A",
|
|
pool_policy: { contains: "package:animations/", uri_limit: 1 },
|
|
},
|
|
normalized_result: {
|
|
abi: "ARM64-V8A",
|
|
string_pool: {
|
|
package_uris: ["package:animations/src/fade_scale_transition.dart"],
|
|
package_uri_count_at_least: 1,
|
|
policy: { uri_limit: 1, contains: "package:animations/" },
|
|
},
|
|
libapp: { snapshot_hash: "a".repeat(32), coverage: "complete" },
|
|
},
|
|
});
|
|
const invalid = await serveCli([
|
|
"inspect-dart-aot",
|
|
path,
|
|
"--pool-policy",
|
|
'{"uri_limit":0}',
|
|
"--json",
|
|
]);
|
|
expect(JSON.parse(invalid.stdout).code).toBe("VALIDATION_ERROR");
|
|
});
|