1'use strict'; 2 3// Flags: --expose-internals 4 5const common = require('../common'); 6 7common.skipIfInspectorDisabled(); 8 9const assert = require('assert'); 10const cluster = require('cluster'); 11 12const debuggerPort = common.PORT; 13const childProcess = require('child_process'); 14 15let offset = 0; 16 17/* 18 * This test suite checks that inspector port in cluster is incremented 19 * for different execArgv combinations 20 */ 21 22function testRunnerMain() { 23 let defaultPortCase = spawnMaster({ 24 execArgv: ['--inspect'], 25 workers: [{ expectedPort: 9230 }] 26 }); 27 28 spawnMaster({ 29 execArgv: ['--inspect=65534'], 30 workers: [ 31 { expectedPort: 65535 }, 32 { expectedPort: 1024 }, 33 { expectedPort: 1025 }, 34 { expectedPort: 1026 } 35 ] 36 }); 37 38 let port = debuggerPort + offset++ * 5; 39 40 spawnMaster({ 41 execArgv: [`--inspect=${port}`], 42 workers: [ 43 { expectedPort: port + 1 }, 44 { expectedPort: port + 2 }, 45 { expectedPort: port + 3 } 46 ] 47 }); 48 49 port = debuggerPort + offset++ * 5; 50 51 spawnMaster({ 52 execArgv: ['--inspect', `--inspect-port=${port}`], 53 workers: [{ expectedPort: port + 1 }] 54 }); 55 56 port = debuggerPort + offset++ * 5; 57 58 spawnMaster({ 59 execArgv: ['--inspect', `--debug-port=${port}`], 60 workers: [{ expectedPort: port + 1 }] 61 }); 62 63 port = debuggerPort + offset++ * 5; 64 65 spawnMaster({ 66 execArgv: [`--inspect=0.0.0.0:${port}`], 67 workers: [{ expectedPort: port + 1, expectedHost: '0.0.0.0' }] 68 }); 69 70 port = debuggerPort + offset++ * 5; 71 72 spawnMaster({ 73 execArgv: [`--inspect=127.0.0.1:${port}`], 74 workers: [{ expectedPort: port + 1, expectedHost: '127.0.0.1' }] 75 }); 76 77 if (common.hasIPv6) { 78 port = debuggerPort + offset++ * 5; 79 80 spawnMaster({ 81 execArgv: [`--inspect=[::]:${port}`], 82 workers: [{ expectedPort: port + 1, expectedHost: '::' }] 83 }); 84 85 port = debuggerPort + offset++ * 5; 86 87 spawnMaster({ 88 execArgv: [`--inspect=[::1]:${port}`], 89 workers: [{ expectedPort: port + 1, expectedHost: '::1' }] 90 }); 91 } 92 93 // These tests check that setting inspectPort in cluster.settings 94 // would take effect and override port incrementing behavior 95 96 port = debuggerPort + offset++ * 5; 97 98 spawnMaster({ 99 execArgv: [`--inspect=${port}`], 100 clusterSettings: { inspectPort: port + 2 }, 101 workers: [{ expectedPort: port + 2 }] 102 }); 103 104 port = debuggerPort + offset++ * 5; 105 106 spawnMaster({ 107 execArgv: [`--inspect=${port}`], 108 clusterSettings: { inspectPort: 'addTwo' }, 109 workers: [ 110 { expectedPort: port + 2 }, 111 { expectedPort: port + 4 } 112 ] 113 }); 114 115 port = debuggerPort + offset++ * 5; 116 117 spawnMaster({ 118 execArgv: [`--inspect=${port}`], 119 clusterSettings: { inspectPort: 'string' }, 120 workers: [{}] 121 }); 122 123 port = debuggerPort + offset++ * 5; 124 125 spawnMaster({ 126 execArgv: [`--inspect=${port}`], 127 clusterSettings: { inspectPort: 'null' }, 128 workers: [{}] 129 }); 130 131 port = debuggerPort + offset++ * 5; 132 133 spawnMaster({ 134 execArgv: [`--inspect=${port}`], 135 clusterSettings: { inspectPort: 'bignumber' }, 136 workers: [{}] 137 }); 138 139 port = debuggerPort + offset++ * 5; 140 141 spawnMaster({ 142 execArgv: [`--inspect=${port}`], 143 clusterSettings: { inspectPort: 'negativenumber' }, 144 workers: [{}] 145 }); 146 147 port = debuggerPort + offset++ * 5; 148 149 spawnMaster({ 150 execArgv: [`--inspect=${port}`], 151 clusterSettings: { inspectPort: 'bignumberfunc' }, 152 workers: [{}] 153 }); 154 155 port = debuggerPort + offset++ * 5; 156 157 spawnMaster({ 158 execArgv: [`--inspect=${port}`], 159 clusterSettings: { inspectPort: 'strfunc' }, 160 workers: [{}] 161 }); 162 163 port = debuggerPort + offset++ * 5; 164 165 spawnMaster({ 166 execArgv: [], 167 clusterSettings: { inspectPort: port, execArgv: ['--inspect'] }, 168 workers: [ 169 { expectedPort: port } 170 ] 171 }); 172 173 port = debuggerPort + offset++ * 5; 174 175 spawnMaster({ 176 execArgv: [`--inspect=${port}`], 177 clusterSettings: { inspectPort: 0 }, 178 workers: [ 179 { expectedInitialPort: 0 }, 180 { expectedInitialPort: 0 }, 181 { expectedInitialPort: 0 } 182 ] 183 }); 184 185 port = debuggerPort + offset++ * 5; 186 187 spawnMaster({ 188 execArgv: [], 189 clusterSettings: { inspectPort: 0 }, 190 workers: [ 191 { expectedInitialPort: 0 }, 192 { expectedInitialPort: 0 }, 193 { expectedInitialPort: 0 } 194 ] 195 }); 196 197 defaultPortCase.then(() => { 198 port = debuggerPort + offset++ * 5; 199 defaultPortCase = spawnMaster({ 200 execArgv: ['--inspect'], 201 clusterSettings: { inspectPort: port + 2 }, 202 workers: [ 203 { expectedInitialPort: port + 2 } 204 ] 205 }); 206 }); 207} 208 209function masterProcessMain() { 210 const workers = JSON.parse(process.env.workers); 211 const clusterSettings = JSON.parse(process.env.clusterSettings) || {}; 212 const badPortError = { name: 'RangeError', code: 'ERR_SOCKET_BAD_PORT' }; 213 let debugPort = process.debugPort; 214 215 for (const worker of workers) { 216 const params = {}; 217 218 if (worker.expectedPort) { 219 params.expectedPort = worker.expectedPort; 220 } 221 222 if (worker.expectedInitialPort) { 223 params.expectedInitialPort = worker.expectedInitialPort; 224 } 225 226 if (worker.expectedHost) { 227 params.expectedHost = worker.expectedHost; 228 } 229 230 clusterSettings.execArgv = clusterSettings.execArgv ? 231 clusterSettings.execArgv.concat(['--expose-internals']) : 232 process.execArgv.concat(['--expose-internals']); 233 234 if (clusterSettings.inspectPort === 'addTwo') { 235 clusterSettings.inspectPort = common.mustCall( 236 () => { return debugPort += 2; }, 237 workers.length 238 ); 239 } else if (clusterSettings.inspectPort === 'string') { 240 clusterSettings.inspectPort = 'string'; 241 cluster.setupMaster(clusterSettings); 242 243 assert.throws(() => { 244 cluster.fork(params).on('exit', common.mustCall(checkExitCode)); 245 }, badPortError); 246 247 return; 248 } else if (clusterSettings.inspectPort === 'null') { 249 clusterSettings.inspectPort = null; 250 cluster.setupMaster(clusterSettings); 251 252 assert.throws(() => { 253 cluster.fork(params).on('exit', common.mustCall(checkExitCode)); 254 }, badPortError); 255 256 return; 257 } else if (clusterSettings.inspectPort === 'bignumber') { 258 clusterSettings.inspectPort = 1293812; 259 cluster.setupMaster(clusterSettings); 260 261 assert.throws(() => { 262 cluster.fork(params).on('exit', common.mustCall(checkExitCode)); 263 }, badPortError); 264 265 return; 266 } else if (clusterSettings.inspectPort === 'negativenumber') { 267 clusterSettings.inspectPort = -9776; 268 cluster.setupMaster(clusterSettings); 269 270 assert.throws(() => { 271 cluster.fork(params).on('exit', common.mustCall(checkExitCode)); 272 }, badPortError); 273 274 return; 275 } else if (clusterSettings.inspectPort === 'bignumberfunc') { 276 clusterSettings.inspectPort = common.mustCall( 277 () => 123121, 278 workers.length 279 ); 280 281 cluster.setupMaster(clusterSettings); 282 283 assert.throws(() => { 284 cluster.fork(params).on('exit', common.mustCall(checkExitCode)); 285 }, badPortError); 286 287 return; 288 } else if (clusterSettings.inspectPort === 'strfunc') { 289 clusterSettings.inspectPort = common.mustCall( 290 () => 'invalidPort', 291 workers.length 292 ); 293 294 cluster.setupMaster(clusterSettings); 295 296 assert.throws(() => { 297 cluster.fork(params).on('exit', common.mustCall(checkExitCode)); 298 }, badPortError); 299 300 return; 301 } 302 303 cluster.setupMaster(clusterSettings); 304 305 cluster.fork(params).on('exit', common.mustCall(checkExitCode)); 306 } 307} 308 309function workerProcessMain() { 310 const { expectedPort, expectedInitialPort, expectedHost } = process.env; 311 const debugOptions = 312 require('internal/options').getOptionValue('--inspect-port'); 313 314 if ('expectedPort' in process.env) { 315 assert.strictEqual(process.debugPort, +expectedPort); 316 } 317 318 if ('expectedInitialPort' in process.env) { 319 assert.strictEqual(debugOptions.port, +expectedInitialPort); 320 } 321 322 if ('expectedHost' in process.env) { 323 assert.strictEqual(debugOptions.host, expectedHost); 324 } 325 326 process.exit(); 327} 328 329function spawnMaster({ execArgv, workers, clusterSettings = {} }) { 330 return new Promise((resolve) => { 331 childProcess.fork(__filename, { 332 env: { ...process.env, 333 workers: JSON.stringify(workers), 334 clusterSettings: JSON.stringify(clusterSettings), 335 testProcess: true 336 }, 337 execArgv: execArgv.concat(['--expose-internals']) 338 }).on('exit', common.mustCall((code, signal) => { 339 checkExitCode(code, signal); 340 resolve(); 341 })); 342 }); 343} 344 345function checkExitCode(code, signal) { 346 assert.strictEqual(code, 0); 347 assert.strictEqual(signal, null); 348} 349 350if (!process.env.testProcess) { 351 testRunnerMain(); 352} else if (cluster.isMaster) { 353 masterProcessMain(); 354} else { 355 workerProcessMain(); 356} 357