mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
test: cover render concurrency limit and winner picker
This commit is contained in:
1 parent
8fece5fd7f
commit
a6c65768f5
2 files changed
+64
No files matched your search
@@ -89,6 +89,47 @@ describe('POST /api/gif', () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
test('rejects concurrent renders beyond the limit and frees the slot afterward', async () => {
|
||||
/** @type {(value?: void) => void} */
|
||||
let releaseRender = () => {};
|
||||
/** @type {(value?: void) => void} */
|
||||
let markRenderStarted = () => {};
|
||||
const renderStarted = new Promise((resolve) => {
|
||||
markRenderStarted = resolve;
|
||||
});
|
||||
const renderGate = new Promise((resolve) => {
|
||||
releaseRender = resolve;
|
||||
});
|
||||
|
||||
const app = await buildServer({
|
||||
config,
|
||||
renderGif: async () => {
|
||||
markRenderStarted();
|
||||
await renderGate;
|
||||
return {buffer: Buffer.from('GIF89a-test'), byteLength: 11, durationMs: 1};
|
||||
},
|
||||
});
|
||||
|
||||
const payload = {options: ['alpha', 'beta'], winnerIndex: 0};
|
||||
const first = app.inject({method: 'POST', url: '/api/gif', payload});
|
||||
// The route acquires the semaphore before calling renderGif, so once the
|
||||
// render body runs the single slot is held.
|
||||
await renderStarted;
|
||||
|
||||
const rejected = await app.inject({method: 'POST', url: '/api/gif', payload});
|
||||
expect(rejected.statusCode).toBe(429);
|
||||
expect(rejected.json().error).toBe('too_many_renders');
|
||||
|
||||
releaseRender();
|
||||
expect((await first).statusCode).toBe(200);
|
||||
|
||||
// The slot released in `finally` must let a later request through.
|
||||
const afterRelease = await app.inject({method: 'POST', url: '/api/gif', payload});
|
||||
expect(afterRelease.statusCode).toBe(200);
|
||||
|
||||
await app.close();
|
||||
});
|
||||
|
||||
test('returns timeout response when rendering exceeds configured limit', async () => {
|
||||
const app = await buildServer({
|
||||
config: {...config, renderTimeoutMs: 7},
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import {describe, expect, test} from 'vitest';
|
||||
import {pickWinnerIndex} from '../src/lib/winner.js';
|
||||
|
||||
describe('pickWinnerIndex', () => {
|
||||
test('returns an index within range across many draws', () => {
|
||||
for (let i = 0; i < 100; i += 1) {
|
||||
const index = pickWinnerIndex(4);
|
||||
expect(Number.isInteger(index)).toBe(true);
|
||||
expect(index).toBeGreaterThanOrEqual(0);
|
||||
expect(index).toBeLessThan(4);
|
||||
}
|
||||
});
|
||||
|
||||
test('always returns 0 for a single option', () => {
|
||||
expect(pickWinnerIndex(1)).toBe(0);
|
||||
});
|
||||
|
||||
test('throws RangeError for non-positive or non-integer counts', () => {
|
||||
expect(() => pickWinnerIndex(0)).toThrow(RangeError);
|
||||
expect(() => pickWinnerIndex(-3)).toThrow(RangeError);
|
||||
expect(() => pickWinnerIndex(2.5)).toThrow(RangeError);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user