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