My-Free-LLM-API / server /src /__tests__ /db /idempotency.test.ts
tayyabimam's picture
Fresh build completely clean of binaries
35ac985
Raw
History Blame Contribute Delete
9.34 kB
import { describe, it, expect } from 'vitest';
import Database from 'better-sqlite3';
import { initDb } from '../../db/index.js';
/**
* All migrations must be idempotent: running initDb twice on the same
* physical database file should produce identical state.
*/
describe('Migration idempotency', () => {
it('initDb on a fresh in-memory DB then re-run produces identical row counts', () => {
process.env.ENCRYPTION_KEY = '0'.repeat(64);
// Use a single shared file so both inits hit the same DB.
const tmpPath = `/tmp/freeapi-idempotency-${Date.now()}.db`;
const db1 = initDb(tmpPath);
const before = {
models: (db1.prepare('SELECT COUNT(*) AS c FROM models').get() as { c: number }).c,
fallback: (db1.prepare('SELECT COUNT(*) AS c FROM fallback_config').get() as { c: number }).c,
enabledModels: (db1.prepare('SELECT COUNT(*) AS c FROM models WHERE enabled = 1').get() as { c: number }).c,
disabledModels: (db1.prepare('SELECT COUNT(*) AS c FROM models WHERE enabled = 0').get() as { c: number }).c,
orphanFallbacks: (db1.prepare(`
SELECT COUNT(*) AS c FROM fallback_config f
LEFT JOIN models m ON f.model_db_id = m.id
WHERE m.id IS NULL
`).get() as { c: number }).c,
};
db1.close();
// Re-init the same DB file — V1..V9 should all no-op idempotently.
const db2 = initDb(tmpPath);
const after = {
models: (db2.prepare('SELECT COUNT(*) AS c FROM models').get() as { c: number }).c,
fallback: (db2.prepare('SELECT COUNT(*) AS c FROM fallback_config').get() as { c: number }).c,
enabledModels: (db2.prepare('SELECT COUNT(*) AS c FROM models WHERE enabled = 1').get() as { c: number }).c,
disabledModels: (db2.prepare('SELECT COUNT(*) AS c FROM models WHERE enabled = 0').get() as { c: number }).c,
orphanFallbacks: (db2.prepare(`
SELECT COUNT(*) AS c FROM fallback_config f
LEFT JOIN models m ON f.model_db_id = m.id
WHERE m.id IS NULL
`).get() as { c: number }).c,
};
db2.close();
expect(after).toEqual(before);
expect(after.orphanFallbacks).toBe(0);
});
it('every catalog row has exactly one fallback_config entry', () => {
process.env.ENCRYPTION_KEY = '0'.repeat(64);
const db = initDb(':memory:');
const rows = db.prepare(`
SELECT m.id, COUNT(f.id) AS fb_count
FROM models m
LEFT JOIN fallback_config f ON m.id = f.model_db_id
GROUP BY m.id
HAVING COUNT(f.id) <> 1
`).all() as { id: number; fb_count: number }[];
expect(rows).toEqual([]);
});
it('UNIQUE(platform, model_id) constraint holds — no duplicate catalog rows', () => {
process.env.ENCRYPTION_KEY = '0'.repeat(64);
const db = initDb(':memory:');
const dups = db.prepare(`
SELECT platform, model_id, COUNT(*) AS c FROM models
GROUP BY platform, model_id
HAVING COUNT(*) > 1
`).all();
expect(dups).toEqual([]);
});
it('V12: dead OR :free rows are absent and the four new rows are present', () => {
process.env.ENCRYPTION_KEY = '0'.repeat(64);
const db = initDb(':memory:');
const dead = db.prepare(`
SELECT model_id FROM models
WHERE platform = 'openrouter'
AND model_id IN ('inclusionai/ling-2.6-1t:free', 'tencent/hy3-preview:free')
`).all();
expect(dead).toEqual([]);
const live = db.prepare(`
SELECT model_id FROM models
WHERE platform = 'openrouter'
AND model_id IN (
'arcee-ai/trinity-large-thinking:free',
'baidu/cobuddy:free',
'openrouter/owl-alpha',
'nousresearch/hermes-3-llama-3.1-405b:free'
)
ORDER BY model_id
`).all() as { model_id: string }[];
expect(live.map(r => r.model_id)).toEqual([
'arcee-ai/trinity-large-thinking:free',
'baidu/cobuddy:free',
'nousresearch/hermes-3-llama-3.1-405b:free',
'openrouter/owl-alpha',
]);
const widened = db.prepare(`
SELECT model_id, context_window FROM models
WHERE platform = 'openrouter'
AND model_id IN ('nvidia/nemotron-3-super-120b-a12b:free', 'qwen/qwen3-coder:free')
ORDER BY model_id
`).all() as { model_id: string; context_window: number }[];
expect(widened).toEqual([
{ model_id: 'nvidia/nemotron-3-super-120b-a12b:free', context_window: 1000000 },
{ model_id: 'qwen/qwen3-coder:free', context_window: 1048576 },
]);
});
it('V13: cross-provider catalog refresh applies cleanly', () => {
process.env.ENCRYPTION_KEY = '0'.repeat(64);
const db = initDb(':memory:');
// Disables — row kept but enabled=0.
const disabled = db.prepare(`
SELECT platform, model_id, enabled FROM models
WHERE (platform = 'google' AND model_id = 'gemini-3.1-pro-preview')
OR (platform = 'ollama' AND model_id IN ('kimi-k2-thinking', 'mistral-large-3:675b', 'deepseek-v3.2'))
ORDER BY platform, model_id
`).all() as { platform: string; model_id: string; enabled: number }[];
expect(disabled).toHaveLength(4);
for (const row of disabled) expect(row.enabled).toBe(0);
// Hard removals — row is gone entirely.
const removed = db.prepare(`
SELECT model_id FROM models
WHERE (platform = 'sambanova' AND model_id = 'DeepSeek-V3.1-cb')
OR (platform = 'cloudflare' AND model_id = '@cf/moonshotai/kimi-k2.5')
`).all();
expect(removed).toEqual([]);
// New rows present across providers (incl. new huggingface platform).
const additions = db.prepare(`
SELECT platform, model_id FROM models
WHERE (platform, model_id) IN (VALUES
('groq', 'openai/gpt-oss-safeguard-20b'),
('cloudflare', '@cf/nvidia/nemotron-3-120b-a12b'),
('cloudflare', '@cf/google/gemma-4-26b-a4b-it'),
('google', 'gemini-3.5-flash'),
('nvidia', 'deepseek-ai/deepseek-v4-flash'),
('nvidia', 'z-ai/glm-5.1'),
('nvidia', 'qwen/qwen3-coder-480b-a35b-instruct'),
('mistral', 'mistral-small-latest'),
('mistral', 'ministral-8b-latest'),
('cohere', 'command-a-reasoning-08-2025'),
('cohere', 'command-r-08-2024'),
('ollama', 'qwen3-coder-next'),
('huggingface', 'deepseek-ai/DeepSeek-V4-Flash'),
('huggingface', 'moonshotai/Kimi-K2.6'),
('huggingface', 'Qwen/Qwen3-Coder-Next')
)
`).all();
expect(additions).toHaveLength(15);
// Spot-check critical limit/context updates.
const cerebrasLimits = db.prepare(`
SELECT rpm_limit, rpd_limit, tpm_limit, tpd_limit FROM models
WHERE platform = 'cerebras' AND model_id = 'qwen-3-235b-a22b-instruct-2507'
`).get() as { rpm_limit: number; rpd_limit: number; tpm_limit: number; tpd_limit: number };
expect(cerebrasLimits).toEqual({ rpm_limit: 5, rpd_limit: 2400, tpm_limit: 30000, tpd_limit: 1000000 });
const sambanovaCtx = (db.prepare(`
SELECT context_window FROM models WHERE platform = 'sambanova' AND model_id = 'DeepSeek-V3.2'
`).get() as { context_window: number }).context_window;
expect(sambanovaCtx).toBe(32768);
const cfFp8Ctx = (db.prepare(`
SELECT context_window FROM models WHERE platform = 'cloudflare' AND model_id = '@cf/meta/llama-3.3-70b-instruct-fp8-fast'
`).get() as { context_window: number }).context_window;
expect(cfFp8Ctx).toBe(24000);
const mistralCtx = db.prepare(`
SELECT model_id, context_window FROM models
WHERE platform = 'mistral'
AND model_id IN ('codestral-latest', 'devstral-latest', 'magistral-medium-latest', 'mistral-large-latest')
ORDER BY model_id
`).all() as { model_id: string; context_window: number }[];
expect(mistralCtx).toEqual([
{ model_id: 'codestral-latest', context_window: 256000 },
{ model_id: 'devstral-latest', context_window: 262144 },
{ model_id: 'magistral-medium-latest', context_window: 131072 },
{ model_id: 'mistral-large-latest', context_window: 262144 },
]);
});
it('V14: cerebras deprecation disables qwen-3-235b and llama3.1-8b but keeps gpt-oss-120b enabled', () => {
process.env.ENCRYPTION_KEY = '0'.repeat(64);
const db = initDb(':memory:');
const rows = db.prepare(`
SELECT model_id, enabled FROM models
WHERE platform = 'cerebras'
AND model_id IN ('qwen-3-235b-a22b-instruct-2507', 'llama3.1-8b', 'gpt-oss-120b')
ORDER BY model_id
`).all() as { model_id: string; enabled: number }[];
expect(rows).toEqual([
{ model_id: 'gpt-oss-120b', enabled: 1 },
{ model_id: 'llama3.1-8b', enabled: 0 },
{ model_id: 'qwen-3-235b-a22b-instruct-2507', enabled: 0 },
]);
});
it('all enabled catalog platforms have a registered provider', async () => {
process.env.ENCRYPTION_KEY = '0'.repeat(64);
const db = initDb(':memory:');
const { hasProvider } = await import('../../providers/index.js');
const platforms = (db.prepare(
`SELECT DISTINCT platform FROM models WHERE enabled = 1`
).all() as { platform: any }[]).map(r => r.platform);
const missing = platforms.filter(p => !hasProvider(p));
expect(missing).toEqual([]);
});
});