1'use strict'; 2const common = require('../common'); 3common.skipIfInspectorDisabled(); 4 5// Test inspector open()/close()/url() API. It uses ephemeral ports so can be 6// run safely in parallel. 7 8const assert = require('assert'); 9const fork = require('child_process').fork; 10const net = require('net'); 11const url = require('url'); 12 13const kFirstOpen = 0; 14const kOpenWhileOpen = 1; 15const kReOpen = 2; 16 17if (process.env.BE_CHILD) 18 return beChild(); 19 20const child = fork(__filename, 21 { env: { ...process.env, BE_CHILD: 1 } }); 22 23child.once('message', common.mustCall((msg) => { 24 assert.strictEqual(msg.cmd, 'started'); 25 26 child.send({ cmd: 'open', args: [kFirstOpen] }); 27 child.once('message', common.mustCall(firstOpen)); 28})); 29 30let firstPort; 31 32function firstOpen(msg) { 33 assert.strictEqual(msg.cmd, 'url'); 34 const port = url.parse(msg.url).port; 35 ping(port, common.mustSucceed(() => { 36 // Inspector is already open, and won't be reopened, so args don't matter. 37 child.send({ cmd: 'open', args: [kOpenWhileOpen] }); 38 child.once('message', common.mustCall(tryToOpenWhenOpen)); 39 firstPort = port; 40 })); 41} 42 43function tryToOpenWhenOpen(msg) { 44 assert.strictEqual(msg.cmd, 'url'); 45 const port = url.parse(msg.url).port; 46 // Reopen didn't do anything, the port was already open, and has not changed. 47 assert.strictEqual(port, firstPort); 48 ping(port, common.mustSucceed(() => { 49 child.send({ cmd: 'close' }); 50 child.once('message', common.mustCall(closeWhenOpen)); 51 })); 52} 53 54function closeWhenOpen(msg) { 55 assert.strictEqual(msg.cmd, 'url'); 56 assert.strictEqual(msg.url, undefined); 57 ping(firstPort, (err) => { 58 assert(err); 59 child.send({ cmd: 'close' }); 60 child.once('message', common.mustCall(tryToCloseWhenClosed)); 61 }); 62} 63 64function tryToCloseWhenClosed(msg) { 65 assert.strictEqual(msg.cmd, 'url'); 66 assert.strictEqual(msg.url, undefined); 67 child.send({ cmd: 'open', args: [kReOpen] }); 68 child.once('message', common.mustCall(reopenAfterClose)); 69} 70 71function reopenAfterClose(msg) { 72 assert.strictEqual(msg.cmd, 'url'); 73 const port = url.parse(msg.url).port; 74 ping(port, common.mustSucceed(() => { 75 process.exit(); 76 })); 77} 78 79function ping(port, callback) { 80 net.connect({ port, family: 4 }) 81 .on('connect', function() { close(this); }) 82 .on('error', function(err) { close(this, err); }); 83 84 function close(self, err) { 85 self.end(); 86 self.on('close', () => callback(err)); 87 } 88} 89 90function beChild() { 91 const inspector = require('inspector'); 92 93 process.send({ cmd: 'started' }); 94 95 process.on('message', (msg) => { 96 if (msg.cmd === 'open') { 97 if (msg.args[0] === kFirstOpen) { 98 inspector.open(0, false, undefined); 99 } else if (msg.args[0] === kOpenWhileOpen) { 100 assert.throws(() => { 101 inspector.open(0, false, undefined); 102 }, { 103 code: 'ERR_INSPECTOR_ALREADY_ACTIVATED' 104 }); 105 } else if (msg.args[0] === kReOpen) { 106 inspector.open(0, false, undefined); 107 } 108 } 109 if (msg.cmd === 'close') { 110 inspector.close(); 111 } 112 process.send({ cmd: 'url', url: inspector.url() }); 113 }); 114} 115