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

103 lines
5.3 KiB
JavaScript

import assert from 'node:assert/strict';
import {mkdtemp, readdir, readFile, rm, writeFile, stat} from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import {fileURLToPath} from 'node:url';
import test from 'node:test';
import {build} from 'esbuild';
const compiled = await build({
entryPoints: [fileURLToPath(new URL('../utils/logger.ts', import.meta.url))],
bundle: true,
platform: 'node',
format: 'esm',
write: false,
});
const {Logger} = await import(`data:text/javascript;base64,${Buffer.from(compiled.outputFiles[0].text).toString('base64')}`);
test('closing logger drains pending records, closes file and ignores late logs', async () => {
const directory = await mkdtemp(path.join(os.tmpdir(), 'node-bot-logger-'));
try {
const logger = new Logger(directory);
for (let i = 0; i < 20; i++) logger.log([logger.info(String(i))]);
const closed = logger.close();
assert.equal(logger.close(), closed);
logger.log([logger.info('late')]);
await closed;
const [name] = await readdir(directory);
const lines = (await readFile(path.join(directory, name), 'utf8')).trim().split('\n');
assert.deepEqual(lines.map(line => JSON.parse(line).log[0].message),
Array.from({length: 20}, (_, i) => String(i)));
} finally {
await rm(directory, {recursive: true, force: true});
}
});
test('disk history sorts dates and numeric rotations and skips malformed records', async () => {
const directory = await mkdtemp(path.join(os.tmpdir(), 'node-bot-history-'));
const record = id => ({id, timestamp: 1, log: [{message: id, font_color: '#ffffff', font_style: ['normal']}]});
try {
await Promise.all([
writeFile(path.join(directory, '2026-10-16_log_99.log'), JSON.stringify(record('older')) + '\n'),
writeFile(path.join(directory, '2026-10-17_log.log'), JSON.stringify(record('base')) + '\n'),
writeFile(path.join(directory, '2026-10-17_log_9.log'), JSON.stringify(record('nine')) + '\n'),
writeFile(path.join(directory, '2026-10-17_log_10.log'), [
JSON.stringify(record('ten')), 'broken json', 'null', '{}',
'{"id":"bad","timestamp":"1","log":[]}',
JSON.stringify(record('latest')),
].join('\n')),
writeFile(path.join(directory, 'unrelated.log'), JSON.stringify(record('ignored'))),
]);
assert.deepEqual((await Logger.read_recent_log(directory, 10)).map(item => item.id),
['older', 'base', 'nine', 'ten', 'latest']);
assert.deepEqual(await Logger.read_recent_log(directory, 2), [record('ten'), record('latest')]);
assert.deepEqual(await Logger.read_recent_log(directory, 0), []);
const missing = path.join(directory, 'missing');
assert.deepEqual(await Logger.read_recent_log(missing, 10), []);
await assert.rejects(stat(missing), {code: 'ENOENT'});
} finally {
await rm(directory, {recursive: true, force: true});
}
});
test('disk history handles chunk boundaries, oversized lines and a bounded read budget', async () => {
const directory = await mkdtemp(path.join(os.tmpdir(), 'node-bot-history-'));
const record = (id, message) => ({id, timestamp: 1, log: [{message, font_color: '#ffffff', font_style: ['normal']}]});
try {
const first = record('first', '中文'.repeat(25000));
const last = record('last', 'tail');
const filename = path.join(directory, '2026-10-17_log.log');
await writeFile(filename, [JSON.stringify(first), 'x'.repeat(1024 * 1024 + 1), JSON.stringify(last), ''].join('\n'));
assert.deepEqual(await Logger.read_recent_log(directory, 10), [first, last]);
await writeFile(filename, JSON.stringify(first) + '\n' + 'x'.repeat(17 * 1024 * 1024) + '\n' + JSON.stringify(last));
assert.deepEqual(await Logger.read_recent_log(directory, 10), [last]);
} finally {
await rm(directory, {recursive: true, force: true});
}
});
test('instance history includes immediate in-flight and queued records, deduplicates disk and survives close', async () => {
const directory = await mkdtemp(path.join(os.tmpdir(), 'node-bot-history-'));
const logger = new Logger(directory);
try {
for (let i = 0; i < 100; i++) logger.log([logger.info(String(i))]);
const immediate = logger.read_recent_log(100);
const recent = logger.read_recent_log(3);
const closed = logger.close();
const closing = logger.read_recent_log(100);
const records = await immediate;
assert.deepEqual(records.map(record => record.log[0].message),
Array.from({length: 100}, (_, i) => String(i)));
assert.equal(new Set(records.map(record => record.id)).size, 100);
assert.ok(records.every(record => typeof record.timestamp === 'number'));
assert.deepEqual((await recent).map(record => record.log[0].message), ['97', '98', '99']);
assert.deepEqual(await closing, records);
await closed;
assert.deepEqual(await Logger.read_recent_log(directory, 100), records);
assert.deepEqual(await logger.read_recent_log(100), records);
} finally {
await logger.close();
await rm(directory, {recursive: true, force: true});
}
});