Skip to content

Commit

Permalink
feat: Add --set-node-options option
Browse files Browse the repository at this point in the history
This completely bypasses spawn-wrap and is enabled by default.
  • Loading branch information
coreyfarrell committed Sep 24, 2019
1 parent 03ba5b9 commit bd148c1
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 50 deletions.
34 changes: 25 additions & 9 deletions bin/nyc.js
Expand Up @@ -4,9 +4,7 @@ const configUtil = require('../lib/config-util')
const foreground = require('foreground-child')
const NYC = require('../index.js')
const processArgs = require('../lib/process-args')

const sw = require('spawn-wrap')
const wrapper = require.resolve('./wrap.js')
const resolveFrom = require('resolve-from')

// parse configuration and command-line arguments;
// we keep these values in a few different forms,
Expand Down Expand Up @@ -34,12 +32,8 @@ if ([
} else {
nyc.createTempDirectory()
}
if (argv.all) nyc.addAllFiles()

var env = {
// Support running nyc as a user without HOME (e.g. linux 'nobody'),
// https://github.com/istanbuljs/nyc/issues/951
SPAWN_WRAP_SHIM_ROOT: process.env.SPAWN_WRAP_SHIM_ROOT || process.env.XDG_CACHE_HOME || require('os').homedir(),
const env = {
NYC_CONFIG: JSON.stringify(argv),
NYC_CWD: process.cwd()
}
Expand All @@ -50,7 +44,29 @@ if ([
env.BABEL_DISABLE_CACHE = process.env.BABEL_DISABLE_CACHE = '1'
}

sw([wrapper], env)
if (argv.setNodeOptions) {
const { preloadAppend, propagateEnv } = require('node-preload')

nyc.require.forEach(requireModule => {
const mod = resolveFrom.silent(nyc.cwd, requireModule) || requireModule
preloadAppend(mod)
require(mod)
})
preloadAppend(require.resolve('../lib/wrap.js'))
Object.assign(propagateEnv, env)
}

if (argv.all) nyc.addAllFiles()

if (!argv.setNodeOptions) {
const wrapper = require.resolve('./wrap.js')
// Support running nyc as a user without HOME (e.g. linux 'nobody'),
// https://github.com/istanbuljs/nyc/issues/951
env.SPAWN_WRAP_SHIM_ROOT = process.env.SPAWN_WRAP_SHIM_ROOT || process.env.XDG_CACHE_HOME || require('os').homedir()
const sw = require('spawn-wrap')

sw([wrapper], env)
}

// Both running the test script invocation and the check-coverage run may
// set process.exitCode. Keep track so that both children are run, but
Expand Down
31 changes: 2 additions & 29 deletions bin/wrap.js
@@ -1,29 +1,2 @@
var sw = require('spawn-wrap')
var NYC = require('../index.js')

var config = {}
if (process.env.NYC_CONFIG) config = JSON.parse(process.env.NYC_CONFIG)
config.isChildProcess = true

config._processInfo = {
pid: process.pid,
ppid: process.ppid,
parent: process.env.NYC_PROCESS_ID || null
}
if (process.env.NYC_PROCESSINFO_EXTERNAL_ID) {
config._processInfo.externalId = process.env.NYC_PROCESSINFO_EXTERNAL_ID
delete process.env.NYC_PROCESSINFO_EXTERNAL_ID
}

if (process.env.NYC_CONFIG_OVERRIDE) {
const override = JSON.parse(process.env.NYC_CONFIG_OVERRIDE)
config = {
...config,
...override
}
process.env.NYC_CONFIG = JSON.stringify(config)
}

;(new NYC(config)).wrap()

sw.runMain()
require('../lib/wrap')
require('spawn-wrap').runMain()
10 changes: 10 additions & 0 deletions index.js
Expand Up @@ -120,6 +120,10 @@ class NYC {
}

_loadAdditionalModules () {
if (this.config.setNodeOptions) {
return
}

this.require.forEach(requireModule => {
// Attempt to require the module relative to the directory being instrumented.
// Then try other locations, e.g. the nyc node_modules folder.
Expand Down Expand Up @@ -334,6 +338,12 @@ class NYC {

wrap (bin) {
process.env.NYC_PROCESS_ID = this.processInfo.uuid
// The else branch is a bug with the spawn-wrap method where
// we cannot force propagation of NYC_PROCESS_ID.
if (this.config.setNodeOptions) {
const { propagateEnv } = require('node-preload')
propagateEnv.NYC_PROCESS_ID = this.processInfo.uuid
}
this._addRequireHooks()
this._wrapExit()
this._loadAdditionalModules()
Expand Down
6 changes: 6 additions & 0 deletions lib/config-util.js
Expand Up @@ -236,6 +236,12 @@ Config.buildYargs = function (cwd) {
type: 'boolean',
global: false
})
.option('set-node-options', {
describe: 'set process.env.NODE_OPTIONS instead of using spawn-wrap',
default: true,
type: 'boolean',
global: false
})
.option('clean', {
describe: 'should the .nyc_output folder be cleaned before executing tests',
default: true,
Expand Down
29 changes: 29 additions & 0 deletions lib/wrap.js
@@ -0,0 +1,29 @@
const NYC = require('../index.js')

let config = {}
if (process.env.NYC_CONFIG) {
config = JSON.parse(process.env.NYC_CONFIG)
}
config.isChildProcess = true

config._processInfo = {
pid: process.pid,
ppid: process.ppid,
parent: process.env.NYC_PROCESS_ID || null
}

if (process.env.NYC_PROCESSINFO_EXTERNAL_ID) {
config._processInfo.externalId = process.env.NYC_PROCESSINFO_EXTERNAL_ID
delete process.env.NYC_PROCESSINFO_EXTERNAL_ID
}

if (process.env.NYC_CONFIG_OVERRIDE) {
const override = JSON.parse(process.env.NYC_CONFIG_OVERRIDE)
config = {
...config,
...override
}
process.env.NYC_CONFIG = JSON.stringify(config)
}

;(new NYC(config)).wrap()
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -85,6 +85,7 @@
"js-yaml": "^3.13.1",
"make-dir": "^3.0.0",
"merge-source-map": "^1.1.0",
"node-preload": "^0.1.2",
"resolve-from": "^5.0.0",
"rimraf": "^3.0.0",
"signal-exit": "^3.0.2",
Expand Down
44 changes: 33 additions & 11 deletions tap-snapshots/test-nyc-integration.js-TAP.test.js
Expand Up @@ -98,7 +98,7 @@ All files | 0 | 0 | 0 | 0 |
external-instrumenter.js | 0 | 0 | 0 | 0 | 1
gc.js | 0 | 100 | 100 | 0 | 2,3
half-covered-failing.js | 0 | 0 | 100 | 0 | 1,3,5,6,7,8
selfspawn-fibonacci.js | 0 | 0 | 0 | 0 | ...19,21,24,25,26,27,28
selfspawn-fibonacci.js | 0 | 0 | 0 | 0 | ...21,23,26,27,28,29,30
skip-full.js | 0 | 100 | 100 | 0 | 1,2
test.js | 0 | 0 | 0 | 0 |
cli/fakebin | 0 | 100 | 100 | 0 |
Expand Down Expand Up @@ -129,8 +129,8 @@ exports[`test/nyc-integration.js TAP --ignore-class-method skips methods that ma
---------------------------------|---------|----------|---------|---------|-------------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------------------------|---------|----------|---------|---------|-------------------------
All files | 1.45 | 0 | 5 | 1.89 |
cli | 2.08 | 0 | 5.56 | 3.13 |
All files | 1.44 | 0 | 5 | 1.87 |
cli | 2.06 | 0 | 5.56 | 3.08 |
args.js | 0 | 100 | 100 | 0 | 1
by-arg2.js | 0 | 0 | 100 | 0 | 1,2,3,4,5,7
classes.js | 66.67 | 100 | 50 | 66.67 | 6
Expand All @@ -143,7 +143,7 @@ All files | 1.45 | 0 | 5 | 1.89 |
gc.js | 0 | 100 | 100 | 0 | 2,3
half-covered-failing.js | 0 | 0 | 100 | 0 | 1,3,5,6,7,8
half-covered.js | 0 | 0 | 100 | 0 | 1,3,5,6,7,8
selfspawn-fibonacci.js | 0 | 0 | 0 | 0 | ...19,21,24,25,26,27,28
selfspawn-fibonacci.js | 0 | 0 | 0 | 0 | ...21,23,26,27,28,29,30
skip-full.js | 0 | 100 | 100 | 0 | 1,2
cli/fakebin | 0 | 100 | 100 | 0 |
npm-template.js | 0 | 100 | 100 | 0 | 2,3,4,7,9
Expand Down Expand Up @@ -182,13 +182,35 @@ All files | 50 | 50 | 100 | 50 |
`

exports[`test/nyc-integration.js TAP --set-node-options=false is functional > stdout 1`] = `
3
------------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------------|---------|----------|---------|---------|-------------------
All files | 91.3 | 70 | 100 | 100 |
selfspawn-fibonacci.js | 91.3 | 70 | 100 | 100 | 6,27,29
------------------------|---------|----------|---------|---------|-------------------
`

exports[`test/nyc-integration.js TAP --set-node-options=true is functional > stdout 1`] = `
3
------------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------------|---------|----------|---------|---------|-------------------
All files | 91.3 | 70 | 100 | 100 |
selfspawn-fibonacci.js | 91.3 | 70 | 100 | 100 | 6,27,29
------------------------|---------|----------|---------|---------|-------------------
`

exports[`test/nyc-integration.js TAP --show-process-tree displays a tree of spawned processes > stdout 1`] = `
3
------------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------------|---------|----------|---------|---------|-------------------
All files | 90.91 | 70 | 100 | 100 |
selfspawn-fibonacci.js | 90.91 | 70 | 100 | 100 | 4,25,27
All files | 91.3 | 70 | 100 | 100 |
selfspawn-fibonacci.js | 91.3 | 70 | 100 | 100 | 6,27,29
------------------------|---------|----------|---------|---------|-------------------
nyc
│ 100 % Lines
Expand All @@ -199,17 +221,17 @@ nyc
│ ├─┬ node ./selfspawn-fibonacci.js 3
│ │ │ 100 % Lines
│ │ ├── node ./selfspawn-fibonacci.js 2
│ │ │ 31.58 % Lines
│ │ │ 35 % Lines
│ │ └── node ./selfspawn-fibonacci.js 1
│ │ 26.32 % Lines
│ │ 30 % Lines
│ └── node ./selfspawn-fibonacci.js 2
31.58 % Lines
35 % Lines
└─┬ node ./selfspawn-fibonacci.js 3
│ 100 % Lines
├── node ./selfspawn-fibonacci.js 2
31.58 % Lines
35 % Lines
└── node ./selfspawn-fibonacci.js 1
26.32 % Lines
30 % Lines
`
Expand Down
7 changes: 6 additions & 1 deletion test/add-all-files.js
Expand Up @@ -65,7 +65,10 @@ t.test('transpiles .js files added via addAllFiles', async t => {
'utf-8'
)

const nyc = new NYC(configUtil.buildYargs(fixtures).parse(['--require', transpileHook]))
const nyc = new NYC(configUtil.buildYargs(fixtures).parse([
'--set-node-options=false',
'--require', transpileHook
]))
nyc.reset()
nyc.addAllFiles()

Expand All @@ -88,6 +91,7 @@ t.test('does not attempt to transpile files when they are excluded', async t =>
)

const nyc = new NYC(configUtil.buildYargs(fixtures).parse([
'--set-node-options=false',
`--require=${transpileHook}`,
'--extension=.do-not-transpile',
'--include=needs-transpile.do-not-transpile'
Expand All @@ -108,6 +112,7 @@ t.test('transpiles non-.js files added via addAllFiles', async t => {
)

const nyc = (new NYC(configUtil.buildYargs(fixtures).parse([
'--set-node-options=false',
`--require=${transpileHook}`,
'--extension=.whatever'
])))
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/cli/selfspawn-fibonacci.js
@@ -1,6 +1,8 @@
'use strict';
var cp = require('child_process');

process.env = {};

var index = +process.argv[2] || 0
if (index <= 1) {
console.log(0)
Expand Down
8 changes: 8 additions & 0 deletions test/nyc-integration.js
Expand Up @@ -186,6 +186,14 @@ t.test('--show-process-tree displays a tree of spawned processes', t => testSucc
args: ['--show-process-tree', process.execPath, 'selfspawn-fibonacci.js', '5']
}))

t.test('--set-node-options=true is functional', t => testSuccess(t, {
args: ['--set-node-options=true', process.execPath, 'selfspawn-fibonacci.js', '5']
}))

t.test('--set-node-options=false is functional', t => testSuccess(t, {
args: ['--set-node-options=false', process.execPath, 'selfspawn-fibonacci.js', '5']
}))

t.test('can run "npm test" which directly invokes a test file', t => testSuccess(t, {
args: ['npm', 'test'],
cwd: path.resolve(fixturesCLI, 'run-npm-test')
Expand Down

0 comments on commit bd148c1

Please sign in to comment.