From eeaa1ddff5ed9e5d3a9441570c6466026629775b Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Mon, 7 Dec 2015 13:54:37 +0000 Subject: [PATCH 1/3] source-map-fixtures@0.2.0 The fixtures now provide a sourceFile property which can be used to get the source location. --- package.json | 2 +- test/source-map-cache.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 19235a829..6818080ff 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "devDependencies": { "chai": "^3.0.0", "sinon": "^1.15.3", - "source-map-fixtures": "^0.1.0", + "source-map-fixtures": "^0.2.0", "standard": "^5.2.1", "tap": "^1.3.4" }, diff --git a/test/source-map-cache.js b/test/source-map-cache.js index 7e63feb35..b336d7d40 100644 --- a/test/source-map-cache.js +++ b/test/source-map-cache.js @@ -8,7 +8,7 @@ var fixture = require('source-map-fixtures').inline('branching') // compute the path to the fixture file relative to the root directory. var relpath = './' + path.relative(path.join(__dirname, '..'), fixture.file) // the sourcemap itself remaps the path. -var mappedPath = './' + path.join(path.dirname(relpath), '../src/branching.js') +var mappedPath = './' + path.relative(path.join(__dirname, '..'), fixture.sourceFile) // Compute the number of lines in the original source, excluding any line break // at the end of the file. var maxLine = fixture.sourceContentSync().trimRight().split(/\r?\n/).length From d4b6393f82986319cc6b39d262369a2580101f36 Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Mon, 7 Dec 2015 14:35:27 +0000 Subject: [PATCH 2/3] generate coverage fixture without source maps It can't be used to test source map support if the source maps are already applied to the coverage report. With this change no reports are written to disk. Therefore the temp directory doesn't have to be cleaned. --- test/fixtures/_generateCoverage.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/fixtures/_generateCoverage.js b/test/fixtures/_generateCoverage.js index b154169b4..a1fbb7e7d 100644 --- a/test/fixtures/_generateCoverage.js +++ b/test/fixtures/_generateCoverage.js @@ -14,14 +14,9 @@ var NYC = require('../../') // Load the 'branching' source map fixture. var fixture = require('source-map-fixtures').inline('branching') -// Prevent pollution from earlier nyc runs. -var tempDirectory = path.join(__dirname, '.nyc_output') -rimraf.sync(tempDirectory) - // Inject nyc into this process. var nyc = (new NYC({ - cwd: path.join(__dirname, '..', '..'), - tempDirectory: tempDirectory + cwd: path.join(__dirname, '..', '..') })).wrap() // Override the exclude option, source-map-fixtures is inside node_modules but // should not be excluded when generating the coverage report. @@ -31,18 +26,23 @@ nyc.exclude = [] // coverage. fixture.require().run() -// Write the coverage file so reports can be loaded. -nyc.writeCoverageFile() +// Copy NYC#writeCoverageFile() behavior to get the coverage object, before +// source maps have been applied. +var coverage = global.__coverage__ +if (typeof __coverage__ === 'object') coverage = __coverage__ +if (!coverage) { + console.error('No coverage.') + process.exit(1) +} -var reports = _.values(nyc._loadReports()[0]) +var reports = _.values(coverage) if (reports.length !== 1) { console.error('Expected 1 report to be generated, got ' + reports.length) process.exit(1) } -var coverage = reports[0] fs.writeFileSync( path.join(__dirname, 'coverage.js'), '// Generated using node test/fixtures/_generateCoverage.js\n' + - 'exports[' + JSON.stringify(coverage.path) + '] = ' + JSON.stringify(coverage, null, 2) + '\n') -console.log('Written coverage report.') + 'exports[' + JSON.stringify(reports[0].path) + '] = ' + JSON.stringify(reports[0], null, 2) + '\n') + console.log('Written coverage report.') From 2a20a22e2e3b68f12e0a8b28b7c37aa6299e9879 Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Mon, 7 Dec 2015 14:38:00 +0000 Subject: [PATCH 3/3] test rewriting coverage path based on source maps Generate coverage reports for files without source maps or with multiple sources. Refactor source map tests a bit now that three covered fixtures are loaded. --- test/fixtures/_generateCoverage.js | 29 ++- test/fixtures/coverage.js | 326 +++++++++++++++++++++++++++++ test/source-map-cache.js | 87 +++++--- 3 files changed, 405 insertions(+), 37 deletions(-) diff --git a/test/fixtures/_generateCoverage.js b/test/fixtures/_generateCoverage.js index a1fbb7e7d..d9ef349e4 100644 --- a/test/fixtures/_generateCoverage.js +++ b/test/fixtures/_generateCoverage.js @@ -8,11 +8,16 @@ var path = require('path') var _ = require('lodash') var rimraf = require('rimraf') +var sourceMapFixtures = require('source-map-fixtures') var NYC = require('../../') -// Load the 'branching' source map fixture. -var fixture = require('source-map-fixtures').inline('branching') +// Load source map fixtures. +var fixtures = { + bundle: sourceMapFixtures.inline('bundle'), + inline: sourceMapFixtures.inline('branching'), + none: sourceMapFixtures.none('branching') +} // Inject nyc into this process. var nyc = (new NYC({ @@ -24,7 +29,9 @@ nyc.exclude = [] // Require the fixture so nyc can instrument it, then run it so there's code // coverage. -fixture.require().run() +fixtures.bundle.require().branching() +fixtures.inline.require().run() +fixtures.none.require().run() // Copy NYC#writeCoverageFile() behavior to get the coverage object, before // source maps have been applied. @@ -36,13 +43,17 @@ if (!coverage) { } var reports = _.values(coverage) -if (reports.length !== 1) { - console.error('Expected 1 report to be generated, got ' + reports.length) +if (reports.length !== 3) { + console.error('Expected 3 reports to be generated, got ' + reports.length) process.exit(1) } -fs.writeFileSync( - path.join(__dirname, 'coverage.js'), - '// Generated using node test/fixtures/_generateCoverage.js\n' + - 'exports[' + JSON.stringify(reports[0].path) + '] = ' + JSON.stringify(reports[0], null, 2) + '\n') +var out = fs.createWriteStream(path.join(__dirname, 'coverage.js')) +out.write('// Generated using node test/fixtures/_generateCoverage.js\n') +reports.forEach(function (coverage) { + out.write('exports[' + JSON.stringify(coverage.path) + '] = ' + JSON.stringify(coverage, null, 2) + '\n') +}) +out.end() +out.on('finish', function () { console.log('Written coverage report.') +}) diff --git a/test/fixtures/coverage.js b/test/fixtures/coverage.js index c8f8ab9ad..d2d653feb 100644 --- a/test/fixtures/coverage.js +++ b/test/fixtures/coverage.js @@ -1,4 +1,215 @@ // Generated using node test/fixtures/_generateCoverage.js +exports["./node_modules/source-map-fixtures/fixtures/bundle-inline.js"] = { + "path": "./node_modules/source-map-fixtures/fixtures/bundle-inline.js", + "s": { + "1": 1, + "2": 1, + "3": 0, + "4": 1, + "5": 0, + "6": 1, + "7": 1, + "8": 0, + "9": 1, + "10": 1, + "11": 1 + }, + "b": { + "1": [ + 0, + 1 + ] + }, + "f": { + "1": 0, + "2": 0, + "3": 1 + }, + "fnMap": { + "1": { + "name": "(anonymous_1)", + "line": 6, + "loc": { + "start": { + "line": 6, + "column": 8 + }, + "end": { + "line": 6, + "column": 20 + } + } + }, + "2": { + "name": "(anonymous_2)", + "line": 10, + "loc": { + "start": { + "line": 10, + "column": 8 + }, + "end": { + "line": 10, + "column": 20 + } + } + }, + "3": { + "name": "(anonymous_3)", + "line": 14, + "loc": { + "start": { + "line": 14, + "column": 8 + }, + "end": { + "line": 14, + "column": 21 + } + } + } + }, + "statementMap": { + "1": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 5, + "column": 3 + } + }, + "2": { + "start": { + "line": 6, + "column": 0 + }, + "end": { + "line": 8, + "column": 2 + } + }, + "3": { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 7, + "column": 51 + } + }, + "4": { + "start": { + "line": 10, + "column": 0 + }, + "end": { + "line": 12, + "column": 2 + } + }, + "5": { + "start": { + "line": 11, + "column": 2 + }, + "end": { + "line": 11, + "column": 12 + } + }, + "6": { + "start": { + "line": 14, + "column": 0 + }, + "end": { + "line": 18, + "column": 2 + } + }, + "7": { + "start": { + "line": 15, + "column": 2 + }, + "end": { + "line": 17, + "column": 3 + } + }, + "8": { + "start": { + "line": 16, + "column": 4 + }, + "end": { + "line": 16, + "column": 16 + } + }, + "9": { + "start": { + "line": 20, + "column": 0 + }, + "end": { + "line": 20, + "column": 22 + } + }, + "10": { + "start": { + "line": 21, + "column": 0 + }, + "end": { + "line": 21, + "column": 19 + } + }, + "11": { + "start": { + "line": 22, + "column": 0 + }, + "end": { + "line": 22, + "column": 19 + } + } + }, + "branchMap": { + "1": { + "line": 15, + "type": "if", + "locations": [ + { + "start": { + "line": 15, + "column": 2 + }, + "end": { + "line": 15, + "column": 2 + } + }, + { + "start": { + "line": 15, + "column": 2 + }, + "end": { + "line": 15, + "column": 2 + } + } + ] + } + } +} exports["./node_modules/source-map-fixtures/fixtures/branching-inline.js"] = { "path": "./node_modules/source-map-fixtures/fixtures/branching-inline.js", "s": { @@ -114,3 +325,118 @@ exports["./node_modules/source-map-fixtures/fixtures/branching-inline.js"] = { } } } +exports["./node_modules/source-map-fixtures/fixtures/branching-none.js"] = { + "path": "./node_modules/source-map-fixtures/fixtures/branching-none.js", + "s": { + "1": 1, + "2": 1, + "3": 1, + "4": 0, + "5": 1 + }, + "b": { + "1": [ + 0, + 1 + ] + }, + "f": { + "1": 1 + }, + "fnMap": { + "1": { + "name": "(anonymous_1)", + "line": 6, + "loc": { + "start": { + "line": 6, + "column": 8 + }, + "end": { + "line": 6, + "column": 21 + } + } + } + }, + "statementMap": { + "1": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 5, + "column": 3 + } + }, + "2": { + "start": { + "line": 6, + "column": 0 + }, + "end": { + "line": 10, + "column": 2 + } + }, + "3": { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 9, + "column": 3 + } + }, + "4": { + "start": { + "line": 8, + "column": 4 + }, + "end": { + "line": 8, + "column": 16 + } + }, + "5": { + "start": { + "line": 11, + "column": 0 + }, + "end": { + "line": 11, + "column": 16 + } + } + }, + "branchMap": { + "1": { + "line": 7, + "type": "if", + "locations": [ + { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 7, + "column": 2 + } + }, + { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 7, + "column": 2 + } + } + ] + } + } +} diff --git a/test/source-map-cache.js b/test/source-map-cache.js index b336d7d40..5bfc96b46 100644 --- a/test/source-map-cache.js +++ b/test/source-map-cache.js @@ -3,80 +3,111 @@ var _ = require('lodash') var path = require('path') -var fixture = require('source-map-fixtures').inline('branching') -// Coverage for the fixture is stored relative to the root directory. Here -// compute the path to the fixture file relative to the root directory. -var relpath = './' + path.relative(path.join(__dirname, '..'), fixture.file) -// the sourcemap itself remaps the path. -var mappedPath = './' + path.relative(path.join(__dirname, '..'), fixture.sourceFile) -// Compute the number of lines in the original source, excluding any line break -// at the end of the file. -var maxLine = fixture.sourceContentSync().trimRight().split(/\r?\n/).length +var sourceMapFixtures = require('source-map-fixtures') + +// Load source map fixtures. +var covered = _.mapValues({ + bundle: sourceMapFixtures.inline('bundle'), + inline: sourceMapFixtures.inline('branching'), + none: sourceMapFixtures.none('branching') +}, function (fixture) { + return _.assign({ + // Coverage for the fixture is stored relative to the root directory. Here + // compute the path to the fixture file relative to the root directory. + relpath: './' + path.relative(path.join(__dirname, '..'), fixture.file), + // the sourcemap itself remaps the path. + mappedPath: './' + path.relative(path.join(__dirname, '..'), fixture.sourceFile), + // Compute the number of lines in the original source, excluding any line + // break at the end of the file. + maxLine: fixture.sourceContentSync().trimRight().split(/\r?\n/).length + }, fixture) +}) var SourceMapCache = require('../lib/source-map-cache') var sourceMapCache = new SourceMapCache() -sourceMapCache.add(relpath, fixture.contentSync()) +_.forOwn(covered, function (fixture) { + sourceMapCache.add(fixture.relpath, fixture.contentSync()) +}) var coverage = require('./fixtures/coverage') +var fixture = covered.inline require('chai').should() require('tap').mochaGlobals() describe('source-map-cache', function () { + it('does not rewrite if there is no source map', function () { + var mappedCoverage = sourceMapCache.applySourceMaps(coverage) + mappedCoverage[covered.none.relpath].should.eql(coverage[covered.none.relpath]) + }) + + describe('path', function () { + it('does not rewrite path if the source map has more than one source', function () { + var mappedCoverage = sourceMapCache.applySourceMaps(coverage) + mappedCoverage.should.have.property(covered.bundle.relpath) + mappedCoverage[covered.bundle.relpath].should.not.eql(coverage[covered.bundle.relpath]) + }) + + it('rewrites path if the source map exactly one source', function () { + var mappedCoverage = sourceMapCache.applySourceMaps(_.pick(coverage, fixture.relpath)) + mappedCoverage.should.have.property(fixture.mappedPath) + }) + }) + describe('statements', function () { it('drops statements that have no mapping back to the original source code', function () { var mappedCoverage = sourceMapCache.applySourceMaps(coverage) - Object.keys(mappedCoverage[mappedPath].s) - .should.be.lt(coverage[relpath].s) - Object.keys(mappedCoverage[mappedPath].statementMap).length - .should.equal(Object.keys(mappedCoverage[mappedPath].s).length) + Object.keys(mappedCoverage[fixture.mappedPath].s) + .should.be.lt(coverage[fixture.relpath].s) + Object.keys(mappedCoverage[fixture.mappedPath].statementMap).length + .should.equal(Object.keys(mappedCoverage[fixture.mappedPath].s).length) }) it('maps all statements back to their original loc', function () { var mappedCoverage = sourceMapCache.applySourceMaps(coverage) - var statements = _.values(mappedCoverage[mappedPath].statementMap) + var statements = _.values(mappedCoverage[fixture.mappedPath].statementMap) var maxStatement = _.max(statements, function (s) { return Math.max(s.start.line, s.end.line) }) - Math.max(maxStatement.start.line, maxStatement.end.line).should.be.lte(maxLine) + Math.max(maxStatement.start.line, maxStatement.end.line).should.be.lte(fixture.maxLine) }) }) describe('functions', function () { it('drops functions that have no mapping back to the original source code', function () { var mappedCoverage = sourceMapCache.applySourceMaps(coverage) - Object.keys(mappedCoverage[mappedPath].f) - .should.be.lt(coverage[relpath].f) - Object.keys(mappedCoverage[mappedPath].fnMap).length - .should.equal(Object.keys(mappedCoverage[mappedPath].f).length) + Object.keys(mappedCoverage[fixture.mappedPath].f) + .should.be.lt(coverage[fixture.relpath].f) + Object.keys(mappedCoverage[fixture.mappedPath].fnMap).length + .should.equal(Object.keys(mappedCoverage[fixture.mappedPath].f).length) }) it('maps all functions back to their original loc', function () { var mappedCoverage = sourceMapCache.applySourceMaps(coverage) - var functions = _.values(mappedCoverage[mappedPath].fnMap) + var functions = _.values(mappedCoverage[fixture.mappedPath].fnMap) var maxFunction = _.max(functions, function (f) { return f.line }) - Math.max(maxFunction.line).should.be.lte(maxLine) + Math.max(maxFunction.line).should.be.lte(fixture.maxLine) }) }) describe('branches', function () { it('drops branches that have no mapping back to the original source code', function () { var mappedCoverage = sourceMapCache.applySourceMaps(coverage) - Object.keys(mappedCoverage[mappedPath].b) - .should.be.lt(coverage[relpath].b) - Object.keys(mappedCoverage[mappedPath].branchMap).length - .should.equal(Object.keys(mappedCoverage[mappedPath].b).length) + Object.keys(mappedCoverage[fixture.mappedPath].b) + .should.be.lt(coverage[fixture.relpath].b) + Object.keys(mappedCoverage[fixture.mappedPath].branchMap).length + .should.equal(Object.keys(mappedCoverage[fixture.mappedPath].b).length) }) it('maps all branches back to their original loc', function () { var mappedCoverage = sourceMapCache.applySourceMaps(coverage) - var branches = _.values(mappedCoverage[mappedPath].branchMap) + var branches = _.values(mappedCoverage[fixture.mappedPath].branchMap) var maxBranch = _.max(branches, function (b) { return b.line }) - Math.max(maxBranch.line).should.be.lte(maxLine) + Math.max(maxBranch.line).should.be.lte(fixture.maxLine) }) }) })