diff --git a/test/common/prof.js b/test/common/prof.js new file mode 100644 index 00000000000..3eb288be1b9 --- /dev/null +++ b/test/common/prof.js @@ -0,0 +1,67 @@ +'use strict'; + +const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); + +function getHeapProfiles(dir) { + const list = fs.readdirSync(dir); + return list + .filter((file) => file.endsWith('.heapprofile')) + .map((file) => path.join(dir, file)); +} + +function findFirstFrameInNode(root, func) { + const first = root.children.find( + (child) => child.callFrame.functionName === func + ); + if (first) { + return first; + } + for (const child of root.children) { + const first = findFirstFrameInNode(child, func); + if (first) { + return first; + } + } + return undefined; +} + +function findFirstFrame(file, func) { + const data = fs.readFileSync(file, 'utf8'); + const profile = JSON.parse(data); + const first = findFirstFrameInNode(profile.head, func); + return { frame: first, roots: profile.head.children }; +} + +function verifyFrames(output, file, func) { + const { frame, roots } = findFirstFrame(file, func); + if (!frame) { + // Show native debug output and the profile for debugging. + console.log(output.stderr.toString()); + console.log(roots); + } + assert.notStrictEqual(frame, undefined); +} + +// We need to set --heap-prof-interval to a small enough value to make +// sure we can find our workload in the samples, so we need to set +// TEST_ALLOCATION > kHeapProfInterval. +const kHeapProfInterval = 128; +const TEST_ALLOCATION = kHeapProfInterval * 2; + +const env = { + ...process.env, + TEST_ALLOCATION, + NODE_DEBUG_NATIVE: 'INSPECTOR_PROFILER' +}; + +// TODO(joyeecheung): share the fixutres with v8 coverage tests +module.exports = { + getHeapProfiles, + verifyFrames, + findFirstFrame, + kHeapProfInterval, + TEST_ALLOCATION, + env +}; diff --git a/test/parallel/test-heap-prof-basic.js b/test/parallel/test-heap-prof-basic.js new file mode 100644 index 00000000000..34d8af9a784 --- /dev/null +++ b/test/parallel/test-heap-prof-basic.js @@ -0,0 +1,37 @@ +'use strict'; + +// Tests --heap-prof without --heap-prof-interval. Here we just verify that +// we manage to generate a profile. + +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 { + getHeapProfiles, + env +} = require('../common/prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--heap-prof', + fixtures.path('workload', 'allocation.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + console.log(output); + } + assert.strictEqual(output.status, 0); + const profiles = getHeapProfiles(tmpdir.path); + assert.strictEqual(profiles.length, 1); +} diff --git a/test/parallel/test-heap-prof-dir-absolute.js b/test/parallel/test-heap-prof-dir-absolute.js new file mode 100644 index 00000000000..5fa22470545 --- /dev/null +++ b/test/parallel/test-heap-prof-dir-absolute.js @@ -0,0 +1,47 @@ +'use strict'; + +// This tests that --heap-prof, --heap-prof-dir and --heap-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'); + +const { + getHeapProfiles, + verifyFrames, + kHeapProfInterval, + env +} = require('../common/prof'); + +// Tests absolute --heap-prof-dir +{ + tmpdir.refresh(); + const dir = path.join(tmpdir.path, 'prof'); + const output = spawnSync(process.execPath, [ + '--heap-prof', + '--heap-prof-dir', + dir, + '--heap-prof-interval', + kHeapProfInterval, + fixtures.path('workload', 'allocation.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 = getHeapProfiles(dir); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'runAllocation'); +} diff --git a/test/parallel/test-heap-prof-dir-name.js b/test/parallel/test-heap-prof-dir-name.js new file mode 100644 index 00000000000..ebc93748596 --- /dev/null +++ b/test/parallel/test-heap-prof-dir-name.js @@ -0,0 +1,49 @@ +'use strict'; + +// Tests --heap-prof-dir and --heap-prof-name work 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 { + getHeapProfiles, + verifyFrames, + kHeapProfInterval, + env +} = require('../common/prof'); + +{ + tmpdir.refresh(); + const dir = path.join(tmpdir.path, 'prof'); + const file = path.join(dir, 'test.heapprofile'); + const output = spawnSync(process.execPath, [ + '--heap-prof', + '--heap-prof-name', + 'test.heapprofile', + '--heap-prof-dir', + dir, + '--heap-prof-interval', + kHeapProfInterval, + fixtures.path('workload', 'allocation.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 = getHeapProfiles(dir); + assert.deepStrictEqual(profiles, [file]); + verifyFrames(output, file, 'runAllocation'); +} diff --git a/test/parallel/test-heap-prof-dir-relative.js b/test/parallel/test-heap-prof-dir-relative.js new file mode 100644 index 00000000000..8b71856cde9 --- /dev/null +++ b/test/parallel/test-heap-prof-dir-relative.js @@ -0,0 +1,46 @@ +'use strict'; + +// Tests relative --heap-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 { + getHeapProfiles, + verifyFrames, + kHeapProfInterval, + env +} = require('../common/prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--heap-prof', + '--heap-prof-dir', + 'prof', + '--heap-prof-interval', + kHeapProfInterval, + fixtures.path('workload', 'allocation.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 = getHeapProfiles(dir); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'runAllocation'); +} diff --git a/test/parallel/test-heap-prof-exec-argv.js b/test/parallel/test-heap-prof-exec-argv.js new file mode 100644 index 00000000000..02ad4430dba --- /dev/null +++ b/test/parallel/test-heap-prof-exec-argv.js @@ -0,0 +1,39 @@ +'use strict'; + +// Tests --heap-prof generates a heap 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 { + getHeapProfiles, + verifyFrames, +} = require('../common/prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + fixtures.path('workload', 'allocation-worker-argv.js'), + ], { + cwd: tmpdir.path, + env: { + ...process.env, + HEAP_PROF_INTERVAL: '128' + } + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 0); + const profiles = getHeapProfiles(tmpdir.path); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'runAllocation'); +} diff --git a/test/parallel/test-heap-prof-exit.js b/test/parallel/test-heap-prof-exit.js new file mode 100644 index 00000000000..ed5073c18f4 --- /dev/null +++ b/test/parallel/test-heap-prof-exit.js @@ -0,0 +1,41 @@ +'use strict'; + +// Tests --heap-prof generates a heap profile when process.exit(55) exits +// 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 { + getHeapProfiles, + verifyFrames, + kHeapProfInterval, + env +} = require('../common/prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--heap-prof', + '--heap-prof-interval', + kHeapProfInterval, + fixtures.path('workload', 'allocation-exit.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 55) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 55); + const profiles = getHeapProfiles(tmpdir.path); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'runAllocation'); +} diff --git a/test/parallel/test-heap-prof-interval.js b/test/parallel/test-heap-prof-interval.js new file mode 100644 index 00000000000..18841016a71 --- /dev/null +++ b/test/parallel/test-heap-prof-interval.js @@ -0,0 +1,56 @@ +'use strict'; + +// Tests multiple profiles generated by --heap-prof-interval are valid. + +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 { + getHeapProfiles, + findFirstFrame, + kHeapProfInterval, + env +} = require('../common/prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--heap-prof-interval', + kHeapProfInterval, + '--heap-prof-dir', + 'prof', + '--heap-prof', + fixtures.path('workload', 'allocation-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 = getHeapProfiles(dir); + assert.strictEqual(profiles.length, 2); + const profile1 = findFirstFrame(profiles[0], 'runAllocation'); + const profile2 = findFirstFrame(profiles[1], 'runAllocation'); + if (!profile1.frame && !profile2.frame) { + // Show native debug output and the profile for debugging. + console.log(output.stderr.toString()); + console.log('heap path: ', profiles[0]); + console.log(profile1.roots); + console.log('heap path: ', profiles[1]); + console.log(profile2.roots); + } + assert(profile1.frame || profile2.frame); +} diff --git a/test/parallel/test-heap-prof-invalid-args.js b/test/parallel/test-heap-prof-invalid-args.js new file mode 100644 index 00000000000..e35376038ec --- /dev/null +++ b/test/parallel/test-heap-prof-invalid-args.js @@ -0,0 +1,82 @@ +'use strict'; + +// Tests invalid --heap-prof CLI arguments. + +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 { + kHeapProfInterval, + env +} = require('../common/prof'); + +// Tests --heap-prof-name without --heap-prof. +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--heap-prof-name', + 'test.heapprofile', + fixtures.path('workload', 'allocation.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}: --heap-prof-name must be used with --heap-prof`); +} + +// Tests --heap-prof-dir without --heap-prof. +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--heap-prof-dir', + 'prof', + fixtures.path('workload', 'allocation.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}: --heap-prof-dir must be used with --heap-prof`); +} + +// Tests --heap-prof-interval without --heap-prof. +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--heap-prof-interval', + kHeapProfInterval, + fixtures.path('workload', 'allocation.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}: ` + + '--heap-prof-interval must be used with --heap-prof'); +} diff --git a/test/parallel/test-heap-prof-loop-drained.js b/test/parallel/test-heap-prof-loop-drained.js new file mode 100644 index 00000000000..d0fc4c98784 --- /dev/null +++ b/test/parallel/test-heap-prof-loop-drained.js @@ -0,0 +1,41 @@ +'use strict'; + +// Tests that --heap-prof outputs heap profile when event loop is drained. + +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 { + getHeapProfiles, + verifyFrames, + kHeapProfInterval, + env, +} = require('../common/prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--heap-prof', + '--heap-prof-interval', + kHeapProfInterval, + fixtures.path('workload', 'allocation.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + console.log(output); + } + assert.strictEqual(output.status, 0); + const profiles = getHeapProfiles(tmpdir.path); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'runAllocation'); +} diff --git a/test/parallel/test-heap-prof-name.js b/test/parallel/test-heap-prof-name.js new file mode 100644 index 00000000000..a2bf6aae396 --- /dev/null +++ b/test/parallel/test-heap-prof-name.js @@ -0,0 +1,44 @@ +'use strict'; + +// Tests --heap-prof-name works. + +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 { + getHeapProfiles, + verifyFrames, + kHeapProfInterval, + env +} = require('../common/prof'); + +{ + tmpdir.refresh(); + const file = path.join(tmpdir.path, 'test.heapprofile'); + const output = spawnSync(process.execPath, [ + '--heap-prof', + '--heap-prof-name', + 'test.heapprofile', + '--heap-prof-interval', + kHeapProfInterval, + fixtures.path('workload', 'allocation.js'), + ], { + cwd: tmpdir.path, + env + }); + if (output.status !== 0) { + console.log(output.stderr.toString()); + } + assert.strictEqual(output.status, 0); + const profiles = getHeapProfiles(tmpdir.path); + assert.deepStrictEqual(profiles, [file]); + verifyFrames(output, file, 'runAllocation'); +} diff --git a/test/parallel/test-heap-prof-sigint.js b/test/parallel/test-heap-prof-sigint.js new file mode 100644 index 00000000000..ec078256c2a --- /dev/null +++ b/test/parallel/test-heap-prof-sigint.js @@ -0,0 +1,43 @@ +'use strict'; + +// Tests --heap-prof generates a heap profile when +// process.kill(process.pid, "SIGINT"); exits 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 { + getHeapProfiles, + verifyFrames, + kHeapProfInterval, + env +} = require('../common/prof'); + +{ + tmpdir.refresh(); + const output = spawnSync(process.execPath, [ + '--heap-prof', + '--heap-prof-interval', + kHeapProfInterval, + fixtures.path('workload', 'allocation-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 = getHeapProfiles(tmpdir.path); + assert.strictEqual(profiles.length, 1); + verifyFrames(output, profiles[0], 'runAllocation'); +} diff --git a/test/sequential/test-heap-prof.js b/test/sequential/test-heap-prof.js deleted file mode 100644 index 1dda8f36743..00000000000 --- a/test/sequential/test-heap-prof.js +++ /dev/null @@ -1,375 +0,0 @@ -'use strict'; - -// This tests that --heap-prof, --heap-prof-dir and --heap-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 getHeapProfiles(dir) { - const list = fs.readdirSync(dir); - return list - .filter((file) => file.endsWith('.heapprofile')) - .map((file) => path.join(dir, file)); -} - -function findFirstFrameInNode(root, func) { - const first = root.children.find( - (child) => child.callFrame.functionName === func - ); - if (first) { - return first; - } - for (const child of root.children) { - const first = findFirstFrameInNode(child, func); - if (first) { - return first; - } - } - return undefined; -} - -function findFirstFrame(file, func) { - const data = fs.readFileSync(file, 'utf8'); - const profile = JSON.parse(data); - const first = findFirstFrameInNode(profile.head, func); - return { frame: first, roots: profile.head.children }; -} - -function verifyFrames(output, file, func) { - const { frame, roots } = findFirstFrame(file, func); - if (!frame) { - // Show native debug output and the profile for debugging. - console.log(output.stderr.toString()); - console.log(roots); - } - assert.notStrictEqual(frame, undefined); -} - -// We need to set --heap-prof-interval to a small enough value to make -// sure we can find our workload in the samples, so we need to set -// TEST_ALLOCATION > kHeapProfInterval. -const kHeapProfInterval = 128; -const TEST_ALLOCATION = kHeapProfInterval * 2; - -const env = { - ...process.env, - TEST_ALLOCATION, - NODE_DEBUG_NATIVE: 'INSPECTOR_PROFILER' -}; - -// Test --heap-prof without --heap-prof-interval. Here we just verify that -// we manage to generate a profile. -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--heap-prof', - fixtures.path('workload', 'allocation.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - console.log(output); - } - assert.strictEqual(output.status, 0); - const profiles = getHeapProfiles(tmpdir.path); - assert.strictEqual(profiles.length, 1); -} - -// Outputs heap profile when event loop is drained. -// TODO(joyeecheung): share the fixutres with v8 coverage tests -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--heap-prof', - '--heap-prof-interval', - kHeapProfInterval, - fixtures.path('workload', 'allocation.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - console.log(output); - } - assert.strictEqual(output.status, 0); - const profiles = getHeapProfiles(tmpdir.path); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'runAllocation'); -} - -// Outputs heap profile when process.exit(55) exits process. -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--heap-prof', - '--heap-prof-interval', - kHeapProfInterval, - fixtures.path('workload', 'allocation-exit.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 55) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 55); - const profiles = getHeapProfiles(tmpdir.path); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'runAllocation'); -} - -// Outputs heap profile when process.kill(process.pid, "SIGINT"); exits process. -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--heap-prof', - '--heap-prof-interval', - kHeapProfInterval, - fixtures.path('workload', 'allocation-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 = getHeapProfiles(tmpdir.path); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'runAllocation'); -} - -// Outputs heap profile from worker when execArgv is set. -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - fixtures.path('workload', 'allocation-worker-argv.js'), - ], { - cwd: tmpdir.path, - env: { - ...process.env, - HEAP_PROF_INTERVAL: '128' - } - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 0); - const profiles = getHeapProfiles(tmpdir.path); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'runAllocation'); -} - -// --heap-prof-name without --heap-prof -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--heap-prof-name', - 'test.heapprofile', - fixtures.path('workload', 'allocation.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}: --heap-prof-name must be used with --heap-prof`); -} - -// --heap-prof-dir without --heap-prof -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--heap-prof-dir', - 'prof', - fixtures.path('workload', 'allocation.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}: --heap-prof-dir must be used with --heap-prof`); -} - -// --heap-prof-interval without --heap-prof -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--heap-prof-interval', - kHeapProfInterval, - fixtures.path('workload', 'allocation.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}: ` + - '--heap-prof-interval must be used with --heap-prof'); -} - -// --heap-prof-name -{ - tmpdir.refresh(); - const file = path.join(tmpdir.path, 'test.heapprofile'); - const output = spawnSync(process.execPath, [ - '--heap-prof', - '--heap-prof-name', - 'test.heapprofile', - '--heap-prof-interval', - kHeapProfInterval, - fixtures.path('workload', 'allocation.js'), - ], { - cwd: tmpdir.path, - env - }); - if (output.status !== 0) { - console.log(output.stderr.toString()); - } - assert.strictEqual(output.status, 0); - const profiles = getHeapProfiles(tmpdir.path); - assert.deepStrictEqual(profiles, [file]); - verifyFrames(output, file, 'runAllocation'); -} - -// relative --heap-prof-dir -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--heap-prof', - '--heap-prof-dir', - 'prof', - '--heap-prof-interval', - kHeapProfInterval, - fixtures.path('workload', 'allocation.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 = getHeapProfiles(dir); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'runAllocation'); -} - -// absolute --heap-prof-dir -{ - tmpdir.refresh(); - const dir = path.join(tmpdir.path, 'prof'); - const output = spawnSync(process.execPath, [ - '--heap-prof', - '--heap-prof-dir', - dir, - '--heap-prof-interval', - kHeapProfInterval, - fixtures.path('workload', 'allocation.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 = getHeapProfiles(dir); - assert.strictEqual(profiles.length, 1); - verifyFrames(output, profiles[0], 'runAllocation'); -} - -// --heap-prof-dir and --heap-prof-name -{ - tmpdir.refresh(); - const dir = path.join(tmpdir.path, 'prof'); - const file = path.join(dir, 'test.heapprofile'); - const output = spawnSync(process.execPath, [ - '--heap-prof', - '--heap-prof-name', - 'test.heapprofile', - '--heap-prof-dir', - dir, - '--heap-prof-interval', - kHeapProfInterval, - fixtures.path('workload', 'allocation.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 = getHeapProfiles(dir); - assert.deepStrictEqual(profiles, [file]); - verifyFrames(output, file, 'runAllocation'); -} - -{ - tmpdir.refresh(); - const output = spawnSync(process.execPath, [ - '--heap-prof-interval', - kHeapProfInterval, - '--heap-prof-dir', - 'prof', - '--heap-prof', - fixtures.path('workload', 'allocation-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 = getHeapProfiles(dir); - assert.strictEqual(profiles.length, 2); - const profile1 = findFirstFrame(profiles[0], 'runAllocation'); - const profile2 = findFirstFrame(profiles[1], 'runAllocation'); - if (!profile1.frame && !profile2.frame) { - // Show native debug output and the profile for debugging. - console.log(output.stderr.toString()); - console.log('heap path: ', profiles[0]); - console.log(profile1.roots); - console.log('heap path: ', profiles[1]); - console.log(profile2.roots); - } - assert(profile1.frame || profile2.frame); -}