const getReporters = require('./getReporters.js');
const gc = require('./gc.js');
/**
* @module pete/lib/runnerQueue
*/
module.exports = enqueue;
/**
* @private
*/
var queueHead = null;
/**
* @private
*/
var queueTail = null;
/**
* @private
*/
var queueExit = false;
/**
* Add runner function to queue.
* Start specified run on `nextTick` if this is the first test added.
*
* @alias module:pete/lib/runnerQueue
* @param {module:pete/lib/runner~startRun} run
* @param {object} options
* @param {string} mode
* @param {Function} [report]
*/
function enqueue (run, options, mode, report) {
var r = {
run,
options,
mode,
report: report || dummyReport,
next : null
};
r.report = wrapReport(r);
if (queueTail) {
queueTail.next = r;
}
queueTail = r;
if (!queueHead) {
queueHead = r;
queueExit = false;
process.nextTick(next);
}
}
/**
* Dummy report function used when no real function was passed to `enqueue`.
*
* @private
*/
function dummyReport () {
/* Nothing to do here */
}
/**
* Shift queue linked list by one item.
* Start run if there was item available.
*
* @private
*/
function next () {
var r = queueHead;
queueHead = r && r.next;
if (!r || queueExit) {
queueHead = null;
queueTail = null;
queueExit = false;
// Close all reporters
getReporters(null, {close: true});
return;
}
r.run(r.mode, r.report);
}
/**
* Wrap `report` function, so when it's called wthout args (marking "end of report"),
* we can ignore that, so next run can continue reporting.
*
* @private
* @param {object} r
* @return {module:pete/lib/getReporters~report}
*/
function wrapReport (r) {
var report = r.report;
return function wrappedReport (err, data) {
if (!r) {
return;
}
if (err && r.options.exitOnError && (!data || data.exitOnError)) {
queueExit = true;
}
if (err || data) {
report(err, data);
return;
}
process.nextTick(next);
if (r.next && r.next.run !== r.run) {
gc(true);
}
r = null;
report = null;
};
}