Add read-only MG4 ADB status collector
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { collectAdbStatus, type AdbConfig, type AdbExecutor } from "../src/adb.js";
|
||||
|
||||
const enabledConfig: AdbConfig = {
|
||||
enabled: true,
|
||||
executable: "/usr/bin/adb",
|
||||
serial: "MG4-HEAD-UNIT",
|
||||
timeoutMs: 2_500
|
||||
};
|
||||
|
||||
describe("read-only ADB collector", () => {
|
||||
it("does not execute anything while integration is disabled", async () => {
|
||||
const execute = vi.fn<AdbExecutor>();
|
||||
await expect(collectAdbStatus({ ...enabledConfig, enabled: false }, execute)).resolves.toEqual({
|
||||
available: false,
|
||||
state: "disabled",
|
||||
reason: "ADB integration is not configured"
|
||||
});
|
||||
expect(execute).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses only fixed argument arrays for one serial and parses identity and display values", async () => {
|
||||
const values = new Map<string, string>([
|
||||
["get-state", "device\n"],
|
||||
["shell getprop ro.product.manufacturer", "SAIC\n"],
|
||||
["shell getprop ro.product.model", "AUTUS\n"],
|
||||
["shell getprop ro.build.version.release", "9\n"],
|
||||
["shell getprop ro.build.version.sdk", "28\n"],
|
||||
["shell getprop ro.build.display.id", "PPR1.181005.003\n"],
|
||||
["shell getprop ro.product.cpu.abi", "arm64-v8a\n"],
|
||||
["shell wm size", "Physical size: 1920x720\n"],
|
||||
["shell wm density", "Physical density: 160\n"]
|
||||
]);
|
||||
const calls: string[][] = [];
|
||||
const execute: AdbExecutor = async (executable, arguments_, options) => {
|
||||
expect(executable).toBe("/usr/bin/adb");
|
||||
expect(options).toEqual({ timeout: 2_500, maxBuffer: 16 * 1024 });
|
||||
calls.push([...arguments_]);
|
||||
return { stdout: values.get(arguments_.slice(2).join(" ")) ?? "", stderr: "" };
|
||||
};
|
||||
|
||||
await expect(collectAdbStatus(enabledConfig, execute)).resolves.toMatchObject({
|
||||
available: true,
|
||||
value: {
|
||||
state: "connected",
|
||||
identity: {
|
||||
manufacturer: { available: true, value: "SAIC" },
|
||||
androidVersion: { available: true, value: "9" },
|
||||
apiLevel: { available: true, value: 28 },
|
||||
abi: { available: true, value: "arm64-v8a" }
|
||||
},
|
||||
display: {
|
||||
size: { available: true, value: { widthPixels: 1920, heightPixels: 720 } },
|
||||
densityDpi: { available: true, value: 160 }
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(calls).toHaveLength(9);
|
||||
for (const arguments_ of calls) {
|
||||
expect(arguments_.slice(0, 2)).toEqual(["-s", "MG4-HEAD-UNIT"]);
|
||||
expect(arguments_).not.toContain("sh");
|
||||
expect(arguments_).not.toContain("-c");
|
||||
}
|
||||
});
|
||||
|
||||
it("reports authorization and offline failures without leaking command output", async () => {
|
||||
const unauthorized: AdbExecutor = async () => {
|
||||
throw { stderr: "error: device unauthorized. private-debug-details" };
|
||||
};
|
||||
await expect(collectAdbStatus(enabledConfig, unauthorized)).resolves.toEqual({
|
||||
available: false,
|
||||
state: "unauthorized",
|
||||
reason: "Authorize this Pi on the infotainment screen"
|
||||
});
|
||||
|
||||
const offline: AdbExecutor = async () => ({ stdout: "offline\n", stderr: "" });
|
||||
await expect(collectAdbStatus(enabledConfig, offline)).resolves.toMatchObject({
|
||||
available: false,
|
||||
state: "offline"
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps individual fields unavailable when a connected device only partially responds", async () => {
|
||||
const execute: AdbExecutor = async (_executable, arguments_) => {
|
||||
if (arguments_.at(-1) === "get-state") return { stdout: "device\n", stderr: "" };
|
||||
if (arguments_.at(-1) === "ro.product.model") throw new Error("read failed");
|
||||
return { stdout: "unexpected\n", stderr: "" };
|
||||
};
|
||||
const status = await collectAdbStatus(enabledConfig, execute);
|
||||
expect(status).toMatchObject({
|
||||
available: true,
|
||||
value: { identity: { model: { available: false, reason: "ADB could not read model" } } }
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user