const { test } = require("tap"); const fs = require("fs"); const path = require("path"); const EOL = require("os").EOL || "\n"; const log4js = require("../../lib/log4js"); function remove(filename) { try { fs.unlinkSync(filename); } catch (e) { // doesn't really matter if it failed } } test("log4js fileSyncAppender", batch => { batch.test("with default fileSyncAppender settings", t => { const testFile = path.join(__dirname, "/fa-default-sync-test.log"); const logger = log4js.getLogger("default-settings"); remove(testFile); t.teardown(() => { remove(testFile); }); log4js.configure({ appenders: { sync: { type: "fileSync", filename: testFile } }, categories: { default: { appenders: ["sync"], level: "debug" } } }); logger.info("This should be in the file."); fs.readFile(testFile, "utf8", (err, fileContents) => { t.match(fileContents, `This should be in the file.${EOL}`); t.match( fileContents, /\[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}] \[INFO] default-settings - / ); t.end(); }); }); batch.test("with a max file size and no backups", t => { const testFile = path.join(__dirname, "/fa-maxFileSize-sync-test.log"); const logger = log4js.getLogger("max-file-size"); remove(testFile); t.teardown(() => { remove(testFile); }); // log file of 100 bytes maximum, no backups log4js.configure({ appenders: { sync: { type: "fileSync", filename: testFile, maxLogSize: 100, backups: 0 } }, categories: { default: { appenders: ["sync"], level: "debug" } } }); logger.info("This is the first log message."); logger.info("This is an intermediate log message."); logger.info("This is the second log message."); t.test("log file should only contain the second message", assert => { fs.readFile(testFile, "utf8", (err, fileContents) => { assert.match(fileContents, `This is the second log message.${EOL}`); assert.equal( fileContents.indexOf("This is the first log message."), -1 ); assert.end(); }); }); t.test("there should be one test files", assert => { fs.readdir(__dirname, (err, files) => { const logFiles = files.filter(file => file.includes("fa-maxFileSize-sync-test.log") ); assert.equal(logFiles.length, 1); assert.end(); }); }); t.end(); }); batch.test("with a max file size in unit mode and no backups", t => { const testFile = path.join(__dirname, "/fa-maxFileSize-unit-sync-test.log"); const logger = log4js.getLogger("max-file-size-unit"); remove(testFile); remove(`${testFile}.1`); t.teardown(() => { remove(testFile); remove(`${testFile}.1`); }); // log file of 100 bytes maximum, no backups log4js.configure({ appenders: { sync: { type: "fileSync", filename: testFile, maxLogSize: "1K", backups: 0, layout: { type: "messagePassThrough" } } }, categories: { default: { appenders: ["sync"], level: "debug" } } }); const maxLine = 22; // 1024 max file size / 47 bytes per line for (let i = 0; i < maxLine; i++) { logger.info("These are the log messages for the first file."); // 46 bytes per line + '\n' } logger.info("This is the second log message."); t.test("log file should only contain the second message", assert => { fs.readFile(testFile, "utf8", (err, fileContents) => { assert.match(fileContents, `This is the second log message.${EOL}`); assert.notMatch(fileContents, "These are the log messages for the first file."); assert.end(); }); }); t.test("there should be one test file", assert => { fs.readdir(__dirname, (err, files) => { const logFiles = files.filter(file => file.includes("fa-maxFileSize-unit-sync-test.log") ); assert.equal(logFiles.length, 1); assert.end(); }); }); t.end(); }); batch.test("with a max file size and 2 backups", t => { const testFile = path.join( __dirname, "/fa-maxFileSize-with-backups-sync-test.log" ); const logger = log4js.getLogger("max-file-size-backups"); remove(testFile); remove(`${testFile}.1`); remove(`${testFile}.2`); t.teardown(() => { remove(testFile); remove(`${testFile}.1`); remove(`${testFile}.2`); }); // log file of 50 bytes maximum, 2 backups log4js.configure({ appenders: { sync: { type: "fileSync", filename: testFile, maxLogSize: 50, backups: 2 } }, categories: { default: { appenders: ["sync"], level: "debug" } } }); logger.info("This is the first log message."); logger.info("This is the second log message."); logger.info("This is the third log message."); logger.info("This is the fourth log message."); t.test("the log files", assert => { assert.plan(5); fs.readdir(__dirname, (err, files) => { const logFiles = files.filter(file => file.includes("fa-maxFileSize-with-backups-sync-test.log") ); assert.equal(logFiles.length, 3, "should be 3 files"); assert.same( logFiles, [ "fa-maxFileSize-with-backups-sync-test.log", "fa-maxFileSize-with-backups-sync-test.log.1", "fa-maxFileSize-with-backups-sync-test.log.2" ], "should be named in sequence" ); fs.readFile( path.join(__dirname, logFiles[0]), "utf8", (e, contents) => { assert.match(contents, "This is the fourth log message."); } ); fs.readFile( path.join(__dirname, logFiles[1]), "utf8", (e, contents) => { assert.match(contents, "This is the third log message."); } ); fs.readFile( path.join(__dirname, logFiles[2]), "utf8", (e, contents) => { assert.match(contents, "This is the second log message."); } ); }); }); t.end(); }); batch.test("configure with fileSyncAppender", t => { const testFile = "tmp-sync-tests.log"; remove(testFile); t.teardown(() => { remove(testFile); }); // this config defines one file appender (to ./tmp-sync-tests.log) // and sets the log level for "tests" to WARN log4js.configure({ appenders: { sync: { type: "fileSync", filename: testFile, layout: { type: "messagePassThrough" } } }, categories: { default: { appenders: ["sync"], level: "debug" }, tests: { appenders: ["sync"], level: "warn" } } }); const logger = log4js.getLogger("tests"); logger.info("this should not be written to the file"); logger.warn("this should be written to the file"); fs.readFile(testFile, "utf8", (err, contents) => { t.match(contents, `this should be written to the file${EOL}`); t.equal(contents.indexOf("this should not be written to the file"), -1); t.end(); }); }); batch.test("test options", t => { const testFile = "tmp-options-tests.log"; remove(testFile); t.teardown(() => { remove(testFile); }); // using non-standard options log4js.configure({ appenders: { sync: { type: "fileSync", filename: testFile, layout: { type: "messagePassThrough" }, flags: "w", encoding: "ascii", mode: 0o666 } }, categories: { default: { appenders: ["sync"], level: "info" } } }); const logger = log4js.getLogger(); logger.warn("log message"); fs.readFile(testFile, "ascii", (err, contents) => { t.match(contents, `log message${EOL}`); t.end(); }); }); batch.end(); });