• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3const tmpdir = require('../common/tmpdir');
4const fs = require('fs');
5const assert = require('assert');
6const util = require('util');
7const { join } = require('path');
8const { spawnSync } = require('child_process');
9
10// Test that --prof also tracks Worker threads.
11// Refs: https://github.com/nodejs/node/issues/24016
12
13if (process.argv[2] === 'child') {
14  const fs = require('fs');
15  let files = fs.readdirSync(tmpdir.path);
16  const plog = files.filter((name) => /\.log$/.test(name))[0];
17  if (plog === undefined) {
18    console.error('`--prof` did not produce a profile log for parent thread!');
19    process.exit(1);
20  }
21  const pingpong = `
22  let counter = 0;
23  const fs = require('fs');
24  const { Worker, parentPort  } = require('worker_threads');
25  parentPort.on('message', (m) => {
26    if (counter++ === 10)
27      process.exit(0);
28     parentPort.postMessage(
29       fs.readFileSync(m.toString()).slice(0, 1024 * 1024));
30  });
31  `;
32
33  const { Worker } = require('worker_threads');
34  const w = new Worker(pingpong, { eval: true });
35  w.on('message', (m) => {
36    w.postMessage(process.execPath);
37  });
38
39  w.on('exit', common.mustCall(() => {
40    files = fs.readdirSync(tmpdir.path);
41    const wlog = files.filter((name) => /\.log$/.test(name) && name !== plog)[0];
42    if (wlog === undefined) {
43      console.error('`--prof` did not produce a profile log' +
44                    ' for worker thread!');
45      process.exit(1);
46    }
47    process.exit(0);
48  }));
49  w.postMessage(process.execPath);
50} else {
51  tmpdir.refresh();
52  const spawnResult = spawnSync(
53    process.execPath, ['--prof', __filename, 'child'],
54    { cwd: tmpdir.path, encoding: 'utf8', timeout: 30_000 });
55  assert.strictEqual(spawnResult.stderr.toString(), '',
56                     `child exited with an error: \
57                     ${util.inspect(spawnResult)}`);
58  assert.strictEqual(spawnResult.signal, null,
59                     `child exited with signal: ${util.inspect(spawnResult)}`);
60  assert.strictEqual(spawnResult.status, 0,
61                     `child exited with non-zero status: \
62                     ${util.inspect(spawnResult)}`);
63  const files = fs.readdirSync(tmpdir.path);
64  const logfiles = files.filter((name) => /\.log$/.test(name));
65  assert.strictEqual(logfiles.length, 2);  // Parent thread + child thread.
66
67  for (const logfile of logfiles) {
68    const lines = fs.readFileSync(
69      join(tmpdir.path, logfile), 'utf8').split('\n');
70    const ticks = lines.filter((line) => /^tick,/.test(line)).length;
71
72    // Test that at least 15 ticks have been recorded for both parent and child
73    // threads. When not tracking Worker threads, only 1 or 2 ticks would
74    // have been recorded.
75    // When running locally on x64 Linux, this number is usually at least 200
76    // for both threads, so 15 seems like a very safe threshold.
77    assert(ticks >= 15, `${ticks} >= 15`);
78  }
79}
80