mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-16 11:52:26 +03:00
* test(infra): retry recursive temp-dir removal on main (main twin of #11968)
`main` has been red since b342c1a361 on the vitest and integration gates:
✖ tests/unit/autoCombo/provider-family-combos.test.ts > auto/<family>
✖ chat pipeline applies Codex OAuth fingerprint and priority tier inside combos
Both call resetStorage() from beforeEach, which does an fs.rmSync(TEST_DATA_DIR,
{recursive: true, force: true}) with no retry, and intermittently loses the race
with a not-yet-released SQLite handle (ENOTEMPTY).
release/v3.8.51 fixed this in #11968 with a mechanical codemod adding
maxRetries/retryDelay to every recursive rm/rmSync/rmdirSync under tests/, but
that PR landed only on the release branch. Because main only receives work at
the release squash, it stayed broken for the whole cycle — and repo-wide gates
then turn every open PR into main red on checks unrelated to their diff.
This is the --base main twin: re-runs the same codemod that already shipped on
the release branch (scripts/ad-hoc/codemod-rm-maxretries.mjs), so the two
branches converge on identical test-teardown semantics. Test-only; no product
logic is touched.
The remaining three failures reported on #12133 (unit full suite exceeding its
4800s ceiling, package-artifact exceeding 1200s, and the boot-smoke that is
skipped as a consequence) are runner-contention timeouts, not code defects —
validate-release-green.mjs runs those heavy gates concurrently on one shared
hosted runner. There is no fix to port for those.
* chore(scripts): carry the rm-maxretries codemod onto main alongside its output
The codemod that generated the previous commit lives in the repo on
release/v3.8.51 (added by #11968) but was never on main. Bringing it over keeps
the tool next to the change it produced, so the transformation stays
reproducible and auditable from either branch.
445 lines
16 KiB
TypeScript
445 lines
16 KiB
TypeScript
// ENVIRONMENT NOTE (sandbox better-sqlite3 / glibc limitation, not a code defect):
|
|
// This test constructs or exercises a real better-sqlite3-backed SQLite database.
|
|
// better-sqlite3 is a native addon; production and CI load it normally, but some
|
|
// sandboxes/dev boxes ship a system glibc older than the prebuilt binary requires
|
|
// ("GLIBC_2.29 not found"), so the native module fails to dlopen and any test that
|
|
// reaches better-sqlite3 directly (or asserts stdout that the load-failure warning
|
|
// would pollute) fails HERE while passing in CI. This is a known environment
|
|
// limitation, not a defect in the code under test: the OmniRoute runtime itself
|
|
// cascades to node:sqlite/sql.js when better-sqlite3 is unavailable. See
|
|
// tests/unit/_helpers/betterSqlite3Availability.ts for a guard helper.
|
|
import { describe, it, beforeEach, afterEach, after } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import path from "node:path";
|
|
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import Database from "better-sqlite3";
|
|
|
|
const fileTmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "omni-dbupc-test-"));
|
|
const moduleDataDir = fs.mkdtempSync(path.join(os.tmpdir(), "omni-dbupc-module-"));
|
|
process.env.DATA_DIR = moduleDataDir;
|
|
|
|
const coreDb = await import("../../src/lib/db/core.ts");
|
|
const upstreamProxyDb = await import("../../src/lib/db/upstreamProxy.ts");
|
|
|
|
const SCHEMA = `
|
|
CREATE TABLE IF NOT EXISTS upstream_proxy_config (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
provider_id TEXT NOT NULL UNIQUE,
|
|
mode TEXT NOT NULL DEFAULT 'native',
|
|
cliproxyapi_model_mapping TEXT,
|
|
native_priority INTEGER NOT NULL DEFAULT 1,
|
|
cliproxyapi_priority INTEGER NOT NULL DEFAULT 2,
|
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
`;
|
|
|
|
let testDb;
|
|
let testDbPath;
|
|
|
|
beforeEach(() => {
|
|
testDbPath = path.join(fileTmpDir, `test-${Date.now()}.db`);
|
|
testDb = new Database(testDbPath);
|
|
testDb.exec(SCHEMA);
|
|
});
|
|
|
|
afterEach(() => {
|
|
testDb.close();
|
|
try {
|
|
fs.unlinkSync(testDbPath);
|
|
} catch {}
|
|
});
|
|
|
|
after(() => {
|
|
if (fs.existsSync(fileTmpDir)) fs.rmSync(fileTmpDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
});
|
|
|
|
async function resetModuleStorage() {
|
|
coreDb.resetDbInstance();
|
|
fs.rmSync(moduleDataDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
fs.mkdirSync(moduleDataDir, { recursive: true });
|
|
}
|
|
|
|
function upsert(db, data) {
|
|
db.prepare(
|
|
`
|
|
INSERT OR REPLACE INTO upstream_proxy_config
|
|
(provider_id, mode, cliproxyapi_model_mapping, native_priority, cliproxyapi_priority, enabled, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))
|
|
`
|
|
).run(
|
|
data.providerId,
|
|
data.mode ?? "native",
|
|
data.cliproxyapiModelMapping !== undefined
|
|
? JSON.stringify(data.cliproxyapiModelMapping)
|
|
: null,
|
|
data.nativePriority ?? 1,
|
|
data.cliproxyapiPriority ?? 2,
|
|
data.enabled !== false ? 1 : 0
|
|
);
|
|
return getConfig(db, data.providerId);
|
|
}
|
|
|
|
function getConfig(db, providerId) {
|
|
const row = db
|
|
.prepare("SELECT * FROM upstream_proxy_config WHERE provider_id = ?")
|
|
.get(providerId);
|
|
if (!row) return null;
|
|
return {
|
|
id: row.id,
|
|
providerId: row.provider_id,
|
|
mode: row.mode,
|
|
cliproxyapiModelMapping:
|
|
row.cliproxyapi_model_mapping && typeof row.cliproxyapi_model_mapping === "string"
|
|
? JSON.parse(row.cliproxyapi_model_mapping)
|
|
: null,
|
|
nativePriority: row.native_priority,
|
|
cliproxyapiPriority: row.cliproxyapi_priority,
|
|
enabled: row.enabled === 1,
|
|
createdAt: row.created_at,
|
|
updatedAt: row.updated_at,
|
|
};
|
|
}
|
|
|
|
function getAllConfigs(db) {
|
|
return db
|
|
.prepare("SELECT * FROM upstream_proxy_config ORDER BY provider_id")
|
|
.all()
|
|
.map((r) => ({
|
|
id: r.id,
|
|
providerId: r.provider_id,
|
|
mode: r.mode,
|
|
cliproxyapiModelMapping:
|
|
r.cliproxyapi_model_mapping && typeof r.cliproxyapi_model_mapping === "string"
|
|
? JSON.parse(r.cliproxyapi_model_mapping)
|
|
: null,
|
|
nativePriority: r.native_priority,
|
|
cliproxyapiPriority: r.cliproxyapi_priority,
|
|
enabled: r.enabled === 1,
|
|
createdAt: r.created_at,
|
|
updatedAt: r.updated_at,
|
|
}));
|
|
}
|
|
|
|
function getProvidersByMode(db, mode) {
|
|
return db
|
|
.prepare(
|
|
"SELECT * FROM upstream_proxy_config WHERE mode = ? AND enabled = 1 ORDER BY provider_id"
|
|
)
|
|
.all(mode)
|
|
.map((r) => ({
|
|
id: r.id,
|
|
providerId: r.provider_id,
|
|
mode: r.mode,
|
|
cliproxyapiModelMapping: r.cliproxyapi_model_mapping
|
|
? JSON.parse(r.cliproxyapi_model_mapping)
|
|
: null,
|
|
nativePriority: r.native_priority,
|
|
cliproxyapiPriority: r.cliproxyapi_priority,
|
|
enabled: r.enabled === 1,
|
|
}));
|
|
}
|
|
|
|
function getFallbackChain(db, providerId) {
|
|
const config = getConfig(db, providerId);
|
|
if (!config) return [];
|
|
const chain = [];
|
|
if (config.enabled) {
|
|
chain.push({ executor: "native", priority: config.nativePriority });
|
|
if (config.mode === "cliproxyapi" || config.mode === "fallback") {
|
|
chain.push({ executor: "cliproxyapi", priority: config.cliproxyapiPriority });
|
|
}
|
|
}
|
|
chain.sort((a, b) => a.priority - b.priority);
|
|
return chain;
|
|
}
|
|
|
|
describe("db/upstreamProxy (logic)", () => {
|
|
describe("upsertUpstreamProxyConfig", () => {
|
|
it("should insert and read back", () => {
|
|
const config = upsert(testDb, { providerId: "claude", mode: "native" });
|
|
assert.equal(config.providerId, "claude");
|
|
assert.equal(config.mode, "native");
|
|
assert.equal(config.enabled, true);
|
|
assert.equal(config.nativePriority, 1);
|
|
assert.equal(config.cliproxyapiPriority, 2);
|
|
assert.equal(config.cliproxyapiModelMapping, null);
|
|
assert.ok(config.id > 0);
|
|
});
|
|
|
|
it("should replace on conflict", () => {
|
|
upsert(testDb, { providerId: "t", mode: "native" });
|
|
const replaced = upsert(testDb, { providerId: "t", mode: "fallback" });
|
|
assert.equal(replaced.mode, "fallback");
|
|
});
|
|
|
|
it("should store model mapping as JSON", () => {
|
|
const mapping = { "ag/gemini-3-pro": "gemini-3-pro-high" };
|
|
const config = upsert(testDb, { providerId: "mapped", cliproxyapiModelMapping: mapping });
|
|
assert.deepEqual(config.cliproxyapiModelMapping, mapping);
|
|
});
|
|
|
|
it("should store null model mapping", () => {
|
|
const config = upsert(testDb, { providerId: "nomap", cliproxyapiModelMapping: null });
|
|
assert.equal(config.cliproxyapiModelMapping, null);
|
|
});
|
|
|
|
it("should handle enabled=false", () => {
|
|
assert.equal(upsert(testDb, { providerId: "dis", enabled: false }).enabled, false);
|
|
});
|
|
|
|
it("should set custom priorities", () => {
|
|
const config = upsert(testDb, {
|
|
providerId: "pri",
|
|
nativePriority: 5,
|
|
cliproxyapiPriority: 10,
|
|
});
|
|
assert.equal(config.nativePriority, 5);
|
|
assert.equal(config.cliproxyapiPriority, 10);
|
|
});
|
|
});
|
|
|
|
describe("getUpstreamProxyConfig", () => {
|
|
it("should return null for non-existent provider", () => {
|
|
assert.equal(getConfig(testDb, "ghost"), null);
|
|
});
|
|
|
|
it("should return config for provider", () => {
|
|
upsert(testDb, { providerId: "claude", mode: "fallback" });
|
|
assert.equal(getConfig(testDb, "claude").mode, "fallback");
|
|
});
|
|
});
|
|
|
|
describe("getUpstreamProxyConfigs", () => {
|
|
it("should return all ordered by provider_id", () => {
|
|
upsert(testDb, { providerId: "zebra" });
|
|
upsert(testDb, { providerId: "alpha" });
|
|
const configs = getAllConfigs(testDb);
|
|
assert.equal(configs.length, 2);
|
|
assert.equal(configs[0].providerId, "alpha");
|
|
assert.equal(configs[1].providerId, "zebra");
|
|
});
|
|
|
|
it("should return empty array", () => {
|
|
assert.equal(getAllConfigs(testDb).length, 0);
|
|
});
|
|
});
|
|
|
|
describe("updateUpstreamProxyConfig", () => {
|
|
it("should update individual fields", () => {
|
|
upsert(testDb, { providerId: "u", mode: "native" });
|
|
testDb
|
|
.prepare(
|
|
"UPDATE upstream_proxy_config SET mode = ?, updated_at = datetime('now') WHERE provider_id = ?"
|
|
)
|
|
.run("cliproxyapi", "u");
|
|
assert.equal(getConfig(testDb, "u").mode, "cliproxyapi");
|
|
});
|
|
|
|
it("should update model mapping", () => {
|
|
upsert(testDb, { providerId: "u2" });
|
|
testDb
|
|
.prepare(
|
|
"UPDATE upstream_proxy_config SET cliproxyapi_model_mapping = ?, updated_at = datetime('now') WHERE provider_id = ?"
|
|
)
|
|
.run(JSON.stringify({ k: "v" }), "u2");
|
|
assert.deepEqual(getConfig(testDb, "u2").cliproxyapiModelMapping, { k: "v" });
|
|
});
|
|
|
|
it("should update multiple fields", () => {
|
|
upsert(testDb, { providerId: "m" });
|
|
testDb
|
|
.prepare(
|
|
"UPDATE upstream_proxy_config SET mode = ?, native_priority = ?, enabled = ?, updated_at = datetime('now') WHERE provider_id = ?"
|
|
)
|
|
.run("fallback", 3, 0, "m");
|
|
const config = getConfig(testDb, "m");
|
|
assert.equal(config.mode, "fallback");
|
|
assert.equal(config.nativePriority, 3);
|
|
assert.equal(config.enabled, false);
|
|
});
|
|
|
|
it("should set model mapping to null", () => {
|
|
upsert(testDb, { providerId: "n", cliproxyapiModelMapping: { a: 1 } });
|
|
testDb
|
|
.prepare(
|
|
"UPDATE upstream_proxy_config SET cliproxyapi_model_mapping = NULL WHERE provider_id = ?"
|
|
)
|
|
.run("n");
|
|
assert.equal(getConfig(testDb, "n").cliproxyapiModelMapping, null);
|
|
});
|
|
});
|
|
|
|
describe("deleteUpstreamProxyConfig", () => {
|
|
it("should delete existing config", () => {
|
|
upsert(testDb, { providerId: "del" });
|
|
assert.equal(
|
|
testDb.prepare("DELETE FROM upstream_proxy_config WHERE provider_id = ?").run("del")
|
|
.changes,
|
|
1
|
|
);
|
|
assert.equal(getConfig(testDb, "del"), null);
|
|
});
|
|
|
|
it("should return 0 for non-existent", () => {
|
|
assert.equal(
|
|
testDb.prepare("DELETE FROM upstream_proxy_config WHERE provider_id = ?").run("ghost")
|
|
.changes,
|
|
0
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("getProvidersByMode", () => {
|
|
it("should filter by mode and enabled", () => {
|
|
upsert(testDb, { providerId: "p1", mode: "fallback", enabled: true });
|
|
upsert(testDb, { providerId: "p2", mode: "fallback", enabled: true });
|
|
upsert(testDb, { providerId: "p3", mode: "native", enabled: true });
|
|
upsert(testDb, { providerId: "p4", mode: "fallback", enabled: false });
|
|
const results = getProvidersByMode(testDb, "fallback");
|
|
assert.equal(results.length, 2);
|
|
assert.ok(results.every((r) => r.enabled));
|
|
});
|
|
|
|
it("should return empty for no matches", () => {
|
|
assert.equal(getProvidersByMode(testDb, "cliproxyapi").length, 0);
|
|
});
|
|
});
|
|
|
|
describe("getFallbackChainForProvider", () => {
|
|
it("should return empty for non-existent provider", () => {
|
|
assert.deepEqual(getFallbackChain(testDb, "ghost"), []);
|
|
});
|
|
|
|
it("should return native-only for native mode", () => {
|
|
upsert(testDb, { providerId: "native-only", mode: "native" });
|
|
const chain = getFallbackChain(testDb, "native-only");
|
|
assert.equal(chain.length, 1);
|
|
assert.equal(chain[0].executor, "native");
|
|
});
|
|
|
|
it("should return native+cliproxyapi for fallback mode", () => {
|
|
upsert(testDb, {
|
|
providerId: "fb",
|
|
mode: "fallback",
|
|
nativePriority: 1,
|
|
cliproxyapiPriority: 2,
|
|
});
|
|
const chain = getFallbackChain(testDb, "fb");
|
|
assert.equal(chain.length, 2);
|
|
assert.equal(chain[0].executor, "native");
|
|
assert.equal(chain[1].executor, "cliproxyapi");
|
|
});
|
|
|
|
it("should return both for cliproxyapi mode", () => {
|
|
upsert(testDb, { providerId: "cpa", mode: "cliproxyapi" });
|
|
const chain = getFallbackChain(testDb, "cpa");
|
|
assert.equal(chain.length, 2);
|
|
});
|
|
|
|
it("should sort by priority", () => {
|
|
upsert(testDb, {
|
|
providerId: "rev",
|
|
mode: "fallback",
|
|
nativePriority: 10,
|
|
cliproxyapiPriority: 1,
|
|
});
|
|
const chain = getFallbackChain(testDb, "rev");
|
|
assert.equal(chain[0].executor, "cliproxyapi");
|
|
assert.equal(chain[0].priority, 1);
|
|
assert.equal(chain[1].executor, "native");
|
|
assert.equal(chain[1].priority, 10);
|
|
});
|
|
|
|
it("should return empty chain when disabled", () => {
|
|
upsert(testDb, { providerId: "dis-fb", mode: "fallback", enabled: false });
|
|
assert.deepEqual(getFallbackChain(testDb, "dis-fb"), []);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("db/upstreamProxy (module coverage)", () => {
|
|
beforeEach(async () => {
|
|
await resetModuleStorage();
|
|
});
|
|
|
|
after(async () => {
|
|
coreDb.resetDbInstance();
|
|
fs.rmSync(moduleDataDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
});
|
|
|
|
it("validates proxy URLs and blocks unsupported or private destinations", async () => {
|
|
assert.deepEqual(upstreamProxyDb.validateProxyUrl("https://proxy.example.com"), {
|
|
valid: true,
|
|
url: "https://proxy.example.com",
|
|
});
|
|
assert.equal(upstreamProxyDb.validateProxyUrl("ftp://proxy.example.com").valid, false);
|
|
assert.match(
|
|
upstreamProxyDb.validateProxyUrl("http://169.254.169.254").error,
|
|
/private\/internal address/
|
|
);
|
|
assert.match(upstreamProxyDb.validateProxyUrl("not-a-url").error, /Invalid URL/);
|
|
});
|
|
|
|
it("round-trips configs through upsert, update, mode filters and fallback ordering", async () => {
|
|
await upstreamProxyDb.upsertUpstreamProxyConfig({
|
|
providerId: "claude",
|
|
mode: "fallback",
|
|
cliproxyapiModelMapping: { "claude-4": "claude-4-cli" },
|
|
nativePriority: 10,
|
|
cliproxyapiPriority: 1,
|
|
});
|
|
await upstreamProxyDb.upsertUpstreamProxyConfig({
|
|
providerId: "openai",
|
|
mode: "native",
|
|
enabled: false,
|
|
});
|
|
|
|
const loaded = await upstreamProxyDb.getUpstreamProxyConfig("claude");
|
|
assert.deepEqual(loaded.cliproxyapiModelMapping, { "claude-4": "claude-4-cli" });
|
|
|
|
const updated = await upstreamProxyDb.updateUpstreamProxyConfig("claude", {
|
|
mode: "cliproxyapi",
|
|
cliproxyapiModelMapping: null,
|
|
enabled: true,
|
|
});
|
|
assert.equal(updated.mode, "cliproxyapi");
|
|
assert.equal(updated.cliproxyapiModelMapping, null);
|
|
|
|
const byMode = await upstreamProxyDb.getProvidersByMode("cliproxyapi");
|
|
assert.equal(byMode.length, 1);
|
|
assert.equal(byMode[0].providerId, "claude");
|
|
|
|
const chain = await upstreamProxyDb.getFallbackChainForProvider("claude");
|
|
assert.deepEqual(chain, [
|
|
{ executor: "cliproxyapi", priority: 1 },
|
|
{ executor: "native", priority: 10 },
|
|
]);
|
|
});
|
|
|
|
it("handles invalid stored JSON, missing rows and deletion", async () => {
|
|
const db = coreDb.getDbInstance();
|
|
db.prepare(
|
|
`
|
|
INSERT INTO upstream_proxy_config
|
|
(provider_id, mode, cliproxyapi_model_mapping, native_priority, cliproxyapi_priority, enabled, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))
|
|
`
|
|
).run("broken", "fallback", "{not-json", 1, 2, 1);
|
|
|
|
const broken = await upstreamProxyDb.getUpstreamProxyConfig("broken");
|
|
assert.equal(broken.cliproxyapiModelMapping, null);
|
|
|
|
await assert.rejects(
|
|
upstreamProxyDb.updateUpstreamProxyConfig("ghost", { mode: "native" }),
|
|
/Provider ghost not found/
|
|
);
|
|
|
|
assert.equal(await upstreamProxyDb.deleteUpstreamProxyConfig("broken"), true);
|
|
assert.equal(await upstreamProxyDb.deleteUpstreamProxyConfig("broken"), false);
|
|
assert.deepEqual(await upstreamProxyDb.getFallbackChainForProvider("ghost"), []);
|
|
});
|
|
});
|