@stdlib/bench-harness
Version:
Benchmark harness.
190 lines (166 loc) • 3.44 kB
JavaScript
/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable no-underscore-dangle */
'use strict';
// MODULES //
var TransformStream = require( '@stdlib/streams-node-transform' );
var isString = require( '@stdlib/assert-is-string' ).isPrimitive;
var nextTick = require( './../utils/next_tick.js' );
// VARIABLES //
var TAP_HEADER = 'TAP version 13';
// MAIN //
/**
* Creates a results stream.
*
* @private
* @param {Options} [options] - stream options
* @throws {TypeError} options argument must be an object
* @throws {TypeError} must provide valid options
* @returns {TransformStream} transform stream
*/
function createStream( options ) {
/* eslint-disable no-invalid-this */
var stream;
var opts;
var self;
var id;
self = this;
if ( arguments.length ) {
opts = options;
} else {
opts = {};
}
stream = new TransformStream( opts );
if ( opts.objectMode ) {
id = 0;
this.on( '_push', onPush );
this.on( 'done', onDone );
} else {
stream.write( TAP_HEADER+'\n' );
this._stream.pipe( stream );
}
this.on( '_run', onRun );
return stream;
/**
* Runs the next benchmark.
*
* @private
*/
function next() {
nextTick( onTick );
}
/**
* Callback invoked upon the next tick.
*
* @private
* @returns {void}
*/
function onTick() {
var b = self._benchmarks.shift();
if ( b ) {
b.run();
if ( !b.ended() ) {
return b.once( 'end', next );
}
return next();
}
self._running = false;
self.emit( 'done' );
}
/**
* Callback invoked upon a run event.
*
* @private
* @returns {void}
*/
function onRun() {
if ( !self._running ) {
self._running = true;
return next();
}
}
/**
* Callback invoked upon a push event.
*
* @private
* @param {Benchmark} b - benchmark
*/
function onPush( b ) {
var bid = id;
id += 1;
b.once( 'prerun', onPreRun );
b.on( 'result', onResult );
b.on( 'end', onEnd );
/**
* Callback invoked upon a `prerun` event.
*
* @private
*/
function onPreRun() {
var row = {
'type': 'benchmark',
'name': b.name,
'id': bid
};
stream.write( row );
}
/**
* Callback invoked upon a `result` event.
*
* @private
* @param {(Object|string)} res - result
*/
function onResult( res ) {
if ( isString( res ) ) {
res = {
'benchmark': bid,
'type': 'comment',
'name': res
};
} else if ( res.operator === 'result' ) {
res.benchmark = bid;
res.type = 'result';
} else {
res.benchmark = bid;
res.type = 'assert';
}
stream.write( res );
}
/**
* Callback invoked upon an `end` event.
*
* @private
*/
function onEnd() {
stream.write({
'benchmark': bid,
'type': 'end'
});
}
}
/**
* Callback invoked upon a `done` event.
*
* @private
*/
function onDone() {
stream.destroy();
}
}
// EXPORTS //
module.exports = createStream;