Files
openmaic/OpenMAIC/render-service/test/config.test.ts
2026-08-16 14:58:47 +08:00

103 lines
3.6 KiB
TypeScript

/**
* Config env parsing — specifically the knobs whose zero value is meaningful.
* `RENDER_MAX_JOBS_PER_USER=0` must *disable* the per-identity guard (documented
* behavior); the earlier `intEnv` rejected 0 and silently fell back to 1, so the
* guard couldn't be turned off. Config resolves env once at import, so each case
* resets the module registry and re-imports under a fresh environment.
*/
import { describe, it, expect, afterEach, vi } from 'vitest';
const KEYS = [
'RENDER_RESOURCE_PROFILE',
'RENDER_MAX_JOBS_PER_USER',
'RENDER_MAX_CONCURRENCY',
'RENDER_MAX_CONCURRENT_EXTRACTIONS',
'PRODUCER_MAX_WORKERS',
'PRODUCER_LOW_MEMORY_MODE',
'PRODUCER_FORCE_SCREENSHOT',
'PRODUCER_BROWSER_GPU_MODE',
'PRODUCER_ENABLE_BROWSER_POOL',
'RENDER_REQUIRE_BEGINFRAME',
] as const;
const originals = Object.fromEntries(KEYS.map((key) => [key, process.env[key]]));
afterEach(() => {
for (const key of KEYS) {
const original = originals[key];
if (original === undefined) delete process.env[key];
else process.env[key] = original;
}
vi.resetModules();
});
async function loadConfig() {
vi.resetModules();
const mod = await import('../src/config.js');
return mod.config;
}
describe('config maxJobsPerUser', () => {
it('accepts 0 to disable the per-identity guard', async () => {
process.env.RENDER_MAX_JOBS_PER_USER = '0';
expect((await loadConfig()).maxJobsPerUser).toBe(0);
});
it('accepts a positive override', async () => {
process.env.RENDER_MAX_JOBS_PER_USER = '5';
expect((await loadConfig()).maxJobsPerUser).toBe(5);
});
it('falls back to the default (1) for negative or non-numeric values', async () => {
process.env.RENDER_MAX_JOBS_PER_USER = '-3';
expect((await loadConfig()).maxJobsPerUser).toBe(1);
process.env.RENDER_MAX_JOBS_PER_USER = 'nonsense';
expect((await loadConfig()).maxJobsPerUser).toBe(1);
});
it('falls back to the default when unset', async () => {
delete process.env.RENDER_MAX_JOBS_PER_USER;
expect((await loadConfig()).maxJobsPerUser).toBe(1);
});
});
describe('config producerWorkers', () => {
it('defaults to one explicit worker in the standard profile', async () => {
delete process.env.PRODUCER_MAX_WORKERS;
expect((await loadConfig()).producerWorkers).toBe(1);
});
it('accepts an explicit single-worker profile without silently raising it', async () => {
process.env.PRODUCER_MAX_WORKERS = '1';
expect((await loadConfig()).producerWorkers).toBe(1);
});
it('rejects worker overrides that contradict the profile', async () => {
process.env.PRODUCER_MAX_WORKERS = '0';
await expect(loadConfig()).rejects.toThrow(/requires PRODUCER_MAX_WORKERS=1/);
});
});
describe('config latency-profile concurrency', () => {
it('defaults to one render and one extraction at a time', async () => {
delete process.env.RENDER_MAX_CONCURRENCY;
delete process.env.RENDER_MAX_CONCURRENT_EXTRACTIONS;
const config = await loadConfig();
expect(config.maxConcurrency).toBe(1);
expect(config.maxConcurrentExtractions).toBe(1);
});
it('rejects service concurrency that exceeds the selected profile', async () => {
process.env.RENDER_MAX_CONCURRENCY = '2';
process.env.RENDER_MAX_CONCURRENT_EXTRACTIONS = '2';
await expect(loadConfig()).rejects.toThrow(/requires RENDER_MAX_CONCURRENCY=1/);
});
it('selects the explicit low-memory profile', async () => {
process.env.RENDER_RESOURCE_PROFILE = 'low-memory';
const config = await loadConfig();
expect(config.resourceProfile.name).toBe('low-memory');
expect(config.requireBeginFrame).toBe(false);
expect(config.producerWorkers).toBe(1);
});
});