Files
node_server/tests/main_server_reconnect.test.mjs
2026-10-22 17:07:08 +08:00

76 lines
2.9 KiB
JavaScript

import assert from 'node:assert/strict';
import {readFile} from 'node:fs/promises';
import vm from 'node:vm';
import test from 'node:test';
import {transformSync} from 'esbuild';
const source = await readFile(new URL('../index.ts', import.meta.url), 'utf8');
const lifecycle = source.slice(source.indexOf(' let reconnect_timer:'), source.indexOf(" main_server_socket.on('connect',"));
const disconnect = source.slice(source.indexOf(" main_server_socket.on('disconnect',"), source.indexOf(' main_server_socket.onAny('));
const code = transformSync(`${lifecycle}\n${disconnect}`, {loader: 'ts'}).code;
function setup(enabled = true, max_attempts = 2) {
const timers = new Map();
const handlers = new Map();
const state = {connects: 0, disconnects: 0};
const process = {once() {}};
let id = 0;
vm.runInNewContext(code, {
auto_reconnect: {enabled, max_attempts, interval: 100},
reconnect_interval: 100,
main_server_socket: {
on: (event, handler) => handlers.set(event, handler),
connect: () => state.connects++,
disconnect: () => state.disconnects++,
},
console_print: {log() {}, info() {}, error() {}, warning() {}},
clear_node_session() {},
get_bot_context_status: async () => [],
stop_bot_context: async () => {},
process,
setTimeout(callback, delay) {
if (delay === 10_000) return ++id;
assert.equal(delay, 100);
timers.set(++id, callback);
return id;
},
clearTimeout: id => timers.delete(id),
});
return {
state, process, timers,
disconnect: reason => handlers.get('disconnect')(reason),
tick() {
assert.equal(timers.size, 1);
const [id, callback] = timers.entries().next().value;
timers.delete(id);
callback();
},
};
}
test('server disconnect retries indefinitely without duplicate timers after the configured limit', () => {
const app = setup();
for (let attempt = 0; attempt < 12; attempt++) {
app.disconnect('io server disconnect');
app.disconnect('io server disconnect');
app.tick();
assert.equal(app.state.connects, attempt + 1);
}
app.disconnect('io server disconnect');
assert.equal(app.state.disconnects, 0);
assert.equal(app.timers.size, 1);
assert.equal(app.process.exitCode, undefined);
});
test('disabled reconnect and a zero attempt limit still retry every disconnect reason', () => {
const app = setup(false, 0);
for (const reason of ['io server disconnect', 'io client disconnect', 'transport close', 'ping timeout', 'transport error']) {
app.disconnect(reason);
app.tick();
}
assert.equal(app.state.connects, 5);
app.disconnect('io client disconnect');
assert.equal(app.timers.size, 1);
assert.equal(app.process.exitCode, undefined);
});