57 lines
1.8 KiB
JavaScript
57 lines
1.8 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { rateLimit, semaphore } from "../server/limits.js";
|
|
|
|
test("Импорт: не больше двух разборов сразу, лишние ждут или получают 429", async () => {
|
|
const run = semaphore({ limit: 2, queue: 1, message: "Занято" });
|
|
let active = 0,
|
|
peak = 0;
|
|
const release = [];
|
|
const task = () =>
|
|
run(async () => {
|
|
peak = Math.max(peak, ++active);
|
|
await new Promise((resolve) => release.push(resolve));
|
|
active--;
|
|
});
|
|
const running = [task(), task(), task()];
|
|
await assert.rejects(task(), (e) => e.status === 429 && e.code === "busy" && e.message === "Занято");
|
|
// Each finished task hands its slot to the one waiting.
|
|
while (release.length) {
|
|
release.shift()();
|
|
await new Promise((resolve) => setImmediate(resolve));
|
|
}
|
|
await Promise.all(running);
|
|
assert.equal(peak, 2);
|
|
// All slots are free again.
|
|
assert.equal(await run(async () => "ok"), "ok");
|
|
});
|
|
|
|
test("Импорт: лимит запросов считается по адресу клиента", () => {
|
|
const limit = rateLimit({ max: 2, windowMs: 60_000, message: "Подождите" });
|
|
const call = (ip) => {
|
|
let status = 200,
|
|
body = null,
|
|
passed = false;
|
|
const res = {
|
|
set() {},
|
|
status(code) {
|
|
status = code;
|
|
return this;
|
|
},
|
|
json(value) {
|
|
body = value;
|
|
},
|
|
};
|
|
limit({ ip }, res, () => (passed = true));
|
|
return { status, body, passed };
|
|
};
|
|
assert.ok(call("10.0.0.1").passed);
|
|
assert.ok(call("10.0.0.1").passed);
|
|
assert.deepEqual(call("10.0.0.1"), {
|
|
status: 429,
|
|
body: { error: "Подождите", code: "too_many_requests" },
|
|
passed: false,
|
|
});
|
|
assert.ok(call("10.0.0.2").passed);
|
|
});
|