service-core/test/log.test.mjs

295 lines
9.8 KiB
JavaScript

import { Eltro as t, assert, stub } from 'eltro'
import fs from 'fs/promises'
import getLog from '../core/log.mjs'
t.describe('#constructor', function() {
t.afterEach(function() {
process.env.NODE_ENV = null
})
t.after(function() {
return Promise.all([
fs.rm('./log.log', { recursive: true, force: true }),
])
})
t.test('should add name', function() {
const assertName = 'Stray Cat'
let logger = getLog(assertName)
assert.strictEqual(logger.fields.name, assertName)
process.env.NODE_ENV = 'production'
logger = getLog(assertName)
assert.strictEqual(logger.fields.name, assertName)
})
t.test('should add default stdout streams in normal environment', function() {
let logger = getLog('app', null)
assert.strictEqual(logger.streams.length, 4)
assert.strictEqual(logger.streams[0].stream, process.stdout)
assert.strictEqual(logger.streams[0].level, 20)
})
t.test('should add default file log stream in production environment', function() {
process.env.NODE_ENV = 'production'
let logger = getLog('app', null)
assert.strictEqual(logger.streams.length, 4)
assert.strictEqual(logger.streams[0].path, 'log.log')
assert.strictEqual(logger.streams[0].level, 30)
})
t.test('should not add default stream if empty array', function() {
let logger = getLog('app', [])
assert.strictEqual(logger.streams.length, 3)
process.env.NODE_ENV = 'production'
logger = getLog('app', [])
assert.strictEqual(logger.streams.length, 3)
})
t.test('should replace process.stdout with actual process', function() {
let logger = getLog('app', [{ stream: 'process.stdout', level: 'info' }])
assert.strictEqual(logger.streams.length, 4)
assert.strictEqual(logger.streams[0].stream, process.stdout)
process.env.NODE_ENV = 'production'
logger = getLog('app', [{ stream: 'process.stdout', level: 'info' }])
assert.strictEqual(logger.streams.length, 4)
assert.strictEqual(logger.streams[0].stream, process.stdout)
})
})
t.describe('ringbuffer', function() {
let logger
t.beforeEach(function() {
logger = getLog('app', [])
})
t.test('should have ringbuffer for info', function() {
const assertMessage = 'Oitachi'
assert.strictEqual(logger.ringbuffer.records.length, 0)
logger.info(assertMessage)
assert.strictEqual(logger.ringbuffer.records.length, 1)
assert.strictEqual(logger.ringbuffer.records[0].level, 30)
assert.strictEqual(logger.ringbuffer.records[0].msg, assertMessage)
logger.debug(assertMessage)
assert.strictEqual(logger.ringbuffer.records.length, 1)
logger.warn(assertMessage)
assert.strictEqual(logger.ringbuffer.records.length, 2)
assert.strictEqual(logger.ringbuffer.records[1].level, 40)
assert.strictEqual(logger.ringbuffer.records[1].msg, assertMessage)
})
t.test('should keep it limited to max 100 records', function() {
const assertPrefix = 'In memory of Keiten'
for (let i = 1; i <= 101; i++) {
logger.info(assertPrefix + i)
}
assert.strictEqual(logger.ringbuffer.records.length, 100)
assert.strictEqual(logger.ringbuffer.records[0].msg, assertPrefix + '2')
logger.info(assertPrefix)
assert.strictEqual(logger.ringbuffer.records.length, 100)
assert.strictEqual(logger.ringbuffer.records[0].msg, assertPrefix + '3')
})
})
t.describe('ringbufferwarn', function() {
let logger
t.beforeEach(function() {
logger = getLog('app', [])
})
t.test('should have ringbufferwarn for info', function() {
const assertMessage = 'Oitachi'
assert.strictEqual(logger.ringbufferwarn.records.length, 0)
logger.warn(assertMessage)
assert.strictEqual(logger.ringbufferwarn.records.length, 1)
assert.strictEqual(logger.ringbufferwarn.records[0].level, 40)
assert.strictEqual(logger.ringbufferwarn.records[0].msg, assertMessage)
logger.info(assertMessage)
assert.strictEqual(logger.ringbufferwarn.records.length, 1)
logger.error(assertMessage)
assert.strictEqual(logger.ringbufferwarn.records.length, 2)
assert.strictEqual(logger.ringbufferwarn.records[1].level, 50)
assert.strictEqual(logger.ringbufferwarn.records[1].msg, assertMessage)
})
t.test('should keep it limited to max 100 records', function() {
const assertPrefix = 'In memory of Keiten'
for (let i = 1; i <= 101; i++) {
logger.warn(assertPrefix + i)
}
assert.strictEqual(logger.ringbufferwarn.records.length, 100)
assert.strictEqual(logger.ringbufferwarn.records[0].msg, assertPrefix + '2')
logger.warn(assertPrefix)
assert.strictEqual(logger.ringbufferwarn.records.length, 100)
assert.strictEqual(logger.ringbufferwarn.records[0].msg, assertPrefix + '3')
})
})
t.describe('event', function() {
t.test('should call import if not in production', async function() {
let stubImport = stub()
stubImport.rejects(new Error('should not be seen'))
let logger = getLog('app', [], { import: stubImport })
let first = new Promise(function(res, rej) {
setImmediate(function() { logger.event.warn('text message here').then(res, rej) })
})
let second = new Promise(function(res, rej) {
setImmediate(function() { logger.event.warn('new message here').then(res, rej) })
})
await Promise.all([
first, second,
])
assert.notOk(stubImport.called)
})
t.test('should call import correctly if in production and fail only once', async function() {
process.env.NODE_ENV = 'production'
let stubImport = stub()
stubImport.rejects(new Error('should not be seen'))
let logger = getLog('app', [], { import: stubImport })
let first = new Promise(function(res, rej) {
setImmediate(function() { try { logger.event.warn('first').then(res, rej) } catch (err) { rej(err) } })
})
let second = new Promise(function(res, rej) {
setImmediate(function() { try { logger.event.warn('second').then(res, rej) } catch (err) { rej(err) } })
})
await Promise.all([
first, second,
])
assert.ok(stubImport.called)
assert.strictEqual(stubImport.callCount, 1)
assert.strictEqual(stubImport.firstCall[0], 'node-windows')
await new Promise(function(res, rej) {
setImmediate(function() { try { logger.event.warn('third').then(res, rej) } catch (err) { rej(err) } })
})
})
t.test('should call event on imported object correctly', async function() {
const assertName = 'It is going to be The Special'
let checkName = ''
let stubInfo = stub().returnWith(function(msg, code, cb) { setTimeout(cb, 20) })
let stubWarn = stub().returnWith(function(msg, code, cb) { setTimeout(cb, 20) })
let stubError = stub().returnWith(function(msg, code, cb) { setTimeout(cb, 20) })
process.env.NODE_ENV = 'production'
let stubImport = stub().resolves({
default: {
EventLogger: function(name) {
checkName = name
this.info = stubInfo
this.warn = stubWarn
this.error = stubError
},
},
})
let logger = getLog(assertName, [], { import: stubImport })
let first = new Promise(function(res, rej) {
setImmediate(function() { try { logger.event.info('first', 1010).then(res, rej) } catch (err) { rej(err) } })
})
let second = new Promise(function(res, rej) {
setImmediate(function() { try { logger.event.warn('second', 1020).then(res, rej) } catch (err) { rej(err) } })
})
await Promise.all([
first, second,
])
assert.strictEqual(checkName, assertName)
assert.ok(stubInfo.called)
assert.strictEqual(stubInfo.firstCall[0], 'first')
assert.strictEqual(stubInfo.firstCall[1], 1010)
assert.ok(stubWarn.called)
assert.strictEqual(stubWarn.firstCall[0], 'second')
assert.strictEqual(stubWarn.firstCall[1], 1020)
assert.notOk(stubError.called)
await new Promise(function(res, rej) {
setImmediate(function() { try { logger.event.error('third', 1030).then(res, rej) } catch (err) { rej(err) } })
})
assert.ok(stubError.called)
assert.strictEqual(stubError.firstCall[0], 'third')
assert.strictEqual(stubError.firstCall[1], 1030)
})
t.test('should work even if it were to throw', async function() {
const assertName = 'It is going to be The Special'
let checkName = ''
let stubInfo = stub().returnWith(function() { throw new Error('not to be seen') })
let stubWarn = stub().returnWith(function() { throw new Error('not to be seen') })
let stubError = stub().returnWith(function() { throw new Error('not to be seen') })
process.env.NODE_ENV = 'production'
let stubImport = stub().resolves({
default: {
EventLogger: function(name) {
checkName = name
this.info = stubInfo
this.warn = stubWarn
this.error = stubError
},
},
})
let logger = getLog(assertName, [], { import: stubImport })
let first = new Promise(function(res, rej) {
setImmediate(function() { try { logger.event.info().then(res, rej) } catch (err) { rej(err) } })
})
let second = new Promise(function(res, rej) {
setImmediate(function() { try { logger.event.warn().then(res, rej) } catch (err) { rej(err) } })
})
await Promise.all([
first, second,
])
assert.strictEqual(checkName, assertName)
assert.ok(stubInfo.called)
assert.ok(stubWarn.called)
assert.notOk(stubError.called)
await new Promise(function(res, rej) {
setImmediate(function() { try { logger.event.error().then(res, rej) } catch (err) { rej(err) } })
})
assert.ok(stubError.called)
})
t.test('should work without stub', async function() {
let res = await import('node-windows').catch(function() {})
if (!res) { return }
process.env.NODE_ENV = 'production'
let logger = getLog('service-core-unit-test', [])
await logger.event.info('Hello from service-core log.event unit test')
})
})