File: test-watch-mode-inspect.mjs

package info (click to toggle)
nodejs 20.19.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 219,072 kB
  • sloc: cpp: 1,277,408; javascript: 565,332; ansic: 129,476; python: 58,536; sh: 3,841; makefile: 2,725; asm: 1,732; perl: 248; lisp: 222; xml: 42
file content (93 lines) | stat: -rw-r--r-- 3,343 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import * as common from '../common/index.mjs';
import * as fixtures from '../common/fixtures.mjs';
import assert from 'node:assert';
import { describe, it } from 'node:test';
import { writeFileSync, readFileSync } from 'node:fs';
import { setTimeout } from 'node:timers/promises';
import { NodeInstance } from '../common/inspector-helper.js';


if (common.isIBMi)
  common.skip('IBMi does not support `fs.watch()`');

common.skipIfInspectorDisabled();

let gettingDebuggedPid = false;

async function getDebuggedPid(instance, waitForLog = true) {
  gettingDebuggedPid = true;
  const session = await instance.connectInspectorSession();
  await session.send({ method: 'Runtime.enable' });
  if (waitForLog) {
    await session.waitForConsoleOutput('log', 'safe to debug now');
  }
  const { value: innerPid } = (await session.send({
    'method': 'Runtime.evaluate', 'params': { 'expression': 'process.pid' }
  })).result;
  session.disconnect();
  gettingDebuggedPid = false;
  return innerPid;
}

function restart(file) {
  writeFileSync(file, readFileSync(file));
  const interval = setInterval(() => {
    if (!gettingDebuggedPid) {
      writeFileSync(file, readFileSync(file));
    }
  }, common.platformTimeout(500));
  return () => clearInterval(interval);
}

describe('watch mode - inspect', () => {
  it('should start debugger on inner process', async () => {
    const file = fixtures.path('watch-mode/inspect.js');
    const instance = new NodeInstance(['--inspect=0', '--watch'], undefined, file);
    let stderr = '';
    const stdout = [];
    instance.on('stderr', (data) => { stderr += data; });
    instance.on('stdout', (data) => { stdout.push(data); });

    const pids = [instance.pid];
    pids.push(await getDebuggedPid(instance));
    instance.resetPort();
    const stopRestarting = restart(file);
    pids.push(await getDebuggedPid(instance));
    stopRestarting();

    await setTimeout(common.platformTimeout(500));
    await instance.kill();

    // There should be a process per restart and one per parent process.
    // Message about Debugger should appear once per restart.
    // On some systems restart can happen multiple times.
    const restarts = stdout.filter((line) => line === 'safe to debug now').length;
    assert.ok(stderr.match(/Debugger listening on ws:\/\//g).length >= restarts);
    assert.ok(new Set(pids).size >= restarts + 1);
  });

  it('should prevent attaching debugger with SIGUSR1 to outer process', { skip: common.isWindows }, async () => {
    const file = fixtures.path('watch-mode/inspect_with_signal.js');
    const instance = new NodeInstance(['--inspect-port=0', '--watch'], undefined, file);
    let stderr = '';
    instance.on('stderr', (data) => { stderr += data; });

    const loggedPid = await new Promise((resolve) => {
      instance.on('stdout', (data) => {
        const matches = data.match(/pid is (\d+)/);
        if (matches) resolve(Number(matches[1]));
      });
    });


    process.kill(instance.pid, 'SIGUSR1');
    process.kill(loggedPid, 'SIGUSR1');
    const debuggedPid = await getDebuggedPid(instance, false);

    await instance.kill();

    // Message about Debugger should only appear once in inner process.
    assert.strictEqual(stderr.match(/Debugger listening on ws:\/\//g).length, 1);
    assert.strictEqual(loggedPid, debuggedPid);
  });
});