◐ Shell
clean mode source ↗

child_process: add tracing channel for spawn · nodejs/node@b771529

1+

'use strict';

2+

const common = require('../common');

3+

const assert = require('assert');

4+

const { spawn, ChildProcess } = require('child_process');

5+

const dc = require('diagnostics_channel');

6+

const path = require('path');

7+

const fs = require('fs');

8+

const tmpdir = require('../common/tmpdir');

9+10+

const isChildProcess = (process) => process instanceof ChildProcess;

11+12+

function testDiagnosticChannel(subscribers, test, after) {

13+

dc.tracingChannel('child_process.spawn').subscribe(subscribers);

14+15+

test(common.mustCall(() => {

16+

dc.tracingChannel('child_process.spawn').unsubscribe(subscribers);

17+

after?.();

18+

}));

19+

}

20+21+

const testSuccessfulSpawn = common.mustCall(() => {

22+

let cb;

23+24+

testDiagnosticChannel(

25+

{

26+

start: common.mustCall(({ process: childProcess, options }) => {

27+

assert.strictEqual(isChildProcess(childProcess), true);

28+

assert.strictEqual(options.file, process.execPath);

29+

}),

30+

end: common.mustCall(({ process: childProcess }) => {

31+

assert.strictEqual(isChildProcess(childProcess), true);

32+

}),

33+

error: common.mustNotCall(),

34+

},

35+

common.mustCall((callback) => {

36+

cb = callback;

37+

const child = spawn(process.execPath, ['-e', 'process.exit(0)']);

38+

child.on('close', () => {

39+

cb();

40+

});

41+

}),

42+

testFailingSpawnENOENT

43+

);

44+

});

45+46+

const testFailingSpawnENOENT = common.mustCall(() => {

47+

testDiagnosticChannel(

48+

{

49+

start: common.mustCall(({ process: childProcess, options }) => {

50+

assert.strictEqual(isChildProcess(childProcess), true);

51+

assert.strictEqual(options.file, 'does-not-exist');

52+

}),

53+

end: common.mustNotCall(),

54+

error: common.mustCall(({ process: childProcess, error }) => {

55+

assert.strictEqual(isChildProcess(childProcess), true);

56+

assert.strictEqual(error.code, 'ENOENT');

57+

}),

58+

},

59+

common.mustCall((callback) => {

60+

const child = spawn('does-not-exist');

61+

child.on('error', () => {});

62+

callback();

63+

}),

64+

common.isWindows ? undefined : testFailingSpawnEACCES,

65+

);

66+

});

67+68+

const testFailingSpawnEACCES = !common.isWindows ? common.mustCall(() => {

69+

tmpdir.refresh();

70+

const noExecFile = path.join(tmpdir.path, 'no-exec');

71+

fs.writeFileSync(noExecFile, '');

72+

fs.chmodSync(noExecFile, 0o644);

73+74+

testDiagnosticChannel(

75+

{

76+

start: common.mustCall(({ process: childProcess, options }) => {

77+

assert.strictEqual(isChildProcess(childProcess), true);

78+

assert.strictEqual(options.file, noExecFile);

79+

}),

80+

end: common.mustNotCall(),

81+

error: common.mustCall(({ process: childProcess, error }) => {

82+

assert.strictEqual(isChildProcess(childProcess), true);

83+

assert.strictEqual(error.code, 'EACCES');

84+

}),

85+

},

86+

common.mustCall((callback) => {

87+

const child = spawn(noExecFile);

88+

child.on('error', () => {});

89+

callback();

90+

}),

91+

);

92+

}) : undefined;

93+94+

testSuccessfulSpawn();