Skip to content

Commit c1e542a

Browse files
unframeworkMarsup
authored andcommitted
fix: add in-memory source code caching to support detail reports on compiled CoffeeScript and other files with intermediate pre-processing
1 parent c5d0b4c commit c1e542a

File tree

4 files changed

+41
-53
lines changed

4 files changed

+41
-53
lines changed

lib/preprocessor.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
var istanbul = require('istanbul'),
22
ibrik = require('ibrik'),
3-
minimatch = require('minimatch');
3+
minimatch = require('minimatch'),
4+
globalSourceCache = require('./sourceCache');
45

56
var createCoveragePreprocessor = function(logger, basePath, reporters, coverageReporter) {
67
var log = logger.create('preprocessor.coverage');
78
var instrumenterOverrides = (coverageReporter && coverageReporter.instrumenter) || {};
89
var instrumenters = {istanbul: istanbul, ibrik: ibrik};
10+
var sourceCache = globalSourceCache.getByBasePath(basePath);
911

1012
// if coverage reporter is not used, do not preprocess the files
1113
if (reporters.indexOf('coverage') === -1) {
@@ -55,6 +57,9 @@ var createCoveragePreprocessor = function(logger, basePath, reporters, coverageR
5557
file.path = file.path.replace(/\.coffee$/, '.js');
5658
}
5759

60+
// remember the actual immediate instrumented JS for given original path
61+
sourceCache[jsPath] = content;
62+
5863
done(instrumentedCode);
5964
});
6065
};

lib/reporter.js

+13-16
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,31 @@ var fs = require('fs');
33
var util = require('util');
44
var istanbul = require('istanbul');
55
var dateformat = require('dateformat');
6+
var globalSourceCache = require('./sourceCache');
67

78

89
var Store = istanbul.Store;
910

10-
var BasePathStore = function(opts) {
11+
var SourceCacheStore = function(opts) {
1112
Store.call(this, opts);
1213
opts = opts || {};
13-
this.basePath = opts.basePath;
14-
this.delegate = Store.create('fslookup');
14+
this.sourceCache = opts.sourceCache;
1515
};
16-
BasePathStore.TYPE = 'basePathlookup';
17-
util.inherits(BasePathStore, Store);
16+
SourceCacheStore.TYPE = 'sourceCacheLookup';
17+
util.inherits(SourceCacheStore, Store);
1818

19-
Store.mix(BasePathStore, {
19+
Store.mix(SourceCacheStore, {
2020
keys : function() {
21-
return this.delegate.keys();
22-
},
23-
toKey : function(key) {
24-
if (key.indexOf('./') === 0) { return path.join(this.basePath, key); }
25-
return key;
21+
throw 'not implemented';
2622
},
2723
get : function(key) {
28-
return this.delegate.get(this.toKey(key));
24+
return this.sourceCache[key];
2925
},
3026
hasKey : function(key) {
31-
return this.delegate.hasKey(this.toKey(key));
27+
return this.sourceCache.hasOwnProperty(key);
3228
},
3329
set : function(key, contents) {
34-
return this.delegate.set(this.toKey(key), contents);
30+
throw 'not applicable';
3531
}
3632
});
3733

@@ -42,6 +38,7 @@ var CoverageReporter = function(rootConfig, helper, logger) {
4238
var config = rootConfig.coverageReporter || {};
4339
var basePath = rootConfig.basePath;
4440
var reporters = config.reporters;
41+
var sourceCache = globalSourceCache.getByBasePath(basePath);
4542

4643
if (!helper.isDefined(reporters)) {
4744
reporters = [config];
@@ -132,8 +129,8 @@ var CoverageReporter = function(rootConfig, helper, logger) {
132129
log.debug('Writing coverage to %s', outputDir);
133130
var options = helper.merge({}, reporterConfig, {
134131
dir : outputDir,
135-
sourceStore : new BasePathStore({
136-
basePath : basePath
132+
sourceStore : new SourceCacheStore({
133+
sourceCache: sourceCache
137134
})
138135
});
139136
var reporter = istanbul.Report.create(reporterConfig.type || 'html', options);

lib/sourceCache.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
var cacheByBasePath = {};
3+
4+
exports.getByBasePath = function (basePath) {
5+
return cacheByBasePath[basePath] ? cacheByBasePath[basePath] : (cacheByBasePath[basePath] = {});
6+
};

test/reporter.spec.coffee

+16-36
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@ describe 'reporter', ->
2323
mockStore = sinon.spy()
2424
mockStore.mix = (fn, obj) ->
2525
istanbul.Store.mix fn, obj
26-
mockFslookup = sinon.stub
27-
keys: ->
28-
get: ->
29-
hasKey: ->
30-
set: ->
31-
mockStore.create = sinon.stub().returns mockFslookup
3226

3327
mockAdd = sinon.spy()
3428
mockDispose = sinon.spy()
@@ -56,40 +50,26 @@ describe 'reporter', ->
5650
beforeEach ->
5751
m = loadFile __dirname + '/../lib/reporter.js', mocks
5852

59-
describe 'BasePathStore', ->
53+
describe 'SourceCacheStore', ->
6054
options = store = null
6155

6256
beforeEach ->
6357
options =
64-
basePath: 'path/to/coverage/'
65-
store = new m.BasePathStore options
66-
67-
describe 'toKey', ->
68-
it 'should concat relative path and basePath', ->
69-
expect(store.toKey './foo').to.deep.equal path.join(options.basePath, 'foo')
70-
71-
it 'should does not concat absolute path and basePath', ->
72-
expect(store.toKey '/foo').to.deep.equal '/foo'
73-
74-
it 'should call keys and delegate to inline store', ->
75-
store.keys()
76-
expect(mockFslookup.keys).to.have.been.called
77-
78-
it 'should call get and delegate to inline store', ->
79-
key = './path/to/js'
80-
store.get(key)
81-
expect(mockFslookup.get).to.have.been.calledWith path.join(options.basePath, key)
82-
83-
it 'should call hasKey and delegate to inline store', ->
84-
key = './path/to/js'
85-
store.hasKey(key)
86-
expect(mockFslookup.hasKey).to.have.been.calledWith path.join(options.basePath, key)
87-
88-
it 'should call set and delegate to inline store', ->
89-
key = './path/to/js'
90-
content = 'any content'
91-
store.set key, content
92-
expect(mockFslookup.set).to.have.been.calledWith path.join(options.basePath, key), content
58+
sourceCache: { './foo': 'TEST_SRC_DATA' }
59+
store = new m.SourceCacheStore options
60+
61+
it 'should fail on call to keys', ->
62+
expect(-> store.keys()).to.throw()
63+
64+
it 'should call get and check cache data', ->
65+
expect(store.get('./foo')).to.equal 'TEST_SRC_DATA'
66+
67+
it 'should call hasKey and check cache data', ->
68+
expect(store.hasKey('./foo')).to.be.true
69+
expect(store.hasKey('./bar')).to.be.false
70+
71+
it 'should fail on call to set', ->
72+
expect(-> store.set()).to.throw()
9373

9474
describe 'CoverageReporter', ->
9575
rootConfig = emitter = reporter = null

0 commit comments

Comments
 (0)