build: add code coverage to make
PR-URL: https://github.com/nodejs/node/pull/10856 Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
This commit is contained in:
parent
82ddf96828
commit
f8ee197614
67
Makefile
67
Makefile
@ -10,6 +10,7 @@ TEST_CI_ARGS ?=
|
|||||||
STAGINGSERVER ?= node-www
|
STAGINGSERVER ?= node-www
|
||||||
LOGLEVEL ?= silent
|
LOGLEVEL ?= silent
|
||||||
OSTYPE := $(shell uname -s | tr '[A-Z]' '[a-z]')
|
OSTYPE := $(shell uname -s | tr '[A-Z]' '[a-z]')
|
||||||
|
COVTESTS ?= test
|
||||||
|
|
||||||
ifdef JOBS
|
ifdef JOBS
|
||||||
PARALLEL_ARGS = -j $(JOBS)
|
PARALLEL_ARGS = -j $(JOBS)
|
||||||
@ -113,6 +114,69 @@ distclean:
|
|||||||
|
|
||||||
check: test
|
check: test
|
||||||
|
|
||||||
|
# Remove files generated by running coverage, put the non-instrumented lib back
|
||||||
|
# in place
|
||||||
|
coverage-clean:
|
||||||
|
if [ -d lib_ ]; then rm -rf lib; mv lib_ lib; fi
|
||||||
|
-rm -rf node_modules
|
||||||
|
-rm -rf gcovr testing
|
||||||
|
-rm -rf out/$(BUILDTYPE)/.coverage
|
||||||
|
-rm -rf .cov_tmp coverage
|
||||||
|
-rm -f out/$(BUILDTYPE)/obj.target/node/src/*.gcda
|
||||||
|
-rm -f out/$(BUILDTYPE)/obj.target/node/src/tracing/*.gcda
|
||||||
|
-rm -f out/$(BUILDTYPE)/obj.target/node/src/*.gcno
|
||||||
|
-rm -f out/$(BUILDTYPE)/obj.target/node/src/tracing*.gcno
|
||||||
|
|
||||||
|
# Build and test with code coverage reporting. Leave the lib directory
|
||||||
|
# instrumented for any additional runs the user may want to make.
|
||||||
|
# For C++ coverage reporting, this needs to be run in conjunction with configure
|
||||||
|
# --coverage. html coverage reports will be created under coverage/
|
||||||
|
|
||||||
|
coverage: coverage-test
|
||||||
|
|
||||||
|
coverage-build: all
|
||||||
|
mkdir -p node_modules
|
||||||
|
if [ ! -d node_modules/istanbul-merge ]; then \
|
||||||
|
$(NODE) ./deps/npm install istanbul-merge; fi
|
||||||
|
if [ ! -d node_modules/nyc ]; then $(NODE) ./deps/npm install nyc; fi
|
||||||
|
if [ ! -d gcovr ]; then git clone --depth=1 \
|
||||||
|
--single-branch git://github.com/gcovr/gcovr.git; fi
|
||||||
|
if [ ! -d testing ]; then git clone --depth=1 \
|
||||||
|
--single-branch https://github.com/nodejs/testing.git; fi
|
||||||
|
if [ ! -f gcovr/scripts/gcovr.orig ]; then \
|
||||||
|
(cd gcovr && patch -N -p1 < \
|
||||||
|
"$(CURDIR)/testing/coverage/gcovr-patches.diff"); fi
|
||||||
|
if [ -d lib_ ]; then rm -rf lib; mv lib_ lib; fi
|
||||||
|
mv lib lib_
|
||||||
|
$(NODE) ./node_modules/.bin/nyc instrument lib_/ lib/
|
||||||
|
$(MAKE)
|
||||||
|
|
||||||
|
coverage-test: coverage-build
|
||||||
|
-rm -rf out/$(BUILDTYPE)/.coverage
|
||||||
|
-rm -rf .cov_tmp
|
||||||
|
-rm -f out/$(BUILDTYPE)/obj.target/node/src/*.gcda
|
||||||
|
-rm -f out/$(BUILDTYPE)/obj.target/node/src/tracing/*.gcda
|
||||||
|
-$(MAKE) $(COVTESTS)
|
||||||
|
mv lib lib__
|
||||||
|
mv lib_ lib
|
||||||
|
mkdir -p coverage .cov_tmp
|
||||||
|
$(NODE) ./node_modules/.bin/istanbul-merge --out \
|
||||||
|
.cov_tmp/libcov.json 'out/Release/.coverage/coverage-*.json'
|
||||||
|
(cd lib && .$(NODE) ../node_modules/.bin/nyc report \
|
||||||
|
--temp-directory "$(CURDIR)/.cov_tmp" -r html \
|
||||||
|
--report-dir "../coverage")
|
||||||
|
-(cd out && "../gcovr/scripts/gcovr" --gcov-exclude='.*deps' \
|
||||||
|
--gcov-exclude='.*usr' -v -r Release/obj.target/node \
|
||||||
|
--html --html-detail -o ../coverage/cxxcoverage.html)
|
||||||
|
mv lib lib_
|
||||||
|
mv lib__ lib
|
||||||
|
@echo -n "Javascript coverage %: "
|
||||||
|
@grep -B1 Lines coverage/index.html | head -n1 \
|
||||||
|
| sed 's/<[^>]*>//g'| sed 's/ //g'
|
||||||
|
@echo -n "C++ coverage %: "
|
||||||
|
@grep -A3 Lines coverage/cxxcoverage.html | grep style \
|
||||||
|
| sed 's/<[^>]*>//g'| sed 's/ //g'
|
||||||
|
|
||||||
cctest: all
|
cctest: all
|
||||||
@out/$(BUILDTYPE)/$@
|
@out/$(BUILDTYPE)/$@
|
||||||
|
|
||||||
@ -781,4 +845,5 @@ endif
|
|||||||
bench-all bench bench-misc bench-array bench-buffer bench-net \
|
bench-all bench bench-misc bench-array bench-buffer bench-net \
|
||||||
bench-http bench-fs bench-tls cctest run-ci test-v8 test-v8-intl \
|
bench-http bench-fs bench-tls cctest run-ci test-v8 test-v8-intl \
|
||||||
test-v8-benchmarks test-v8-all v8 lint-ci bench-ci jslint-ci doc-only \
|
test-v8-benchmarks test-v8-all v8 lint-ci bench-ci jslint-ci doc-only \
|
||||||
$(TARBALL)-headers test-ci test-ci-native test-ci-js build-ci clear-stalled
|
$(TARBALL)-headers test-ci test-ci-native test-ci-js build-ci clear-stalled \
|
||||||
|
coverage-clean coverage-build coverage-test coverage
|
||||||
|
2
lib/internal/bootstrap_node.js
vendored
2
lib/internal/bootstrap_node.js
vendored
@ -44,6 +44,8 @@
|
|||||||
NativeModule.require('internal/process/stdio').setup();
|
NativeModule.require('internal/process/stdio').setup();
|
||||||
_process.setupKillAndExit();
|
_process.setupKillAndExit();
|
||||||
_process.setupSignalHandlers();
|
_process.setupSignalHandlers();
|
||||||
|
if (global.__coverage__)
|
||||||
|
NativeModule.require('internal/process/write-coverage').setup();
|
||||||
|
|
||||||
// Do not initialize channel in debugger agent, it deletes env variable
|
// Do not initialize channel in debugger agent, it deletes env variable
|
||||||
// and the main thread won't see it.
|
// and the main thread won't see it.
|
||||||
|
46
lib/internal/process/write-coverage.js
Normal file
46
lib/internal/process/write-coverage.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
'use strict';
|
||||||
|
const process = require('process');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
const mkdirSync = fs.mkdirSync;
|
||||||
|
const writeFileSync = fs.writeFileSync;
|
||||||
|
|
||||||
|
var isWritingCoverage = false;
|
||||||
|
function writeCoverage() {
|
||||||
|
if (isWritingCoverage || !global.__coverage__) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isWritingCoverage = true;
|
||||||
|
|
||||||
|
const dirname = path.join(path.dirname(process.execPath), '.coverage');
|
||||||
|
const filename = `coverage-${process.pid}-${Date.now()}.json`;
|
||||||
|
try {
|
||||||
|
mkdirSync(dirname);
|
||||||
|
} catch (err) {
|
||||||
|
if (err.code !== 'EEXIST') {
|
||||||
|
console.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = path.join(dirname, filename);
|
||||||
|
const coverageInfo = JSON.stringify(global.__coverage__);
|
||||||
|
try {
|
||||||
|
writeFileSync(target, coverageInfo);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
const reallyReallyExit = process.reallyExit;
|
||||||
|
|
||||||
|
process.reallyExit = function(code) {
|
||||||
|
writeCoverage();
|
||||||
|
reallyReallyExit(code);
|
||||||
|
};
|
||||||
|
|
||||||
|
process.on('exit', writeCoverage);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.setup = setup;
|
1
node.gyp
1
node.gyp
@ -94,6 +94,7 @@
|
|||||||
'lib/internal/process/warning.js',
|
'lib/internal/process/warning.js',
|
||||||
'lib/internal/process.js',
|
'lib/internal/process.js',
|
||||||
'lib/internal/querystring.js',
|
'lib/internal/querystring.js',
|
||||||
|
'lib/internal/process/write-coverage.js',
|
||||||
'lib/internal/readline.js',
|
'lib/internal/readline.js',
|
||||||
'lib/internal/repl.js',
|
'lib/internal/repl.js',
|
||||||
'lib/internal/socket_list.js',
|
'lib/internal/socket_list.js',
|
||||||
|
@ -287,6 +287,9 @@ exports.platformTimeout = function(ms) {
|
|||||||
if (process.config.target_defaults.default_configuration === 'Debug')
|
if (process.config.target_defaults.default_configuration === 'Debug')
|
||||||
ms = 2 * ms;
|
ms = 2 * ms;
|
||||||
|
|
||||||
|
if (global.__coverage__)
|
||||||
|
ms = 4 * ms;
|
||||||
|
|
||||||
if (exports.isAix)
|
if (exports.isAix)
|
||||||
return 2 * ms; // default localhost speed is slower on AIX
|
return 2 * ms; // default localhost speed is slower on AIX
|
||||||
|
|
||||||
@ -384,7 +387,11 @@ function leakedGlobals() {
|
|||||||
if (!knownGlobals.includes(global[val]))
|
if (!knownGlobals.includes(global[val]))
|
||||||
leaked.push(val);
|
leaked.push(val);
|
||||||
|
|
||||||
return leaked;
|
if (global.__coverage__) {
|
||||||
|
return leaked.filter((varname) => !/^(cov_|__cov)/.test(varname));
|
||||||
|
} else {
|
||||||
|
return leaked;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.leakedGlobals = leakedGlobals;
|
exports.leakedGlobals = leakedGlobals;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user