diff --git a/examples/index.js b/examples/index.js index f257742..3533de9 100644 --- a/examples/index.js +++ b/examples/index.js @@ -50,7 +50,7 @@ */ // Check if a metric exists: - console.log( metrics.exists( 'mem.utilization' ) ); + console.log( metrics.exists( 'mem.swapspaceutilization' ) ); /** * Returns: @@ -65,7 +65,28 @@ */ // Get a metric specification: - console.log( metrics.get( 'mem.utilization' ) ); + console.log( metrics.get( 'mem.swapspaceutilization' ) ); + + /** + * Returns: + * [object] + */ + + // Get the list of devices: + console.log( metrics.listDevices() ); + + /** + * Returns: + * [ + * 'device0', + * 'device1', + * ... + * 'deviceN' + * ] + */ + + // Get a list of metric specifications by device name: + console.log( metrics.getDevice( 'DISK' ) ); /** * Returns: diff --git a/lib/index.js b/lib/index.js index e01086b..9a89016 100644 --- a/lib/index.js +++ b/lib/index.js @@ -29,19 +29,57 @@ (function() { 'use strict'; - // MODULES // - - var os = require( 'os' ); - - // SPECIFICATIONS // var METRICS = require( './../specs/memory.json' ); + // DEVICES // + + var DEVICES = {}; + var metricName, + devices, + i; + + /** Iterates through METRICS and creates DEVICES with the following structure: + *{ + * deviceName1: { + * metricNameA: {}, + * metricNameB: {}, + * ... + * }, + * deviceName2: { + * metricNameH: {}, + * metricNameI: {}, + * ... + * }, + * ... + *} + */ + for ( metricName in METRICS ) { + devices = METRICS[ metricName ][ 'device' ]; + if ( devices !== null ) { + for ( i = 0; i < devices.length; i++ ) { + DEVICES[ devices[i] ] = ( DEVICES[ devices[i] ] ? DEVICES[ devices[i] ] : {} ); + DEVICES[ devices[i] ][ metricName ] = METRICS[ metricName ]; + } + } + } + + // VARIABLES // - var NAMES = Object.keys( METRICS ); + var NAMES = Object.keys( METRICS ), + DEVICENAMES = Object.keys( DEVICES ); + var NAMESLOWER = NAMES.slice(), + DEVICENAMESLOWER = DEVICENAMES.slice(); + + for ( i = 0; i < NAMESLOWER.length; i++ ) { + NAMESLOWER[i] = NAMESLOWER[i].toLowerCase(); + } + for ( i = 0; i < DEVICENAMESLOWER.length; i++ ) { + DEVICENAMESLOWER[i] = DEVICENAMESLOWER[i].toLowerCase(); + } // METRICS // @@ -78,7 +116,7 @@ if ( typeof name !== 'string' ) { throw new TypeError( 'exists()::invalid input argument. Metric `name` must be a string.' ); } - if ( NAMES.indexOf( name ) === -1 ) { + if ( NAMESLOWER.indexOf( name.toLowerCase() ) === -1 ) { return false; } return true; @@ -86,38 +124,57 @@ /** * METHOD: get( name ) - * Returns a metric's specification. If a metric does not have a specification, returns null. + * Returns a metric's specification. If a metric does not have a specification, returns null. If invoked with null for metric name, returns all metric specifications. * * @param {String} name - metric name - * @returns {Object|null} metric specification or null + * @returns {Object|null} one or all metric specification(s), or null */ Metrics.prototype.get = function( name ) { + var indexOfName; + if ( arguments.length === 0 ) { + return JSON.parse( JSON.stringify( METRICS ) ); + } if ( typeof name !== 'string' ) { throw new TypeError( 'get()::invalid input argument. Metric `name` must be a string.' ); } - if ( NAMES.indexOf( name ) === -1 ) { + indexOfName = NAMESLOWER.indexOf( name.toLowerCase() ); + if ( indexOfName === -1 ) { return null; } - return JSON.parse( JSON.stringify( METRICS[ name ] ) ); + return JSON.parse( JSON.stringify( METRICS[ NAMES[ indexOfName ] ] ) ); }; // end METHOD get() /** - * METHOD: source( name ) - * Returns a metric's name. The source depends on the OS. Check the relevant specification for the return value and its use. If no source is found, returns null. + * METHOD: listDevices() + * Lists all devices associated with these metrics. * - * @param {String} name - metric name - * @returns {String|null} metric source or null + * @returns {Array} list of device names. */ - Metrics.prototype.source = function( name ) { - var spec; + Metrics.prototype.listDevices = function() { + return DEVICENAMES; + }; // end METHOD listDevices() + + /** + * METHOD: device( name ) + * Returns a list of metric specifications associated with the device. If a device does not have any associated metric specifications, returns null. If invoked with null for device name, returns all devices and their corresponding metric specifications. + * + * @param {String} name - device name + * @returns {Object|null} list of metric specifications, or list of devices, or null + */ + Metrics.prototype.device = function( name ) { + var indexOfName; + if ( arguments.length === 0 ) { + return JSON.parse( JSON.stringify( DEVICES ) ); + } if ( typeof name !== 'string' ) { - throw new TypeError( 'source()::invalid input argument. Metric `name` must be a string.' ); + throw new TypeError( 'device()::invalid input argument. Device `name` must be a string.' ); } - if ( NAMES.indexOf( name ) === -1 ) { + indexOfName = DEVICENAMESLOWER.indexOf( name.toLowerCase() ); + if ( indexOfName === -1 ) { return null; } - return null; - }; // end METHOD source() + return JSON.parse( JSON.stringify( DEVICES[ DEVICENAMES[ indexOfName ] ] ) ); + }; // end METHOD device() // EXPORTS // diff --git a/package.json b/package.json index 790d3c0..1d5286e 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ ], "scripts": { "postinstall": "./scripts/specs.js", - "test": "./node_modules/.bin/mocha", + "postupdate": "./scripts/specs.js", + "get-specs": "./scripts/specs.js", + "test": "./node_modules/.bin/mocha -R nyan", "test-cov": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha --dir ./reports/coverage -- -R spec", "coveralls": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha --dir ./reports/coveralls/coverage --report lcovonly -- -R spec && cat ./reports/coveralls/coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./reports/coveralls" }, @@ -34,9 +36,9 @@ }, "devDependencies": { "chai": "1.x.x", - "mocha": "1.x.x", "coveralls": "^2.11.1", - "istanbul": "^0.3.0" + "istanbul": "^0.3.0", + "mocha": "1.x.x" }, "licenses": [ { diff --git a/scripts/specs.js b/scripts/specs.js index 70a77df..07c20a5 100755 --- a/scripts/specs.js +++ b/scripts/specs.js @@ -57,9 +57,9 @@ */ function getSpecs() { var keys = Object.keys( resources ); - - fs.mkdirSync( filepath ); - + if ( !fs.existsSync( filepath ) ) { + fs.mkdirSync( filepath ); + } for ( var i = 0; i < keys.length; i++ ) { request({ 'method': 'GET', diff --git a/test/test.js b/test/test.js index 44220d6..21be883 100644 --- a/test/test.js +++ b/test/test.js @@ -8,7 +8,29 @@ var // Expectation library: METRICS = require( './../specs/memory.json' ), // Module to be tested: - metrics = require( './../lib' ); + metrics = require( './../lib' ), + + // Metric specifications by device: + DEVICES = {}; + +var metricName, + deviceName, + i; + +for ( metricName in METRICS ) { + if ( METRICS[ metricName ].device !== null ) { + for ( i = 0; i < METRICS[ metricName ].device.length; i++ ) { + DEVICES[ METRICS[ metricName ].device[i] ] = ( DEVICES[ METRICS[ metricName ].device[i] ] ? DEVICES[ METRICS[ metricName ].device[i] ] : {} ); + } + } +} +for ( deviceName in DEVICES ) { + for ( metricName in METRICS ) { + if ( METRICS[ metricName ].device.indexOf( deviceName ) !== -1 ) { + DEVICES[ deviceName ][ metricName ] = METRICS[ metricName ]; + } + } +} // VARIABLES // @@ -24,7 +46,8 @@ describe( 'doc-metrix-memory', function tests() { // SETUP // - var NAMES = Object.keys( METRICS ); + var NAMES = Object.keys( METRICS ), + DEVICENAMES = Object.keys( DEVICES ); // TESTS // @@ -75,13 +98,17 @@ describe( 'doc-metrix-memory', function tests() { }); it( 'should return false for a metric which does not have a specification', function test() { - assert.notOk( metrics.exists( 'cpu.utilization' ) ); + assert.notOk( metrics.exists( 'invalid.classification.utilization' ) ); }); it( 'should return true for a metric which has a specification', function test() { assert.ok( metrics.exists( NAMES[0] ), true ); }); + it( 'should return true for a metric which has a specification regardless of input name case sensitivity', function test() { + assert.ok( metrics.exists( NAMES[0].toUpperCase() ), true ); + }); + }); describe( 'get', function tests() { @@ -96,8 +123,8 @@ describe( 'doc-metrix-memory', function tests() { [], {}, true, - null, undefined, + null, NaN, function(){} ]; @@ -114,18 +141,79 @@ describe( 'doc-metrix-memory', function tests() { }); it( 'should return null for a metric which does not have a specification', function test() { - assert.isNull( metrics.get( 'cpu.utilization' ) ); + assert.isNull( metrics.get( 'invalid.classification.utilization' ) ); }); it( 'should return a metric specification', function test() { assert.deepEqual( metrics.get( NAMES[0] ), METRICS[ NAMES[0] ] ); }); + it( 'should return all metric specifications if called without a metric name', function test() { + assert.deepEqual( metrics.get(), METRICS ); + }); + + it( 'should return a metric specification regardless of input name case sensitivity', function test() { + assert.deepEqual( metrics.get( NAMES[0].toUpperCase() ), METRICS[ NAMES[0] ] ); + }); + }); - describe( 'source', function tests() { + describe( 'listDevices', function tests() { + + it( 'should provide a method to list all devices associated with the metrics', function test() { + expect( metrics.listDevices ).to.be.a( 'function' ); + }); + + it( 'should list all devices associated with the metrics', function test() { + assert.deepEqual( metrics.listDevices(), DEVICENAMES ); + }); + + }); + + describe( 'device', function tests() { + + it( 'should provide a method to get metric specifications associated with a device', function test() { + expect( metrics.device ).to.be.a( 'function' ); + }); + + it( 'should not allow a non-string metric name', function test() { + var values = [ + 5, + [], + {}, + true, + undefined, + null, + NaN, + function(){} + ]; + + for ( var i = 0; i < values.length; i++ ) { + expect( badValue( values[i] ) ).to.throw( Error ); + } - it( 'should do something' ); + function badValue( value ) { + return function() { + metrics.device( value ); + }; + } + }); + + it( 'should return null for a device which does not have any associated metric specification', function test() { + assert.isNull( metrics.device( 'no such device' ) ); + }); + + it( 'should return metric specification(s) associated with the device', function test() { + assert.deepEqual( metrics.device( DEVICENAMES[0] ), DEVICES[ DEVICENAMES[0] ] ); + }); + + it( 'should return metric specifications associated with all devices if called without a device name', function test() { + assert.deepEqual( metrics.device(), DEVICES ); + }); + + it( 'should return metric specification(s) associated with the device regardless of input device case sensitivity', function test() { + assert.deepEqual( metrics.device( DEVICENAMES[0].toUpperCase() ), DEVICES[ DEVICENAMES[0] ] ); + }); });