Code coverage report for istanbul/lib/collector.js

Statements: 87.5% (28 / 32)      Branches: 62.5% (10 / 16)      Functions: 100% (9 / 9)      Lines: 90.32% (28 / 31)     

All files » istanbul/lib/ » collector.js
1 /*
2 Copyright (c) 2012, Yahoo! Inc. All rights reserved.
3 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
4 */
5
6 1 var MemoryStore = require('./store/memory'),
7 LookupStore = require('./store/fslookup')
8 1 utils = require('./object-utils');
9
10 /**
11 * a mechanism to merge multiple coverage objects into one. Handles the use case
12 * of overlapping coverage information for the same files in multiple coverage
13 * objects and does not double-count in this situation. For example, if
14 * you pass the same coverage object multiple times, the final merged object will be
15 * no different that any of the objects passed in (except for execution counts).
16 *
17 * The `Collector` is built for scale to handle thousands of coverage objects.
18 * By default, all processing is done in memory since the common use-case is of
19 * one or a few coverage objects. You can work around memory
20 * issues by passing in a `Store` implementation that stores temporary computations
21 * on disk (the `tmp` store, for example).
22 *
23 * The `getFinalCoverage` method returns an object with merged coverage information
24 * and is provided as a convenience for implementors working with coverage information
25 * that can fit into memory. Reporters, in the interest of generality, should *not* use this method for
26 * creating reports.
27 *
28 * Usage
29 * -----
30 *
31 * var collector = new require('istanbul').Collector();
32 *
33 * files.forEach(function (f) {
34 * //each coverage object can have overlapping information about multiple files
35 * collector.add(JSON.parse(fs.readFileSync(f, 'utf8')));
36 * });
37 *
38 * collector.files().forEach(function(file) {
39 * var fileCoverage = collector.fileCoverageFor(file);
40 * console.log('Coverage for ' + file + ' is:' + JSON.stringify(fileCoverage));
41 * });
42 *
43 * // convenience method: do not use this when dealing with a large number of files
44 * var finalCoverage = collector.getFinalCoverage();
45 *
46 * @class Collector
47 * @constructor
48 * @param {Object} options Optional. Configuration options.
49 * @param {Store} options.store - an implementation of `Store` to use for temporary
50 * calculations.
51 * @param {Store} options.sourceStore - an implementation of `Store` for finding
52 * original sources.
53 */
54 1 function Collector(options) {
55 8 options = options || {};
56 8 this.store = options.store || new MemoryStore();
57 8 this.sourceStore = options.sourceStore || new LookupStore();
58 8 this.embeddedSource = false;
59 }
60
61 1 Collector.prototype = {
62 /**
63 * adds a coverage object to the collector.
64 *
65 * @method add
66 * @param {Object} coverage the coverage object.
67 * @param {String} testName Optional. The name of the test used to produce the object.
68 * This is currently not used.
69 */
70 add: function (coverage, testName) {
71 9 var store = this.store;
72 9 Object.keys(coverage).forEach(function (key) {
73 29 var fileCoverage = coverage[key];
74 29 Iif (fileCoverage.code) { this.embeddedSource = true; } //keep track of the fact that we have seen at least one object with embedded sources
75 29 if (store.hasKey(key)) {
76 1 store.setObject(key, utils.mergeFileCoverage(fileCoverage, store.getObject(key)));
77 } else {
78 28 store.setObject(key, fileCoverage);
79 }
80 });
81 },
82 /**
83 * returns a list of unique file paths for which coverage information has been added.
84 * @method files
85 * @return {Array} an array of file paths for which coverage information is present.
86 */
87 files: function () {
88 12 return this.store.keys();
89 },
90 /**
91 * return file coverage information for a single file
92 * @method fileCoverageFor
93 * @param {String} fileName the path for the file for which coverage information is
94 * required. Must be one of the values returned in the `files()` method.
95 * @return {Object} the coverage information for the specified file.
96 */
97 fileCoverageFor: function (fileName) {
98 56 var ret = this.store.getObject(fileName);
99 56 utils.addDerivedInfoForFile(ret);
100 56 return ret;
101 },
102 /**
103 * return source code for a file
104 * @method sourceFor
105 * @param {String} fileName the path for the file for which source code is required.
106 * Must be one of the values returned in the `files()` method.
107 * @return {Object} the source code for the specified file.
108 */
109 sourceFor: function (fileName) {
110 16 var obj;
111
112 16 Iif (this.embeddedSource) { //get it from coverage object if possible
113 obj = this.store.getObject(fileName);
114 if (obj.code && Array.isArray(obj.code)) {
115 return obj.code.join('\n');
116 }
117 }
118 16 return this.sourceStore.get(fileName);
119 },
120 /**
121 * returns file coverage information for all files. This has the same format as
122 * any of the objects passed in to the `add` method. The number of keys in this
123 * object will be a superset of all keys found in the objects passed to `add()`
124 * @method getFinalCoverage
125 * @return {Object} the merged coverage information
126 */
127 getFinalCoverage: function () {
128 2 var ret = {},
129 that = this;
130 2 this.files().forEach(function (file) {
131 4 ret[file] = that.fileCoverageFor(file);
132 });
133 2 return ret;
134 },
135 /**
136 * disposes this collector and reclaims temporary resources used in the
137 * computation. Calls `dispose()` on the underlying store.
138 * @method dispose
139 */
140 dispose: function () {
141 2 this.store.dispose();
142 }
143 };
144
145 1 module.exports = Collector;