diff options
author | Florian Dold <florian.dold@gmail.com> | 2016-10-10 03:43:44 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2016-10-10 03:43:44 +0200 |
commit | abd94a7f5a50f43c797a11b53549ae48fff667c3 (patch) | |
tree | ab8ed457f65cdd72e13e0571d2975729428f1551 /node_modules/istanbul-lib-coverage/lib | |
parent | a0247c6a3fd6a09a41a7e35a3441324c4dcb58be (diff) |
add node_modules to address #4364
Diffstat (limited to 'node_modules/istanbul-lib-coverage/lib')
-rw-r--r-- | node_modules/istanbul-lib-coverage/lib/coverage-map.js | 116 | ||||
-rw-r--r-- | node_modules/istanbul-lib-coverage/lib/file.js | 331 |
2 files changed, 447 insertions, 0 deletions
diff --git a/node_modules/istanbul-lib-coverage/lib/coverage-map.js b/node_modules/istanbul-lib-coverage/lib/coverage-map.js new file mode 100644 index 000000000..440779a6a --- /dev/null +++ b/node_modules/istanbul-lib-coverage/lib/coverage-map.js @@ -0,0 +1,116 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +"use strict"; + +var FileCoverage = require('./file').FileCoverage, + CoverageSummary = require('./file').CoverageSummary; + +function loadMap(source) { + var data = {}; + Object.keys(source).forEach(function (k) { + var cov = source[k]; + if (cov instanceof FileCoverage) { + data[k] = cov; + } else { + data[k] = new FileCoverage(cov); + } + }); + return data; +} +/** + * CoverageMap is a map of `FileCoverage` objects keyed by file paths. + * @param {Object} [obj=undefined] obj A coverage map from which to initialize this + * map's contents. This can be the raw global coverage object. + * @constructor + */ +function CoverageMap(obj) { + if (!obj) { + this.data = {}; + } else if (obj instanceof CoverageMap) { + this.data = obj.data; + } else { + this.data = loadMap(obj); + } +} +/** + * merges a second coverage map into this one + * @param {CoverageMap} obj - a CoverageMap or its raw data. Coverage is merged + * correctly for the same files and additional file coverage keys are created + * as needed. + */ +CoverageMap.prototype.merge = function (obj) { + var that = this, + other; + if (obj instanceof CoverageMap) { + other = obj; + } else { + other = new CoverageMap(obj); + } + Object.keys(other.data).forEach(function (k) { + var fc = other.data[k]; + if (that.data[k]) { + that.data[k].merge(fc); + } else { + that.data[k] = fc; + } + }); +}; +/** + * returns a JSON-serializable POJO for this coverage map + * @returns {Object} + */ +CoverageMap.prototype.toJSON = function () { + return this.data; +}; +/** + * returns an array for file paths for which this map has coverage + * @returns {Array{string}} - array of files + */ +CoverageMap.prototype.files = function () { + return Object.keys(this.data); +}; +/** + * returns the file coverage for the specified file. + * @param {String} file + * @returns {FileCoverage} + */ +CoverageMap.prototype.fileCoverageFor = function (file) { + var fc = this.data[file]; + if (!fc) { + throw new Error('No file coverage available for: ' + file); + } + return fc; +}; +/** + * adds a file coverage object to this map. If the path for the object, + * already exists in the map, it is merged with the existing coverage + * otherwise a new key is added to the map. + * @param {FileCoverage} fc the file coverage to add + */ +CoverageMap.prototype.addFileCoverage = function (fc) { + var cov = new FileCoverage(fc), + path = cov.path; + if (this.data[path]) { + this.data[path].merge(cov); + } else { + this.data[path] = cov; + } +}; +/** + * returns the coverage summary for all the file coverage objects in this map. + * @returns {CoverageSummary} + */ +CoverageMap.prototype.getCoverageSummary = function () { + var that = this, + ret = new CoverageSummary(); + this.files().forEach(function (key) { + ret.merge(that.fileCoverageFor(key).toSummary()); + }); + return ret; +}; + +module.exports = { + CoverageMap: CoverageMap +}; diff --git a/node_modules/istanbul-lib-coverage/lib/file.js b/node_modules/istanbul-lib-coverage/lib/file.js new file mode 100644 index 000000000..0cfb8a4be --- /dev/null +++ b/node_modules/istanbul-lib-coverage/lib/file.js @@ -0,0 +1,331 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +"use strict"; + +function percent(covered, total) { + var tmp; + if (total > 0) { + tmp = 1000 * 100 * covered / total + 5; + return Math.floor(tmp / 10) / 100; + } else { + return 100.00; + } +} + +function blankSummary() { + var empty = function () { + return { + total: 0, + covered: 0, + skipped: 0, + pct: 'Unknown' + }; + }; + return { + lines: empty(), + statements: empty(), + functions: empty(), + branches: empty() + }; +} + +// asserts that a data object "looks like" a summary coverage object +function assertValidSummary(obj) { + var valid = obj && + obj.lines && + obj.statements && + obj.functions && + obj.branches; + if (!valid) { + throw new Error('Invalid summary coverage object, missing keys, found:' + + Object.keys(obj).join(',')); + } +} +/** + * CoverageSummary provides a summary of code coverage . It exposes 4 properties, + * `lines`, `statements`, `branches`, and `functions`. Each of these properties + * is an object that has 4 keys `total`, `covered`, `skipped` and `pct`. + * `pct` is a percentage number (0-100). + * @param {Object|CoverageSummary} [obj=undefined] an optional data object or + * another coverage summary to initialize this object with. + * @constructor + */ +function CoverageSummary(obj) { + if (!obj) { + this.data = blankSummary(); + } else if (obj instanceof CoverageSummary) { + this.data = obj.data; + } else { + this.data = obj; + } + assertValidSummary(this.data); +} + +['lines', 'statements', 'functions', 'branches'].forEach(function (p) { + Object.defineProperty(CoverageSummary.prototype, p, { + enumerable: true, + get: function () { + return this.data[p]; + } + }); +}); + +/** + * merges a second summary coverage object into this one + * @param {CoverageSummary} obj - another coverage summary object + */ +CoverageSummary.prototype.merge = function (obj) { + var that = this, + keys = ['lines', 'statements', 'branches', 'functions']; + keys.forEach(function (key) { + that[key].total += obj[key].total; + that[key].covered += obj[key].covered; + that[key].skipped += obj[key].skipped; + that[key].pct = percent(that[key].covered, that[key].total); + }); + return this; +}; + +/** + * returns a POJO that is JSON serializable. May be used to get the raw + * summary object. + */ +CoverageSummary.prototype.toJSON = function () { + return this.data; +}; + +// returns a data object that represents empty coverage +function emptyCoverage(filePath) { + return { + path: filePath, + statementMap: {}, + fnMap: {}, + branchMap: {}, + s: {}, + f: {}, + b: {} + }; +} +// asserts that a data object "looks like" a coverage object +function assertValidObject(obj) { + var valid = obj && + obj.path && + obj.statementMap && + obj.fnMap && + obj.branchMap && + obj.s && + obj.f && + obj.b; + if (!valid) { + throw new Error('Invalid file coverage object, missing keys, found:' + + Object.keys(obj).join(',')); + } +} +/** + * provides a read-only view of coverage for a single file. + * The deep structure of this object is documented elsewhere. It has the following + * properties: + * + * * `path` - the file path for which coverage is being tracked + * * `statementMap` - map of statement locations keyed by statement index + * * `functionMap` - map of function metadata keyed by function index + * * `branchMap` - map of branch metadata keyed by branch index + * * `s` - hit counts for statements + * * `f` - hit count for functions + * * `b` - hit count for branches + * + * @param {Object|FileCoverage|String} pathOrObj is a string that initializes + * and empty coverage object with the specified file path or a data object that + * has all the required properties for a file coverage object. + * @constructor + */ +function FileCoverage(pathOrObj) { + if (!pathOrObj) { + throw new Error("Coverage must be initialized with a path or an object"); + } + if (typeof pathOrObj === 'string') { + this.data = emptyCoverage(pathOrObj); + } else if (pathOrObj instanceof FileCoverage) { + this.data = pathOrObj.data; + } else if (typeof pathOrObj === 'object') { + this.data = pathOrObj; + } else { + throw new Error('Invalid argument to coverage constructor'); + } + assertValidObject(this.data); +} +/** + * returns computed line coverage from statement coverage. + * This is a map of hits keyed by line number in the source. + */ +FileCoverage.prototype.getLineCoverage = function () { + var statementMap = this.data.statementMap, + statements = this.data.s, + lineMap = {}; + + Object.keys(statements).forEach(function (st) { + if (!statementMap[st]) { + return; + } + var line = statementMap[st].start.line, + count = statements[st], + prevVal = lineMap[line]; + if (prevVal === undefined || prevVal < count) { + lineMap[line] = count; + } + }); + return lineMap; +}; +/** + * returns an array of uncovered line numbers. + * @returns {Array} an array of line numbers for which no hits have been + * collected. + */ +FileCoverage.prototype.getUncoveredLines = function () { + var lc = this.getLineCoverage(), + ret = []; + Object.keys(lc).forEach(function (l) { + var hits = lc[l]; + if (hits === 0) { + ret.push(l); + } + }); + return ret; +}; +/** + * returns a map of branch coverage by source line number. + * @returns {Object} an object keyed by line number. Each object + * has a `covered`, `total` and `coverage` (percentage) property. + */ +FileCoverage.prototype.getBranchCoverageByLine = function () { + var branchMap = this.branchMap, + branches = this.b, + ret = {}; + Object.keys(branchMap).forEach(function (k) { + var line = branchMap[k].line, + branchData = branches[k]; + ret[line] = ret[line] || []; + ret[line].push.apply(ret[line], branchData); + }); + Object.keys(ret).forEach(function (k) { + var dataArray = ret[k], + covered = dataArray.filter(function (item) { return item > 0; }), + coverage = covered.length / dataArray.length * 100; + ret[k] = { covered: covered.length, total: dataArray.length, coverage: coverage }; + }); + return ret; +}; + +// expose coverage data attributes +['path', 'statementMap', 'fnMap', 'branchMap', 's', 'f', 'b' ].forEach(function (p) { + Object.defineProperty(FileCoverage.prototype, p, { + enumerable: true, + get: function () { + return this.data[p]; + } + }); +}); +/** + * return a JSON-serializable POJO for this file coverage object + */ +FileCoverage.prototype.toJSON = function () { + return this.data; +}; +/** + * merges a second coverage object into this one, updating hit counts + * @param {FileCoverage} other - the coverage object to be merged into this one. + * Note that the other object should have the same structure as this one (same file). + */ +FileCoverage.prototype.merge = function (other) { + var that = this; + Object.keys(other.s).forEach(function (k) { + that.data.s[k] += other.s[k]; + }); + Object.keys(other.f).forEach(function (k) { + that.data.f[k] += other.f[k]; + }); + Object.keys(other.b).forEach(function (k) { + var i, + retArray = that.data.b[k], + secondArray = other.b[k]; + for (i = 0; i < retArray.length; i += 1) { + retArray[i] += secondArray[i]; + } + }); +}; + +FileCoverage.prototype.computeSimpleTotals = function (property) { + var stats = this[property], + ret = {total: 0, covered: 0, skipped: 0}; + + if (typeof stats === 'function') { + stats = stats.call(this); + } + Object.keys(stats).forEach(function (key) { + var covered = !!stats[key]; + ret.total += 1; + if (covered) { + ret.covered += 1; + } + }); + ret.pct = percent(ret.covered, ret.total); + return ret; +}; + +FileCoverage.prototype.computeBranchTotals = function () { + var stats = this.b, + ret = {total: 0, covered: 0, skipped: 0}; + + Object.keys(stats).forEach(function (key) { + var branches = stats[key], + covered; + branches.forEach(function (branchHits) { + covered = branchHits > 0; + if (covered) { + ret.covered += 1; + } + }); + ret.total += branches.length; + }); + ret.pct = percent(ret.covered, ret.total); + return ret; +}; +/** + * resets hit counts for all statements, functions and branches + * in this coverage object resulting in zero coverage. + */ +FileCoverage.prototype.resetHits = function () { + var statements = this.s, + functions = this.f, + branches = this.b; + Object.keys(statements).forEach(function (s) { + statements[s] = 0; + }); + Object.keys(functions).forEach(function (f) { + functions[f] = 0; + }); + Object.keys(branches).forEach(function (b) { + var hits = branches[b]; + branches[b] = hits.map(function () { return 0; }); + }); +}; + +/** + * returns a CoverageSummary for this file coverage object + * @returns {CoverageSummary} + */ +FileCoverage.prototype.toSummary = function () { + var ret = {}; + ret.lines = this.computeSimpleTotals('getLineCoverage'); + ret.functions = this.computeSimpleTotals('f', 'fnMap'); + ret.statements = this.computeSimpleTotals('s', 'statementMap'); + ret.branches = this.computeBranchTotals(); + return new CoverageSummary(ret); +}; + +module.exports = { + CoverageSummary: CoverageSummary, + FileCoverage: FileCoverage +}; |