Skip to content
This repository has been archived by the owner on Apr 21, 2022. It is now read-only.

Commit

Permalink
package: Convert to tap for testing
Browse files Browse the repository at this point in the history
This moves to `tap` as the test framework, and increases coverage
to 100%

Semver: patch
Ref: LOG-6338
  • Loading branch information
darinspivey committed Jul 16, 2020
1 parent d8a65cd commit a2153f1
Show file tree
Hide file tree
Showing 13 changed files with 1,246 additions and 917 deletions.
21 changes: 21 additions & 0 deletions .taprc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
esm: false
ts: false
jsx: false
check-coverage: true
reporter: tap
jobs: 2
nyc-arg:
- --all=true
- --exclude=test/
coverage-report:
- text
- text-summary
- json
- html
files:
- test/**/*.js
branches: 98
lines: 100
functions: 100
statements: 100

6 changes: 3 additions & 3 deletions lib/configs.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ module.exports = {
, MAX_LINE_LENGTH: 32000
, MAX_INPUT_LENGTH: 80
, FLUSH_INTERVAL: 250
, FLUSH_BYTE_LIMIT: (process.env.test === 'test') ? 320000 : 5000000
, AGENT_SETTING: (process.env.test === 'test') ? {maxSockets: 20, keepAliveTimeout: 1000} : {maxSockets: 20, keepAliveTimeout: 60000}
, AGENT_PROTOCOL: (process.env.test === 'test') ? 'http' : 'https'
, FLUSH_BYTE_LIMIT: 5000000
, AGENT_SETTING: {maxSockets: 20, keepAliveTimeout: 60000}
, AGENT_PROTOCOL: 'https'
, LOGDNA_URL: 'https://logs.logdna.com/logs/ingest'
, HOSTNAME_CHECK: /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$/
, MAC_ADDR_CHECK: /^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$/
Expand Down
62 changes: 31 additions & 31 deletions lib/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ const validUrl = require('valid-url')

// Configuration
const configs = require('./configs')

const TAGS_RE = /\s*,\s*/
// Variables
let loggers = []

const isInt = value => !isNaN(value) && ((parseFloat(value) | 0) === parseFloat(value))

const checkStringParam = (param, name, optional) => {
if (optional && !param) return
if (!param || typeof param !== 'string') {
Expand All @@ -44,10 +42,11 @@ const isValidTimestamp = (timestamp) => {
return true
}

function Logger(key, options) {
function Logger(key, opts) {
if (!(this instanceof Logger)) {
return new Logger(key, options)
return new Logger(key, opts)
}
const options = opts || {}

checkStringParam(key, 'LogDNA Ingestion Key', false)
checkStringParam(options.hostname, 'Hostname', true)
Expand All @@ -57,13 +56,13 @@ function Logger(key, options) {
checkStringParam(options.app, 'App', true)
checkStringParam(options.logdna_url, 'LogDNA URL', true)

if (options.tags) {
if (typeof options.tags === 'string') {
options.tags = options.tags.split(',')
let tags = options.tags
if (tags) {
if (typeof tags === 'string') {
tags = tags.split(TAGS_RE)
}

if (Array.isArray(options.tags)) {
options.tags = options.tags
if (Array.isArray(tags)) {
tags = tags
.filter(tag => tag !== '')
.map(tag => tag.trim())
.join(',')
Expand All @@ -73,7 +72,7 @@ function Logger(key, options) {
}

if (options.timeout) {
if (!isInt(options.timeout)) {
if (!Number.isInteger(options.timeout)) {
throw new Error('Timeout must be an Integer')
}
if (options.timeout > configs.MAX_REQUEST_TIMEOUT) {
Expand Down Expand Up @@ -140,16 +139,19 @@ function Logger(key, options) {
this._meta = {}
this._isLoggingBackedOff = false
this._attempts = 0
this.__dbgLines = null
this.__bufSizePreserve = null
this.callback = null

this.source = {
hostname: options.hostname || os.hostname()
, app: options.app || 'default'
, level: options.level || 'INFO'
, env: options.env || undefined
, tags: options.tags || undefined
, tags: tags || undefined
}

const useHttps = configs.AGENT_PROTOCOL === 'https'
const useHttps = (options.protocol || configs.AGENT_PROTOCOL) === 'https'

this._req = {
auth: {username: key}
Expand Down Expand Up @@ -199,8 +201,10 @@ Logger.prototype.log = function(statement, opts, callback) {
message.level = opts
} else {
if (typeof opts !== 'object') {
this._err = true
debug('Can only pass a String or JSON object as additional parameter')
const err = new TypeError('options parameter must be a level (string), or object')
err.meta = {opts}
this._err = err
debug(err.message)
}

message.level = opts.level || message.level
Expand Down Expand Up @@ -249,22 +253,22 @@ Logger.prototype.log = function(statement, opts, callback) {
}

if (this._err) {
return this._err
return callback(this._err)
}

this._bufferLog(message, callback)
}

Logger.prototype._bufferLog = function(message, callback) {
if (!message || !message.line) {
debug('Ignoring empty message')
return
}

if (!callback || typeof callback !== 'function') {
callback = (err) => { debug(err) }
}

if (!message || !message.line) {
debug('Ignoring empty message')
return setImmediate(callback)
}

if (this._max_length && message.line.length > configs.MAX_LINE_LENGTH) {
message.line = message.line.substring(0, configs.MAX_LINE_LENGTH) + ' (cut off, too long...)'
debug('Line was longer than ' + configs.MAX_LINE_LENGTH + ' chars and was truncated.')
Expand All @@ -282,11 +286,8 @@ Logger.prototype._bufferLog = function(message, callback) {

if (!this._isLoggingBackedOff && (this._bufByteLength >= this._flushLimit)) {
debug('Buffer size meets (or exceeds) flush limit. Immediately flushing')
this._flush((err) => {
if (err) {
debug('Received an error while flushing...' + err)
}
})
this._flush(callback)
return
}

if (this._isLoggingBackedOff) {
Expand Down Expand Up @@ -421,7 +422,6 @@ const flushAll = function(cb) {
return cb(`The following errors happened while flushing all loggers: ${errors}`)
}
return cb()

}

const errors = []
Expand All @@ -434,9 +434,9 @@ const flushAll = function(cb) {
if (++counter === loggersCount) {

/*
* Flushed all the loggers
* Completes by calling the callback
*/
* Flushed all the loggers
* Completes by calling the callback
*/
complete(errors)
}
})
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
},
"scripts": {
"lint": "eslint .",
"test": "nyc --reporter=html --reporter=text mocha"
"pretest": "npm run lint",
"test": "tap"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -68,6 +69,8 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-sensible": "^2.2.0",
"mocha": "^5.2.0",
"nyc": "^14.1.1"
"nock": "^13.0.2",
"nyc": "^14.1.1",
"tap": "^14.10.7"
}
}
45 changes: 45 additions & 0 deletions test/common/create-options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict'

module.exports = function createOptions({
key = '< YOUR INGESTION KEY HERE >'
, hostname = 'AWESOMEHOSTER'
, ip = '10.0.1.101'
, mac = 'C0:FF:EE:C0:FF:EE'
, app = 'testing.log'
, test = true
, port = 1337
, failedBufRetentionLimit = null
, retryTimes = null
, retryTimeout = null
, flushInterval = 1 // Immediate flushing should be the default
, flushLimit = null
, max_length = null
, index_meta = null
, level = null
, tags = null
, protocol = null
, timeout = null
, shimProperties
} = {}) {
return {
key
, hostname
, ip
, mac
, app
, test
, logdna_url: `http://localhost:${port}`
, failedBufRetentionLimit
, retryTimeout
, flushInterval
, flushLimit
, max_length
, index_meta
, level
, retryTimes
, tags
, protocol
, timeout
, shimProperties
}
}
6 changes: 6 additions & 0 deletions test/common/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use strict'

module.exports = {
apiKey: '< YOUR INGESTION KEY HERE >'
, createOptions: require('./create-options.js')
}
41 changes: 41 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict'

const {test} = require('tap')
const index = require('../index.js')
const logger = require('../lib/logger.js')
const {apiKey, createOptions} = require('./common/index.js')

test('Index exports are correct', async (t) => {
t.equal(Object.keys(index).length, 5, 'property count is correct')
t.match(index, {
cleanUpAll: logger.cleanUpAll
, createLogger: logger.createLogger
, flushAll: logger.flushAll
, Logger: logger.Logger
, setupDefaultLogger: Function
}, 'Exported properties are correct')
})

test('setupDefaultLogger', async (t) => {
t.test('Create the singleton', async (tt) => {
const instance = index.setupDefaultLogger(
apiKey
, createOptions({
app: 'MyDefaultApp'
})
)
tt.equal(instance.constructor.name, 'Logger', 'Returned an instance')
tt.equal(instance.source.app, 'MyDefaultApp', 'App name is correct')
})

t.test('Singleton is returned', async (tt) => {
const instance = index.setupDefaultLogger(
apiKey
, createOptions({
app: 'ThisWillNotWork'
})
)
tt.equal(instance.constructor.name, 'Logger', 'Returned an instance')
tt.equal(instance.source.app, 'MyDefaultApp', 'App name is correct')
})
})
Loading

0 comments on commit a2153f1

Please sign in to comment.