From 8f98cf5e15db62ce1e156486ecfd79b0534c68b4 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 11 Jun 2019 17:54:07 +0800 Subject: [PATCH] test: split test-cpu-prof.js Split test-cpu-prof.js into multiple files for different test cases so it's easier to find the problematic one if it flakes. Also move the split tests into parallel. PR-URL: https://github.com/nodejs/node/pull/28170 Refs: https://github.com/nodejs/node/issues/27611 Reviewed-By: Gireesh Punathil Reviewed-By: Anna Henningsen Reviewed-By: Yongsheng Zhang Reviewed-By: Colin Ihrig Reviewed-By: Sam Roberts Reviewed-By: Trivikram Kamat --- test/common/cpu-prof.js | 63 +++ test/parallel/test-cpu-prof-default.js | 36 ++ test/parallel/test-cpu-prof-dir-absolute.js | 45 +++ test/parallel/test-cpu-prof-dir-and-name.js | 47 +++ test/parallel/test-cpu-prof-dir-relative.js | 45 +++ test/parallel/test-cpu-prof-dir-worker.js | 55 +++ test/parallel/test-cpu-prof-drained.js | 40 ++ test/parallel/test-cpu-prof-exit.js | 39 ++ .../parallel/test-cpu-prof-invalid-options.js | 79 ++++ test/parallel/test-cpu-prof-kill.js | 41 ++ test/parallel/test-cpu-prof-name.js | 44 +++ test/parallel/test-cpu-prof-worker-argv.js | 38 ++ test/sequential/test-cpu-prof.js | 367 ------------------ 13 files changed, 572 insertions(+), 367 deletions(-) create mode 100644 test/common/cpu-prof.js create mode 100644 test/parallel/test-cpu-prof-default.js create mode 100644 test/parallel/test-cpu-prof-dir-absolute.js create mode 100644 test/parallel/test-cpu-prof-dir-and-name.js create mode 100644 test/parallel/test-cpu-prof-dir-relative.js create mode 100644 test/parallel/test-cpu-prof-dir-worker.js create mode 100644 test/parallel/test-cpu-prof-drained.js create mode 100644 test/parallel/test-cpu-prof-exit.js create mode 100644 test/parallel/test-cpu-prof-invalid-options.js create mode 100644 test/parallel/test-cpu-prof-kill.js create mode 100644 test/parallel/test-cpu-prof-name.js create mode 100644 test/parallel/test-cpu-prof-worker-argv.js delete mode 100644 test/sequential/test-cpu-prof.js diff --git a/test/common/cpu-prof.js b/test/common/cpu-prof.js new file mode 100644 index 00000000000000..78e746082b4990 --- /dev/null +++ b/test/common/cpu-prof.js @@ -0,0 +1,63 @@ +/* eslint-disable node-core/require-common-first, node-core/required-modules */ + +'use strict'; + +const common = require('./'); +const fs = require('fs'); +const path = require('path'); +const assert = require('assert'); + +function getCpuProfiles(dir) { + const list = fs.readdirSync(dir); + return list + .filter((file) => file.endsWith('.cpuprofile')) + .map((file) => path.join(dir, file)); +} + +function getFrames(output, file, suffix) { + const data = fs.readFileSync(file, 'utf8'); + const profile = JSON.parse(data); + const frames = profile.nodes.filter((i) => { + const frame = i.callFrame; + return frame.url.endsWith(suffix); + }); + return { frames, nodes: profile.nodes }; +} + +function verifyFrames(output, file, suffix) { + const { frames, nodes } = getFrames(output, file, suffix); + if (frames.length === 0) { + // Show native debug output and the profile for debugging. + console.log(output.stderr.toString()); + console.log(nodes); + } + assert.notDeepStrictEqual(frames, []); +} + +let FIB = 30; +// This is based on emperial values - in the CI, on Windows the program +// tend to finish too fast then we won't be able to see the profiled script +// in the samples, so we need to bump the values a bit. On slower platforms +// like the Pis it could take more time to complete, we need to use a +// smaller value so the test would not time out. +if (common.isWindows) { + FIB = 40; +} + +// We need to set --cpu-interval to a smaller value to make sure we can +// find our workload in the samples. 50us should be a small enough sampling +// interval for this. +const kCpuProfInterval = 50; +const env = { + ...process.env, + FIB, + NODE_DEBUG_NATIVE: 'INSPECTOR_PROFILER' +}; + +module.exports = { + getCpuProfiles, + kCpuProfInterval, + env, + getFrames, + verifyFrames +}; diff --git a/test/parallel/test-cpu-prof-default.js b/test/parallel/test-cpu-prof-default.js new file mode 100644 index 00000000000000..12c4bc05bb9c3c --- /dev/null +++ b/test/parallel/test-cpu-prof-default.js @@ -0,0 +1,36 @@ +'use strict'; + +// Test --cpu-prof without --cpu-prof-interval. Here we just verify that +// we manage to generate a profile since it's hard to tell whether we +// can sample our target function with the default sampling rate across +// different platforms and machine configurations. + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + getCpuProfiles, + env +} = require('../common/cpu-prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--cpu-prof', + fixtures.path('workload', 'fibonacci.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 0); + const profiles = getCpuProfiles(tmpdir.path); + assert.strictEqual(profiles.length, 1); +} diff --git a/test/parallel/test-cpu-prof-dir-absolute.js b/test/parallel/test-cpu-prof-dir-absolute.js new file mode 100644 index 00000000000000..ad0842dbc4c4fc --- /dev/null +++ b/test/parallel/test-cpu-prof-dir-absolute.js @@ -0,0 +1,45 @@ +'use strict'; + +// This tests that relative --cpu-prof-dir works. + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + getCpuProfiles, + kCpuProfInterval, + env, + verifyFrames +} = require('../common/cpu-prof'); + +// relative --cpu-prof-dir +{ + tmpdir.refresh(); + const dir = path.join(tmpdir.path, 'prof'); + const output = spawnSync(process.execPath, [ + '--cpu-prof', + '--cpu-prof-interval', + kCpuProfInterval, + '--cpu-prof-dir', + dir, + fixtures.path('workload', 'fibonacci.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 0); + assert(fs.existsSync(dir)); + const profiles = getCpuProfiles(dir); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'fibonacci.js'); +} diff --git a/test/parallel/test-cpu-prof-dir-and-name.js b/test/parallel/test-cpu-prof-dir-and-name.js new file mode 100644 index 00000000000000..7ce775ebc16973 --- /dev/null +++ b/test/parallel/test-cpu-prof-dir-and-name.js @@ -0,0 +1,47 @@ +'use strict'; + +// This tests that --cpu-prof-dir and --cpu-prof-name works together. + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + getCpuProfiles, + kCpuProfInterval, + env, + verifyFrames +} = require('../common/cpu-prof'); + +{ + tmpdir.refresh(); + const dir = path.join(tmpdir.path, 'prof'); + const file = path.join(dir, 'test.cpuprofile'); + const output = spawnSync(process.execPath, [ + '--cpu-prof', + '--cpu-prof-interval', + kCpuProfInterval, + '--cpu-prof-name', + 'test.cpuprofile', + '--cpu-prof-dir', + dir, + fixtures.path('workload', 'fibonacci.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 0); + assert(fs.existsSync(dir)); + const profiles = getCpuProfiles(dir); + assert.deepStrictEqual(profiles, [file]); + verifyFrames(output, file, 'fibonacci.js'); +} diff --git a/test/parallel/test-cpu-prof-dir-relative.js b/test/parallel/test-cpu-prof-dir-relative.js new file mode 100644 index 00000000000000..2d679959efdebd --- /dev/null +++ b/test/parallel/test-cpu-prof-dir-relative.js @@ -0,0 +1,45 @@ +'use strict'; + +// This tests that relative --cpu-prof-dir works. + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + getCpuProfiles, + kCpuProfInterval, + env, + verifyFrames +} = require('../common/cpu-prof'); + +// relative --cpu-prof-dir +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--cpu-prof', + '--cpu-prof-interval', + kCpuProfInterval, + '--cpu-prof-dir', + 'prof', + fixtures.path('workload', 'fibonacci.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 0); + const dir = path.join(tmpdir.path, 'prof'); + assert(fs.existsSync(dir)); + const profiles = getCpuProfiles(dir); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'fibonacci.js'); +} diff --git a/test/parallel/test-cpu-prof-dir-worker.js b/test/parallel/test-cpu-prof-dir-worker.js new file mode 100644 index 00000000000000..d382088ca7286b --- /dev/null +++ b/test/parallel/test-cpu-prof-dir-worker.js @@ -0,0 +1,55 @@ +'use strict'; + +// This tests that --cpu-prof-dir works for workers. + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + getCpuProfiles, + kCpuProfInterval, + env, + getFrames +} = require('../common/cpu-prof'); + +// --cpu-prof-dir with worker +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--cpu-prof-interval', + kCpuProfInterval, + '--cpu-prof-dir', + 'prof', + '--cpu-prof', + fixtures.path('workload', 'fibonacci-worker.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 0); + const dir = path.join(tmpdir.path, 'prof'); + assert(fs.existsSync(dir)); + const profiles = getCpuProfiles(dir); + assert.strictEqual(profiles.length, 2); + const profile1 = getFrames(output, profiles[0], 'fibonacci.js'); + const profile2 = getFrames(output, profiles[1], 'fibonacci.js'); + if (profile1.frames.length === 0 && profile2.frames.length === 0) { + // Show native debug output and the profile for debugging. + console.log(output.stderr.toString()); + console.log('CPU path: ', profiles[0]); + console.log(profile1.nodes); + console.log('CPU path: ', profiles[1]); + console.log(profile2.nodes); + } + assert(profile1.frames.length > 0 || profile2.frames.length > 0); +} diff --git a/test/parallel/test-cpu-prof-drained.js b/test/parallel/test-cpu-prof-drained.js new file mode 100644 index 00000000000000..5be4d1a919eec0 --- /dev/null +++ b/test/parallel/test-cpu-prof-drained.js @@ -0,0 +1,40 @@ +'use strict'; + +// This tests that --cpu-prof generates CPU profile when event +// loop is drained. +// TODO(joyeecheung): share the fixtures with v8 coverage tests + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + getCpuProfiles, + kCpuProfInterval, + env, + verifyFrames +} = require('../common/cpu-prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--cpu-prof', + '--cpu-prof-interval', + kCpuProfInterval, + fixtures.path('workload', 'fibonacci.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 0); + const profiles = getCpuProfiles(tmpdir.path); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'fibonacci.js'); +} diff --git a/test/parallel/test-cpu-prof-exit.js b/test/parallel/test-cpu-prof-exit.js new file mode 100644 index 00000000000000..34b1acff4b8f99 --- /dev/null +++ b/test/parallel/test-cpu-prof-exit.js @@ -0,0 +1,39 @@ +'use strict'; + +// This tests that --cpu-prof generates CPU profile when +// process.exit(55) exits the process. + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + getCpuProfiles, + kCpuProfInterval, + env, + verifyFrames +} = require('../common/cpu-prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--cpu-prof', + '--cpu-prof-interval', + kCpuProfInterval, + fixtures.path('workload', 'fibonacci-exit.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 55) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 55); + const profiles = getCpuProfiles(tmpdir.path); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'fibonacci-exit.js'); +} diff --git a/test/parallel/test-cpu-prof-invalid-options.js b/test/parallel/test-cpu-prof-invalid-options.js new file mode 100644 index 00000000000000..b5f7619cdac0d8 --- /dev/null +++ b/test/parallel/test-cpu-prof-invalid-options.js @@ -0,0 +1,79 @@ +'use strict'; + +// This tests that invalid --cpu-prof options are rejected. + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + kCpuProfInterval, + env +} = require('../common/cpu-prof'); + +// --cpu-prof-name without --cpu-prof +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--cpu-prof-name', + 'test.cpuprofile', + fixtures.path('workload', 'fibonacci.js'), + ], { + cwd: tmpdir.path, + env + }); + const stderr = output.stderr.toString().trim(); + if (output.status !== 9) { + console.log(stderr); + } + assert.strictEqual(output.status, 9); + assert.strictEqual( + stderr, + `${process.execPath}: --cpu-prof-name must be used with --cpu-prof`); +} + +// --cpu-prof-dir without --cpu-prof +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--cpu-prof-dir', + 'prof', + fixtures.path('workload', 'fibonacci.js'), + ], { + cwd: tmpdir.path, + env + }); + const stderr = output.stderr.toString().trim(); + if (output.status !== 9) { + console.log(stderr); + } + assert.strictEqual(output.status, 9); + assert.strictEqual( + stderr, + `${process.execPath}: --cpu-prof-dir must be used with --cpu-prof`); +} + +// --cpu-prof-interval without --cpu-prof +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--cpu-prof-interval', + kCpuProfInterval, + fixtures.path('workload', 'fibonacci.js'), + ], { + cwd: tmpdir.path, + env + }); + const stderr = output.stderr.toString().trim(); + if (output.status !== 9) { + console.log(stderr); + } + assert.strictEqual(output.status, 9); + assert.strictEqual( + stderr, + `${process.execPath}: --cpu-prof-interval must be used with --cpu-prof`); +} diff --git a/test/parallel/test-cpu-prof-kill.js b/test/parallel/test-cpu-prof-kill.js new file mode 100644 index 00000000000000..cee66a62569bc8 --- /dev/null +++ b/test/parallel/test-cpu-prof-kill.js @@ -0,0 +1,41 @@ +'use strict'; + +// This tests that --cpu-prof generates CPU profile when +// process.kill(process.pid, "SIGINT"); exits the process. + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + getCpuProfiles, + kCpuProfInterval, + env, + verifyFrames +} = require('../common/cpu-prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--cpu-prof', + '--cpu-prof-interval', + kCpuProfInterval, + fixtures.path('workload', 'fibonacci-sigint.js'), + ], { + cwd: tmpdir.path, + env + }); + if (!common.isWindows) { + if (output.signal !== 'SIGINT') { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.signal, 'SIGINT'); + } + const profiles = getCpuProfiles(tmpdir.path); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'fibonacci-sigint.js'); +} diff --git a/test/parallel/test-cpu-prof-name.js b/test/parallel/test-cpu-prof-name.js new file mode 100644 index 00000000000000..58d9a0ec15862f --- /dev/null +++ b/test/parallel/test-cpu-prof-name.js @@ -0,0 +1,44 @@ +'use strict'; + +// This tests that --cpu-prof-name can be used to specify the +// name of the generated CPU profile. + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const path = require('path'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + getCpuProfiles, + kCpuProfInterval, + env, + verifyFrames +} = require('../common/cpu-prof'); + +// --cpu-prof-name +{ + tmpdir.refresh(); + const file = path.join(tmpdir.path, 'test.cpuprofile'); + const output = spawnSync(process.execPath, [ + '--cpu-prof', + '--cpu-prof-interval', + kCpuProfInterval, + '--cpu-prof-name', + 'test.cpuprofile', + fixtures.path('workload', 'fibonacci.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 0); + const profiles = getCpuProfiles(tmpdir.path); + assert.deepStrictEqual(profiles, [file]); + verifyFrames(output, file, 'fibonacci.js'); +} diff --git a/test/parallel/test-cpu-prof-worker-argv.js b/test/parallel/test-cpu-prof-worker-argv.js new file mode 100644 index 00000000000000..ad88a2eeb08f0d --- /dev/null +++ b/test/parallel/test-cpu-prof-worker-argv.js @@ -0,0 +1,38 @@ +'use strict'; + +// This tests that --cpu-prof generates CPU profile from worker +// when execArgv is set. + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const { spawnSync } = require('child_process'); + +const tmpdir = require('../common/tmpdir'); +const { + getCpuProfiles, + kCpuProfInterval, + verifyFrames +} = require('../common/cpu-prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + fixtures.path('workload', 'fibonacci-worker-argv.js'), + ], { + cwd: tmpdir.path, + env: { + ...process.env, + CPU_PROF_INTERVAL: kCpuProfInterval + } + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 0); + const profiles = getCpuProfiles(tmpdir.path); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'fibonacci.js'); +} diff --git a/test/sequential/test-cpu-prof.js b/test/sequential/test-cpu-prof.js deleted file mode 100644 index 38be6211e4d23f..00000000000000 --- a/test/sequential/test-cpu-prof.js +++ /dev/null @@ -1,367 +0,0 @@ -'use strict'; - -// This tests that --cpu-prof, --cpu-prof-dir and --cpu-prof-name works. - -const common = require('../common'); -const fixtures = require('../common/fixtures'); -common.skipIfInspectorDisabled(); - -const assert = require('assert'); -const fs = require('fs'); -const path = require('path'); -const { spawnSync } = require('child_process'); - -const tmpdir = require('../common/tmpdir'); - -function getCpuProfiles(dir) { - const list = fs.readdirSync(dir); - return list - .filter((file) => file.endsWith('.cpuprofile')) - .map((file) => path.join(dir, file)); -} - -function getFrames(output, file, suffix) { - const data = fs.readFileSync(file, 'utf8'); - const profile = JSON.parse(data); - const frames = profile.nodes.filter((i) => { - const frame = i.callFrame; - return frame.url.endsWith(suffix); - }); - return { frames, nodes: profile.nodes }; -} - -function verifyFrames(output, file, suffix) { - const { frames, nodes } = getFrames(output, file, suffix); - if (frames.length === 0) { - // Show native debug output and the profile for debugging. - console.log(output.stderr.toString()); - console.log(nodes); - } - assert.notDeepStrictEqual(frames, []); -} - -let FIB = 30; -// This is based on emperial values - in the CI, on Windows the program -// tend to finish too fast then we won't be able to see the profiled script -// in the samples, so we need to bump the values a bit. On slower platforms -// like the Pis it could take more time to complete, we need to use a -// smaller value so the test would not time out. -if (common.isWindows) { - FIB = 40; -} - -// We need to set --cpu-interval to a smaller value to make sure we can -// find our workload in the samples. 50us should be a small enough sampling -// interval for this. -const kCpuProfInterval = 50; -const env = { - ...process.env, - FIB, - NODE_DEBUG_NATIVE: 'INSPECTOR_PROFILER' -}; - -// Test --cpu-prof without --cpu-prof-interval. Here we just verify that -// we manage to generate a profile. -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--cpu-prof', - fixtures.path('workload', 'fibonacci.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 0); - const profiles = getCpuProfiles(tmpdir.path); - assert.strictEqual(profiles.length, 1); -} - -// Outputs CPU profile when event loop is drained. -// TODO(joyeecheung): share the fixutres with v8 coverage tests -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--cpu-prof', - '--cpu-prof-interval', - kCpuProfInterval, - fixtures.path('workload', 'fibonacci.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 0); - const profiles = getCpuProfiles(tmpdir.path); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'fibonacci.js'); -} - -// Outputs CPU profile when process.exit(55) exits process. -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--cpu-prof', - '--cpu-prof-interval', - kCpuProfInterval, - fixtures.path('workload', 'fibonacci-exit.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 55) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 55); - const profiles = getCpuProfiles(tmpdir.path); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'fibonacci-exit.js'); -} - -// Outputs CPU profile when process.kill(process.pid, "SIGINT"); exits process. -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--cpu-prof', - '--cpu-prof-interval', - kCpuProfInterval, - fixtures.path('workload', 'fibonacci-sigint.js'), - ], { - cwd: tmpdir.path, - env - }); - if (!common.isWindows) { - if (output.signal !== 'SIGINT') { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.signal, 'SIGINT'); - } - const profiles = getCpuProfiles(tmpdir.path); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'fibonacci-sigint.js'); -} - -// Outputs CPU profile from worker when execArgv is set. -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - fixtures.path('workload', 'fibonacci-worker-argv.js'), - ], { - cwd: tmpdir.path, - env: { - ...process.env, - CPU_PROF_INTERVAL: kCpuProfInterval - } - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 0); - const profiles = getCpuProfiles(tmpdir.path); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'fibonacci.js'); -} - -// --cpu-prof-name without --cpu-prof -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--cpu-prof-name', - 'test.cpuprofile', - fixtures.path('workload', 'fibonacci.js'), - ], { - cwd: tmpdir.path, - env - }); - const stderr = output.stderr.toString().trim(); - if (output.status !== 9) { - console.log(stderr); - } - assert.strictEqual(output.status, 9); - assert.strictEqual( - stderr, - `${process.execPath}: --cpu-prof-name must be used with --cpu-prof`); -} - -// --cpu-prof-dir without --cpu-prof -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--cpu-prof-dir', - 'prof', - fixtures.path('workload', 'fibonacci.js'), - ], { - cwd: tmpdir.path, - env - }); - const stderr = output.stderr.toString().trim(); - if (output.status !== 9) { - console.log(stderr); - } - assert.strictEqual(output.status, 9); - assert.strictEqual( - stderr, - `${process.execPath}: --cpu-prof-dir must be used with --cpu-prof`); -} - -// --cpu-prof-interval without --cpu-prof -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--cpu-prof-interval', - kCpuProfInterval, - fixtures.path('workload', 'fibonacci.js'), - ], { - cwd: tmpdir.path, - env - }); - const stderr = output.stderr.toString().trim(); - if (output.status !== 9) { - console.log(stderr); - } - assert.strictEqual(output.status, 9); - assert.strictEqual( - stderr, - `${process.execPath}: --cpu-prof-interval must be used with --cpu-prof`); -} - -// --cpu-prof-name -{ - tmpdir.refresh(); - const file = path.join(tmpdir.path, 'test.cpuprofile'); - const output = spawnSync(process.execPath, [ - '--cpu-prof', - '--cpu-prof-interval', - kCpuProfInterval, - '--cpu-prof-name', - 'test.cpuprofile', - fixtures.path('workload', 'fibonacci.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 0); - const profiles = getCpuProfiles(tmpdir.path); - assert.deepStrictEqual(profiles, [file]); - verifyFrames(output, file, 'fibonacci.js'); -} - -// relative --cpu-prof-dir -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--cpu-prof', - '--cpu-prof-interval', - kCpuProfInterval, - '--cpu-prof-dir', - 'prof', - fixtures.path('workload', 'fibonacci.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 0); - const dir = path.join(tmpdir.path, 'prof'); - assert(fs.existsSync(dir)); - const profiles = getCpuProfiles(dir); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'fibonacci.js'); -} - -// absolute --cpu-prof-dir -{ - tmpdir.refresh(); - const dir = path.join(tmpdir.path, 'prof'); - const output = spawnSync(process.execPath, [ - '--cpu-prof', - '--cpu-prof-interval', - kCpuProfInterval, - '--cpu-prof-dir', - dir, - fixtures.path('workload', 'fibonacci.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 0); - assert(fs.existsSync(dir)); - const profiles = getCpuProfiles(dir); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'fibonacci.js'); -} - -// --cpu-prof-dir and --cpu-prof-name -{ - tmpdir.refresh(); - const dir = path.join(tmpdir.path, 'prof'); - const file = path.join(dir, 'test.cpuprofile'); - const output = spawnSync(process.execPath, [ - '--cpu-prof', - '--cpu-prof-interval', - kCpuProfInterval, - '--cpu-prof-name', - 'test.cpuprofile', - '--cpu-prof-dir', - dir, - fixtures.path('workload', 'fibonacci.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 0); - assert(fs.existsSync(dir)); - const profiles = getCpuProfiles(dir); - assert.deepStrictEqual(profiles, [file]); - verifyFrames(output, file, 'fibonacci.js'); -} - -// --cpu-prof-dir with worker -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--cpu-prof-interval', - kCpuProfInterval, - '--cpu-prof-dir', - 'prof', - '--cpu-prof', - fixtures.path('workload', 'fibonacci-worker.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 0); - const dir = path.join(tmpdir.path, 'prof'); - assert(fs.existsSync(dir)); - const profiles = getCpuProfiles(dir); - assert.strictEqual(profiles.length, 2); - const profile1 = getFrames(output, profiles[0], 'fibonacci.js'); - const profile2 = getFrames(output, profiles[1], 'fibonacci.js'); - if (profile1.frames.length === 0 && profile2.frames.length === 0) { - // Show native debug output and the profile for debugging. - console.log(output.stderr.toString()); - console.log('CPU path: ', profiles[0]); - console.log(profile1.nodes); - console.log('CPU path: ', profiles[1]); - console.log(profile2.nodes); - } - assert(profile1.frames.length > 0 || profile2.frames.length > 0); -}