feat: add omx team adapter skeleton
This commit is contained in:
110
tests/omx-team-backend-config.test.ts
Normal file
110
tests/omx-team-backend-config.test.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
||||
import {
|
||||
getOmxTeamBackendAvailabilityForTesting,
|
||||
getOmxTeamBackendConfigForTesting,
|
||||
isOmxTeamBackendConfiguredForTesting,
|
||||
} from "@/lib/execution/backends/omx-team-config";
|
||||
|
||||
function snapshotEnv() {
|
||||
return {
|
||||
BOSS_OMX_ENABLED: process.env.BOSS_OMX_ENABLED,
|
||||
BOSS_OMX_COMMAND: process.env.BOSS_OMX_COMMAND,
|
||||
BOSS_OMX_ARGS: process.env.BOSS_OMX_ARGS,
|
||||
BOSS_OMX_WORKDIR: process.env.BOSS_OMX_WORKDIR,
|
||||
BOSS_OMX_TIMEOUT_MS: process.env.BOSS_OMX_TIMEOUT_MS,
|
||||
};
|
||||
}
|
||||
|
||||
function restoreEnv(snapshot: ReturnType<typeof snapshotEnv>) {
|
||||
for (const [key, value] of Object.entries(snapshot)) {
|
||||
if (value === undefined) {
|
||||
delete process.env[key];
|
||||
} else {
|
||||
process.env[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test("OMX backend 默认关闭", () => {
|
||||
const previous = snapshotEnv();
|
||||
delete process.env.BOSS_OMX_ENABLED;
|
||||
delete process.env.BOSS_OMX_COMMAND;
|
||||
delete process.env.BOSS_OMX_ARGS;
|
||||
delete process.env.BOSS_OMX_WORKDIR;
|
||||
delete process.env.BOSS_OMX_TIMEOUT_MS;
|
||||
|
||||
const config = getOmxTeamBackendConfigForTesting();
|
||||
assert.equal(config.enabled, false);
|
||||
assert.equal(config.command, undefined);
|
||||
assert.deepEqual(config.args, []);
|
||||
assert.equal(config.timeoutMs, 45000);
|
||||
assert.equal(isOmxTeamBackendConfiguredForTesting(config), false);
|
||||
|
||||
restoreEnv(previous);
|
||||
});
|
||||
|
||||
test("OMX backend 在配置完整时返回 command、args 和 timeout", () => {
|
||||
const previous = snapshotEnv();
|
||||
process.env.BOSS_OMX_ENABLED = "true";
|
||||
process.env.BOSS_OMX_COMMAND = "node";
|
||||
process.env.BOSS_OMX_ARGS = "scripts/omx-team-smoke.mjs --smoke";
|
||||
process.env.BOSS_OMX_WORKDIR = "/tmp/boss-omx";
|
||||
process.env.BOSS_OMX_TIMEOUT_MS = "120000";
|
||||
|
||||
const config = getOmxTeamBackendConfigForTesting();
|
||||
assert.equal(config.enabled, true);
|
||||
assert.equal(config.command, "node");
|
||||
assert.deepEqual(config.args, ["scripts/omx-team-smoke.mjs", "--smoke"]);
|
||||
assert.equal(config.cwd, "/tmp/boss-omx");
|
||||
assert.equal(config.timeoutMs, 120000);
|
||||
assert.equal(isOmxTeamBackendConfiguredForTesting(config), true);
|
||||
|
||||
restoreEnv(previous);
|
||||
});
|
||||
|
||||
test("OMX backend availability 会在可执行命令和脚本都存在时返回 ready", async () => {
|
||||
const previous = snapshotEnv();
|
||||
const tempDir = await mkdtemp(path.join(os.tmpdir(), "boss-omx-config-"));
|
||||
const scriptPath = path.join(tempDir, "omx-team-smoke.mjs");
|
||||
await writeFile(scriptPath, "console.log('ok');\n", "utf8");
|
||||
|
||||
process.env.BOSS_OMX_ENABLED = "true";
|
||||
process.env.BOSS_OMX_COMMAND = process.execPath;
|
||||
process.env.BOSS_OMX_ARGS = scriptPath;
|
||||
process.env.BOSS_OMX_WORKDIR = tempDir;
|
||||
|
||||
try {
|
||||
const availability = await getOmxTeamBackendAvailabilityForTesting();
|
||||
assert.equal(availability.status, "ready");
|
||||
assert.equal(availability.selectable, true);
|
||||
assert.equal(availability.reason, "ready");
|
||||
} finally {
|
||||
restoreEnv(previous);
|
||||
await rm(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("OMX backend availability 会在脚本参数不存在时返回不可选", async () => {
|
||||
const previous = snapshotEnv();
|
||||
const tempDir = await mkdtemp(path.join(os.tmpdir(), "boss-omx-config-"));
|
||||
const missingScript = path.join(tempDir, "missing-omx-script.mjs");
|
||||
|
||||
process.env.BOSS_OMX_ENABLED = "true";
|
||||
process.env.BOSS_OMX_COMMAND = process.execPath;
|
||||
process.env.BOSS_OMX_ARGS = missingScript;
|
||||
process.env.BOSS_OMX_WORKDIR = tempDir;
|
||||
|
||||
try {
|
||||
const availability = await getOmxTeamBackendAvailabilityForTesting();
|
||||
assert.equal(availability.status, "misconfigured");
|
||||
assert.equal(availability.selectable, false);
|
||||
assert.equal(availability.reason, "script_not_found");
|
||||
} finally {
|
||||
restoreEnv(previous);
|
||||
await rm(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
60
tests/omx-team-smoke-script.test.ts
Normal file
60
tests/omx-team-smoke-script.test.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import path from "node:path";
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
function runSmoke(payload: unknown) {
|
||||
return new Promise<{
|
||||
exitCode: number | null;
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
}>((resolve, reject) => {
|
||||
const scriptPath = path.resolve("scripts/omx-team-smoke.mjs");
|
||||
const child = spawn(process.execPath, [scriptPath], {
|
||||
cwd: "/Users/kris/code/boss",
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
child.stdout.setEncoding("utf8");
|
||||
child.stderr.setEncoding("utf8");
|
||||
child.stdout.on("data", (chunk) => {
|
||||
stdout += chunk;
|
||||
});
|
||||
child.stderr.on("data", (chunk) => {
|
||||
stderr += chunk;
|
||||
});
|
||||
child.on("error", reject);
|
||||
child.on("close", (exitCode) => {
|
||||
resolve({ exitCode, stdout, stderr });
|
||||
});
|
||||
|
||||
child.stdin.write(JSON.stringify(payload));
|
||||
child.stdin.end();
|
||||
});
|
||||
}
|
||||
|
||||
test("omx team smoke script emits ready JSON for valid payload", async () => {
|
||||
const result = await runSmoke({
|
||||
requestKind: "dispatch_execution",
|
||||
workersRequested: 2,
|
||||
objective: "并行协作链路 smoke",
|
||||
});
|
||||
|
||||
assert.equal(result.exitCode, 0);
|
||||
assert.equal(result.stderr, "");
|
||||
const parsed = JSON.parse(result.stdout);
|
||||
assert.equal(parsed.status, "ready");
|
||||
assert.equal(parsed.backendId, "omx-team");
|
||||
assert.match(parsed.summary, /并行协作链路 smoke/);
|
||||
});
|
||||
|
||||
test("omx team smoke script emits failed JSON for invalid payload", async () => {
|
||||
const result = await runSmoke("not-an-object");
|
||||
|
||||
assert.equal(result.exitCode, 0);
|
||||
const parsed = JSON.parse(result.stdout);
|
||||
assert.equal(parsed.status, "failed");
|
||||
assert.match(parsed.error, /INVALID_OMX_PAYLOAD/);
|
||||
});
|
||||
53
tests/orchestration-backend-selector.test.ts
Normal file
53
tests/orchestration-backend-selector.test.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import {
|
||||
listOrchestrationBackendChoices,
|
||||
selectOrchestrationBackendForTesting,
|
||||
} from "@/lib/execution/orchestration-backend-selector";
|
||||
|
||||
test("listOrchestrationBackendChoices keeps omx disabled by default", async () => {
|
||||
const backends = await listOrchestrationBackendChoices();
|
||||
|
||||
assert.deepEqual(
|
||||
backends.map((backend) => backend.backendId),
|
||||
["boss-native-orchestrator"],
|
||||
);
|
||||
});
|
||||
|
||||
test("selectOrchestrationBackendForTesting honors explicit omx request when selectable", async () => {
|
||||
const backend = await selectOrchestrationBackendForTesting({
|
||||
requestedBackendId: "omx-team",
|
||||
omx: {
|
||||
enabled: true,
|
||||
selectable: true,
|
||||
availability: {
|
||||
status: "ready",
|
||||
selectable: true,
|
||||
configured: true,
|
||||
reason: "ready",
|
||||
reasonLabel: "OMX Team Runtime 可用。",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(backend.backendId, "omx-team");
|
||||
});
|
||||
|
||||
test("selectOrchestrationBackendForTesting falls back when omx is requested but unavailable", async () => {
|
||||
const backend = await selectOrchestrationBackendForTesting({
|
||||
requestedBackendId: "omx-team",
|
||||
omx: {
|
||||
enabled: false,
|
||||
selectable: false,
|
||||
availability: {
|
||||
status: "disabled",
|
||||
selectable: false,
|
||||
configured: false,
|
||||
reason: "disabled",
|
||||
reasonLabel: "OMX Team Runtime 当前未启用。",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(backend.backendId, "boss-native-orchestrator");
|
||||
});
|
||||
Reference in New Issue
Block a user