mirror of
https://github.com/denoland/std.git
synced 2024-11-22 04:59:05 +00:00
342 lines
8.4 KiB
TypeScript
342 lines
8.4 KiB
TypeScript
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
import {
|
|
assert,
|
|
assertEquals,
|
|
assertNotEquals,
|
|
assertThrows,
|
|
} from "@std/assert";
|
|
import { LogLevels } from "./levels.ts";
|
|
import { RotatingFileHandler } from "./rotating_file_handler.ts";
|
|
import { LogRecord } from "./logger.ts";
|
|
import { existsSync } from "@std/fs/exists";
|
|
|
|
const LOG_FILE = "./rotating_file_handler_test_log.file";
|
|
|
|
Deno.test({
|
|
name:
|
|
"RotatingFileHandler wipes existing log file clean and removes others with mode 'w'",
|
|
async fn() {
|
|
Deno.writeFileSync(LOG_FILE, new TextEncoder().encode("hello world"));
|
|
Deno.writeFileSync(
|
|
LOG_FILE + ".1",
|
|
new TextEncoder().encode("hello world"),
|
|
);
|
|
Deno.writeFileSync(
|
|
LOG_FILE + ".2",
|
|
new TextEncoder().encode("hello world"),
|
|
);
|
|
Deno.writeFileSync(
|
|
LOG_FILE + ".3",
|
|
new TextEncoder().encode("hello world"),
|
|
);
|
|
|
|
const fileHandler = new RotatingFileHandler("WARN", {
|
|
filename: LOG_FILE,
|
|
maxBytes: 50,
|
|
maxBackupCount: 3,
|
|
mode: "w",
|
|
});
|
|
fileHandler.setup();
|
|
fileHandler.destroy();
|
|
|
|
assertEquals((await Deno.stat(LOG_FILE)).size, 0);
|
|
assert(!existsSync(LOG_FILE + ".1"));
|
|
assert(!existsSync(LOG_FILE + ".2"));
|
|
assert(!existsSync(LOG_FILE + ".3"));
|
|
|
|
Deno.removeSync(LOG_FILE);
|
|
},
|
|
});
|
|
|
|
Deno.test({
|
|
name:
|
|
"RotatingFileHandler throws if any log file already exists with mode 'x'",
|
|
fn() {
|
|
Deno.writeFileSync(
|
|
LOG_FILE + ".3",
|
|
new TextEncoder().encode("hello world"),
|
|
);
|
|
using fileHandler = new RotatingFileHandler("WARN", {
|
|
filename: LOG_FILE,
|
|
maxBytes: 50,
|
|
maxBackupCount: 3,
|
|
mode: "x",
|
|
});
|
|
assertThrows(
|
|
() => {
|
|
fileHandler.setup();
|
|
},
|
|
Deno.errors.AlreadyExists,
|
|
"Backup log file " + LOG_FILE + ".3 already exists",
|
|
);
|
|
|
|
Deno.removeSync(LOG_FILE + ".3");
|
|
Deno.removeSync(LOG_FILE);
|
|
},
|
|
});
|
|
|
|
Deno.test({
|
|
name: "RotatingFileHandler handles first rollover, monitor step by step",
|
|
async fn() {
|
|
using fileHandler = new RotatingFileHandler("WARN", {
|
|
filename: LOG_FILE,
|
|
maxBytes: 25,
|
|
maxBackupCount: 3,
|
|
mode: "w",
|
|
});
|
|
fileHandler.setup();
|
|
|
|
fileHandler.handle(
|
|
new LogRecord({
|
|
msg: "AAA",
|
|
args: [],
|
|
level: LogLevels.ERROR,
|
|
loggerName: "default",
|
|
}),
|
|
); // 'ERROR AAA\n' = 10 bytes
|
|
fileHandler.flush();
|
|
assertEquals((await Deno.stat(LOG_FILE)).size, 10);
|
|
fileHandler.handle(
|
|
new LogRecord({
|
|
msg: "AAA",
|
|
args: [],
|
|
level: LogLevels.ERROR,
|
|
loggerName: "default",
|
|
}),
|
|
);
|
|
fileHandler.flush();
|
|
assertEquals((await Deno.stat(LOG_FILE)).size, 20);
|
|
fileHandler.handle(
|
|
new LogRecord({
|
|
msg: "AAA",
|
|
args: [],
|
|
level: LogLevels.ERROR,
|
|
loggerName: "default",
|
|
}),
|
|
);
|
|
fileHandler.flush();
|
|
// Rollover occurred. Log file now has 1 record, rollover file has the original 2
|
|
assertEquals((await Deno.stat(LOG_FILE)).size, 10);
|
|
assertEquals((await Deno.stat(LOG_FILE + ".1")).size, 20);
|
|
|
|
Deno.removeSync(LOG_FILE);
|
|
Deno.removeSync(LOG_FILE + ".1");
|
|
},
|
|
});
|
|
|
|
Deno.test({
|
|
name: "RotatingFileHandler handles first rollover, check all at once",
|
|
async fn() {
|
|
const fileHandler = new RotatingFileHandler("WARN", {
|
|
filename: LOG_FILE,
|
|
maxBytes: 25,
|
|
maxBackupCount: 3,
|
|
mode: "w",
|
|
});
|
|
fileHandler.setup();
|
|
|
|
fileHandler.handle(
|
|
new LogRecord({
|
|
msg: "AAA",
|
|
args: [],
|
|
level: LogLevels.ERROR,
|
|
loggerName: "default",
|
|
}),
|
|
); // 'ERROR AAA\n' = 10 bytes
|
|
fileHandler.handle(
|
|
new LogRecord({
|
|
msg: "AAA",
|
|
args: [],
|
|
level: LogLevels.ERROR,
|
|
loggerName: "default",
|
|
}),
|
|
);
|
|
fileHandler.handle(
|
|
new LogRecord({
|
|
msg: "AAA",
|
|
args: [],
|
|
level: LogLevels.ERROR,
|
|
loggerName: "default",
|
|
}),
|
|
);
|
|
|
|
fileHandler.destroy();
|
|
|
|
assertEquals((await Deno.stat(LOG_FILE)).size, 10);
|
|
assertEquals((await Deno.stat(LOG_FILE + ".1")).size, 20);
|
|
|
|
Deno.removeSync(LOG_FILE);
|
|
Deno.removeSync(LOG_FILE + ".1");
|
|
},
|
|
});
|
|
|
|
Deno.test({
|
|
name: "RotatingFileHandler handles all backups rollover",
|
|
fn() {
|
|
Deno.writeFileSync(LOG_FILE, new TextEncoder().encode("original log file"));
|
|
Deno.writeFileSync(
|
|
LOG_FILE + ".1",
|
|
new TextEncoder().encode("original log.1 file"),
|
|
);
|
|
Deno.writeFileSync(
|
|
LOG_FILE + ".2",
|
|
new TextEncoder().encode("original log.2 file"),
|
|
);
|
|
Deno.writeFileSync(
|
|
LOG_FILE + ".3",
|
|
new TextEncoder().encode("original log.3 file"),
|
|
);
|
|
|
|
const fileHandler = new RotatingFileHandler("WARN", {
|
|
filename: LOG_FILE,
|
|
maxBytes: 2,
|
|
maxBackupCount: 3,
|
|
mode: "a",
|
|
});
|
|
fileHandler.setup();
|
|
fileHandler.handle(
|
|
new LogRecord({
|
|
msg: "AAA",
|
|
args: [],
|
|
level: LogLevels.ERROR,
|
|
loggerName: "default",
|
|
}),
|
|
); // 'ERROR AAA\n' = 10 bytes
|
|
fileHandler.destroy();
|
|
|
|
assertEquals(Deno.readTextFileSync(LOG_FILE), "ERROR AAA\n");
|
|
assertEquals(Deno.readTextFileSync(LOG_FILE + ".1"), "original log file");
|
|
assertEquals(Deno.readTextFileSync(LOG_FILE + ".2"), "original log.1 file");
|
|
assertEquals(Deno.readTextFileSync(LOG_FILE + ".3"), "original log.2 file");
|
|
assert(!existsSync(LOG_FILE + ".4"));
|
|
|
|
Deno.removeSync(LOG_FILE);
|
|
Deno.removeSync(LOG_FILE + ".1");
|
|
Deno.removeSync(LOG_FILE + ".2");
|
|
Deno.removeSync(LOG_FILE + ".3");
|
|
},
|
|
});
|
|
|
|
Deno.test({
|
|
name: "RotatingFileHandler handles maxBytes less than 1",
|
|
fn() {
|
|
assertThrows(
|
|
() => {
|
|
const fileHandler = new RotatingFileHandler("WARN", {
|
|
filename: LOG_FILE,
|
|
maxBytes: 0,
|
|
maxBackupCount: 3,
|
|
mode: "w",
|
|
});
|
|
fileHandler.setup();
|
|
},
|
|
Error,
|
|
'"maxBytes" must be >= 1: received 0',
|
|
);
|
|
},
|
|
});
|
|
|
|
Deno.test({
|
|
name: "RotatingFileHandler handles maxBackupCount less than 1",
|
|
fn() {
|
|
assertThrows(
|
|
() => {
|
|
const fileHandler = new RotatingFileHandler("WARN", {
|
|
filename: LOG_FILE,
|
|
maxBytes: 50,
|
|
maxBackupCount: 0,
|
|
mode: "w",
|
|
});
|
|
fileHandler.setup();
|
|
},
|
|
Error,
|
|
'"maxBackupCount" must be >= 1: received 0',
|
|
);
|
|
},
|
|
});
|
|
|
|
Deno.test({
|
|
name: "RotatingFileHandler rotates on byte length, not msg length",
|
|
async fn() {
|
|
const fileHandler = new RotatingFileHandler("WARN", {
|
|
filename: LOG_FILE,
|
|
maxBytes: 7,
|
|
maxBackupCount: 1,
|
|
mode: "w",
|
|
});
|
|
fileHandler.setup();
|
|
|
|
const msg = "。";
|
|
const msgLength = msg.length;
|
|
const msgByteLength = new TextEncoder().encode(msg).byteLength;
|
|
assertNotEquals(msgLength, msgByteLength);
|
|
assertEquals(msgLength, 1);
|
|
assertEquals(msgByteLength, 3);
|
|
|
|
fileHandler.log(msg); // logs 4 bytes (including '\n')
|
|
fileHandler.log(msg); // max bytes is 7, but this would be 8. Rollover.
|
|
|
|
fileHandler.destroy();
|
|
|
|
const fileSize1 = (await Deno.stat(LOG_FILE)).size;
|
|
const fileSize2 = (await Deno.stat(LOG_FILE + ".1")).size;
|
|
|
|
assertEquals(fileSize1, msgByteLength + 1);
|
|
assertEquals(fileSize2, msgByteLength + 1);
|
|
|
|
Deno.removeSync(LOG_FILE);
|
|
Deno.removeSync(LOG_FILE + ".1");
|
|
},
|
|
});
|
|
|
|
Deno.test({
|
|
name: "RotatingFileHandler handles strings larger than the buffer",
|
|
fn() {
|
|
const fileHandler = new RotatingFileHandler("WARN", {
|
|
filename: LOG_FILE,
|
|
mode: "w",
|
|
maxBytes: 4000000,
|
|
maxBackupCount: 10,
|
|
});
|
|
const logOverBufferLimit = "A".repeat(4096);
|
|
fileHandler.setup();
|
|
|
|
fileHandler.log(logOverBufferLimit);
|
|
fileHandler.destroy();
|
|
|
|
assertEquals(
|
|
Deno.readTextFileSync(LOG_FILE),
|
|
`${logOverBufferLimit}\n`,
|
|
);
|
|
|
|
Deno.removeSync(LOG_FILE);
|
|
},
|
|
});
|
|
|
|
Deno.test({
|
|
name: "RotatingFileHandler handles a mixture of string sizes",
|
|
fn() {
|
|
const fileHandler = new RotatingFileHandler("WARN", {
|
|
filename: LOG_FILE,
|
|
mode: "w",
|
|
maxBytes: 4000000,
|
|
maxBackupCount: 10,
|
|
});
|
|
const veryLargeLog = "A".repeat(10000);
|
|
const regularLog = "B".repeat(100);
|
|
fileHandler.setup();
|
|
|
|
fileHandler.log(regularLog);
|
|
fileHandler.log(veryLargeLog);
|
|
fileHandler.log(regularLog);
|
|
fileHandler.destroy();
|
|
|
|
assertEquals(
|
|
Deno.readTextFileSync(LOG_FILE),
|
|
`${regularLog}\n${veryLargeLog}\n${regularLog}\n`,
|
|
);
|
|
|
|
Deno.removeSync(LOG_FILE);
|
|
},
|
|
});
|