mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 17:28:28 +00:00
test: dedupe auth fallback tests and add auth util unit coverage
This commit is contained in:
@@ -23,6 +23,61 @@ function makeCfg(overrides: Partial<OpenClawConfig> = {}): OpenClawConfig {
|
||||
} as OpenClawConfig;
|
||||
}
|
||||
|
||||
function makeFallbacksOnlyCfg(): OpenClawConfig {
|
||||
return {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: {
|
||||
fallbacks: ["openai/gpt-5.2"],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
}
|
||||
|
||||
function makeProviderFallbackCfg(provider: string): OpenClawConfig {
|
||||
return makeCfg({
|
||||
agents: {
|
||||
defaults: {
|
||||
model: {
|
||||
primary: `${provider}/m1`,
|
||||
fallbacks: ["fallback/ok-model"],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function withTempAuthStore<T>(
|
||||
store: AuthProfileStore,
|
||||
run: (tempDir: string) => Promise<T>,
|
||||
): Promise<T> {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-auth-"));
|
||||
saveAuthProfileStore(store, tempDir);
|
||||
try {
|
||||
return await run(tempDir);
|
||||
} finally {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
async function runWithStoredAuth(params: {
|
||||
cfg: OpenClawConfig;
|
||||
store: AuthProfileStore;
|
||||
provider: string;
|
||||
run: (provider: string, model: string) => Promise<string>;
|
||||
}) {
|
||||
return withTempAuthStore(params.store, async (tempDir) =>
|
||||
runWithModelFallback({
|
||||
cfg: params.cfg,
|
||||
provider: params.provider,
|
||||
model: "m1",
|
||||
agentDir: tempDir,
|
||||
run: params.run,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async function expectFallsBackToHaiku(params: {
|
||||
provider: string;
|
||||
model: string;
|
||||
@@ -121,7 +176,6 @@ describe("runWithModelFallback", () => {
|
||||
});
|
||||
|
||||
it("skips providers when all profiles are in cooldown", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-auth-"));
|
||||
const provider = `cooldown-test-${crypto.randomUUID()}`;
|
||||
const profileId = `${provider}:default`;
|
||||
|
||||
@@ -136,23 +190,12 @@ describe("runWithModelFallback", () => {
|
||||
},
|
||||
usageStats: {
|
||||
[profileId]: {
|
||||
cooldownUntil: Date.now() + 60_000,
|
||||
cooldownUntil: Date.now() + 5 * 60_000,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
saveAuthProfileStore(store, tempDir);
|
||||
|
||||
const cfg = makeCfg({
|
||||
agents: {
|
||||
defaults: {
|
||||
model: {
|
||||
primary: `${provider}/m1`,
|
||||
fallbacks: ["fallback/ok-model"],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const cfg = makeProviderFallbackCfg(provider);
|
||||
const run = vi.fn().mockImplementation(async (providerId, modelId) => {
|
||||
if (providerId === "fallback") {
|
||||
return "ok";
|
||||
@@ -160,25 +203,19 @@ describe("runWithModelFallback", () => {
|
||||
throw new Error(`unexpected provider: ${providerId}/${modelId}`);
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await runWithModelFallback({
|
||||
cfg,
|
||||
provider,
|
||||
model: "m1",
|
||||
agentDir: tempDir,
|
||||
run,
|
||||
});
|
||||
const result = await runWithStoredAuth({
|
||||
cfg,
|
||||
store,
|
||||
provider,
|
||||
run,
|
||||
});
|
||||
|
||||
expect(result.result).toBe("ok");
|
||||
expect(run.mock.calls).toEqual([["fallback", "ok-model"]]);
|
||||
expect(result.attempts[0]?.reason).toBe("rate_limit");
|
||||
} finally {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
expect(result.result).toBe("ok");
|
||||
expect(run.mock.calls).toEqual([["fallback", "ok-model"]]);
|
||||
expect(result.attempts[0]?.reason).toBe("rate_limit");
|
||||
});
|
||||
|
||||
it("does not skip when any profile is available", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-auth-"));
|
||||
const provider = `cooldown-mixed-${crypto.randomUUID()}`;
|
||||
const profileA = `${provider}:a`;
|
||||
const profileB = `${provider}:b`;
|
||||
@@ -204,18 +241,7 @@ describe("runWithModelFallback", () => {
|
||||
},
|
||||
};
|
||||
|
||||
saveAuthProfileStore(store, tempDir);
|
||||
|
||||
const cfg = makeCfg({
|
||||
agents: {
|
||||
defaults: {
|
||||
model: {
|
||||
primary: `${provider}/m1`,
|
||||
fallbacks: ["fallback/ok-model"],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const cfg = makeProviderFallbackCfg(provider);
|
||||
const run = vi.fn().mockImplementation(async (providerId) => {
|
||||
if (providerId === provider) {
|
||||
return "ok";
|
||||
@@ -223,21 +249,16 @@ describe("runWithModelFallback", () => {
|
||||
return "unexpected";
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await runWithModelFallback({
|
||||
cfg,
|
||||
provider,
|
||||
model: "m1",
|
||||
agentDir: tempDir,
|
||||
run,
|
||||
});
|
||||
const result = await runWithStoredAuth({
|
||||
cfg,
|
||||
store,
|
||||
provider,
|
||||
run,
|
||||
});
|
||||
|
||||
expect(result.result).toBe("ok");
|
||||
expect(run.mock.calls).toEqual([[provider, "m1"]]);
|
||||
expect(result.attempts).toEqual([]);
|
||||
} finally {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
expect(result.result).toBe("ok");
|
||||
expect(run.mock.calls).toEqual([[provider, "m1"]]);
|
||||
expect(result.attempts).toEqual([]);
|
||||
});
|
||||
|
||||
it("does not append configured primary when fallbacksOverride is set", async () => {
|
||||
@@ -271,15 +292,7 @@ describe("runWithModelFallback", () => {
|
||||
});
|
||||
|
||||
it("uses fallbacksOverride instead of agents.defaults.model.fallbacks", async () => {
|
||||
const cfg = {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: {
|
||||
fallbacks: ["openai/gpt-5.2"],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const cfg = makeFallbacksOnlyCfg();
|
||||
|
||||
const calls: Array<{ provider: string; model: string }> = [];
|
||||
|
||||
@@ -308,15 +321,7 @@ describe("runWithModelFallback", () => {
|
||||
});
|
||||
|
||||
it("treats an empty fallbacksOverride as disabling global fallbacks", async () => {
|
||||
const cfg = {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: {
|
||||
fallbacks: ["openai/gpt-5.2"],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const cfg = makeFallbacksOnlyCfg();
|
||||
|
||||
const calls: Array<{ provider: string; model: string }> = [];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user