llm-complete-openrouter-stress.test.mjs file-level

at sha256:3 · View file ↗ · Intel ↗

History
1 files
1 commits
0 hotspots
0 🧊 dead
0 💥 blast risk
sha256:9 feat(calendar): hosted bridge/gateway route parity and timeline noteRec… · aaronrene · Jun 19, 2026
1 /**
2 * Tier 4 — STRESS: the OpenRouter lane under high concurrency and high sequential volume.
3 *
4 * Goal: confirm the lane has no shared mutable state that corrupts results when many calls
5 * run at once, that every call maps to exactly one upstream request, and that a partial
6 * failure in a batch is isolated to that call. Network is mocked.
7 */
8 import { describe, it, beforeEach, afterEach } from 'node:test';
9 import assert from 'node:assert';
10 import { completeChat } from '../lib/llm-complete.mjs';
11
12 const ORIG = { ...process.env };
13 const origFetch = globalThis.fetch;
14
15 const CHAT_ENV_KEYS = [
16 'OPENAI_API_KEY',
17 'ANTHROPIC_API_KEY',
18 'DEEPINFRA_API_KEY',
19 'OPENROUTER_API_KEY',
20 'OPENROUTER_CHAT_MODEL',
21 'OPENROUTER_SITE_URL',
22 'OPENROUTER_APP_TITLE',
23 'KNOWTATION_CHAT_PROVIDER',
24 'KNOWTATION_CHAT_PREFER_ANTHROPIC',
25 ];
26
27 function clearChatEnv() {
28 for (const k of CHAT_ENV_KEYS) delete process.env[k];
29 }
30
31 function restoreEnv() {
32 for (const k of CHAT_ENV_KEYS) {
33 if (ORIG[k] === undefined) delete process.env[k];
34 else process.env[k] = ORIG[k];
35 }
36 }
37
38 describe('OpenRouter lane — stress', () => {
39 beforeEach(() => {
40 clearChatEnv();
41 process.env.KNOWTATION_CHAT_PROVIDER = 'openrouter';
42 process.env.OPENROUTER_API_KEY = 'or-stress';
43 });
44
45 afterEach(() => {
46 globalThis.fetch = origFetch;
47 restoreEnv();
48 });
49
50 it('500 concurrent calls each return their own correct, non-cross-contaminated result', async () => {
51 let fetchCount = 0;
52 globalThis.fetch = async (url, init) => {
53 fetchCount += 1;
54 // Echo the user content back so we can prove no response was crossed between calls.
55 const sent = JSON.parse(init.body).messages[1].content;
56 await new Promise((r) => setTimeout(r, Math.floor(Math.random() * 3)));
57 return { ok: true, json: async () => ({ choices: [{ message: { content: `echo:${sent}` } }] }) };
58 };
59
60 const N = 500;
61 const results = await Promise.all(
62 Array.from({ length: N }, (_, i) =>
63 completeChat({}, { system: 's', user: `payload-${i}` }),
64 ),
65 );
66
67 assert.strictEqual(fetchCount, N);
68 for (let i = 0; i < N; i += 1) {
69 assert.strictEqual(results[i], `echo:payload-${i}`);
70 }
71 });
72
73 it('1000 sequential calls all succeed with stable behaviour', async () => {
74 globalThis.fetch = async () => ({
75 ok: true,
76 json: async () => ({ choices: [{ message: { content: 'stable' } }] }),
77 });
78 for (let i = 0; i < 1000; i += 1) {
79 const out = await completeChat({}, { system: 's', user: `n-${i}` });
80 assert.strictEqual(out, 'stable');
81 }
82 });
83
84 it('one failing call in a concurrent batch does not break the others', async () => {
85 globalThis.fetch = async (url, init) => {
86 const sent = JSON.parse(init.body).messages[1].content;
87 if (sent === 'user-3') return { ok: false, status: 500, text: async () => 'boom' };
88 return { ok: true, json: async () => ({ choices: [{ message: { content: `ok:${sent}` } }] }) };
89 };
90
91 const settled = await Promise.allSettled(
92 Array.from({ length: 10 }, (_, i) => completeChat({}, { system: 's', user: `user-${i}` })),
93 );
94
95 const failures = settled.filter((s) => s.status === 'rejected');
96 const successes = settled.filter((s) => s.status === 'fulfilled');
97 assert.strictEqual(failures.length, 1);
98 assert.strictEqual(successes.length, 9);
99 assert.match(failures[0].reason.message, /OpenRouter chat failed: 500/);
100 });
101 });