Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | 'use strict'; |
michael@0 | 6 | |
michael@0 | 7 | const { spawn, exec, execFile, fork } = require('sdk/system/child_process'); |
michael@0 | 8 | const { env, platform, pathFor } = require('sdk/system'); |
michael@0 | 9 | const { isNumber } = require('sdk/lang/type'); |
michael@0 | 10 | const { after } = require('sdk/test/utils'); |
michael@0 | 11 | const { emit } = require('sdk/event/core'); |
michael@0 | 12 | const PROFILE_DIR= pathFor('ProfD'); |
michael@0 | 13 | const isWindows = platform.toLowerCase().indexOf('win') === 0; |
michael@0 | 14 | const { getScript, cleanUp } = require('./fixtures/child-process-scripts'); |
michael@0 | 15 | |
michael@0 | 16 | // We use direct paths to these utilities as we currently cannot |
michael@0 | 17 | // call non-absolute paths to utilities in subprocess.jsm |
michael@0 | 18 | const CAT_PATH = isWindows ? 'C:\\Windows\\System32\\more.com' : '/bin/cat'; |
michael@0 | 19 | |
michael@0 | 20 | exports.testExecCallbackSuccess = function (assert, done) { |
michael@0 | 21 | exec(isWindows ? 'DIR /A-D' : 'ls -al', { |
michael@0 | 22 | cwd: PROFILE_DIR |
michael@0 | 23 | }, function (err, stdout, stderr) { |
michael@0 | 24 | assert.ok(!err, 'no errors found'); |
michael@0 | 25 | assert.equal(stderr, '', 'stderr is empty'); |
michael@0 | 26 | assert.ok(/extensions\.ini/.test(stdout), 'stdout output of `ls -al` finds files'); |
michael@0 | 27 | |
michael@0 | 28 | if (isWindows) { |
michael@0 | 29 | // `DIR /A-D` does not display directories on WIN |
michael@0 | 30 | assert.ok(!/<DIR>/.test(stdout), |
michael@0 | 31 | 'passing arguments in `exec` works'); |
michael@0 | 32 | } |
michael@0 | 33 | else { |
michael@0 | 34 | // `ls -al` should list all the priviledge information on Unix |
michael@0 | 35 | assert.ok(/d(r[-|w][-|x]){3}/.test(stdout), |
michael@0 | 36 | 'passing arguments in `exec` works'); |
michael@0 | 37 | } |
michael@0 | 38 | done(); |
michael@0 | 39 | }); |
michael@0 | 40 | }; |
michael@0 | 41 | |
michael@0 | 42 | exports.testExecCallbackError = function (assert, done) { |
michael@0 | 43 | exec('not-real-command', { cwd: PROFILE_DIR }, function (err, stdout, stderr) { |
michael@0 | 44 | assert.ok(/not-real-command/.test(err.toString()), |
michael@0 | 45 | 'error contains error message'); |
michael@0 | 46 | assert.ok(err.lineNumber >= 0, 'error contains lineNumber'); |
michael@0 | 47 | assert.ok(/resource:\/\//.test(err.fileName), 'error contains fileName'); |
michael@0 | 48 | assert.ok(err.code && isNumber(err.code), 'non-zero error code property on error'); |
michael@0 | 49 | assert.equal(err.signal, null, |
michael@0 | 50 | 'null signal property when not manually terminated'); |
michael@0 | 51 | assert.equal(stdout, '', 'stdout is empty'); |
michael@0 | 52 | assert.ok(/not-real-command/.test(stderr), 'stderr contains error message'); |
michael@0 | 53 | done(); |
michael@0 | 54 | }); |
michael@0 | 55 | }; |
michael@0 | 56 | |
michael@0 | 57 | exports.testExecOptionsEnvironment = function (assert, done) { |
michael@0 | 58 | getScript('check-env').then(envScript => { |
michael@0 | 59 | exec(envScript, { |
michael@0 | 60 | cwd: PROFILE_DIR, |
michael@0 | 61 | env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' } |
michael@0 | 62 | }, function (err, stdout, stderr) { |
michael@0 | 63 | assert.equal(stderr, '', 'stderr is empty'); |
michael@0 | 64 | assert.ok(!err, 'received `cwd` option'); |
michael@0 | 65 | assert.ok(/my-value-test/.test(stdout), |
michael@0 | 66 | 'receives environment option'); |
michael@0 | 67 | done(); |
michael@0 | 68 | }); |
michael@0 | 69 | }); |
michael@0 | 70 | }; |
michael@0 | 71 | |
michael@0 | 72 | exports.testExecOptionsTimeout = function (assert, done) { |
michael@0 | 73 | let count = 0; |
michael@0 | 74 | getScript('wait').then(script => { |
michael@0 | 75 | let child = exec(script, { timeout: 100 }, (err, stdout, stderr) => { |
michael@0 | 76 | assert.equal(err.killed, true, 'error has `killed` property as true'); |
michael@0 | 77 | assert.equal(err.code, null, 'error has `code` as null'); |
michael@0 | 78 | assert.equal(err.signal, 'SIGTERM', |
michael@0 | 79 | 'error has `signal` as SIGTERM by default'); |
michael@0 | 80 | assert.equal(stdout, '', 'stdout is empty'); |
michael@0 | 81 | assert.equal(stderr, '', 'stderr is empty'); |
michael@0 | 82 | if (++count === 3) complete(); |
michael@0 | 83 | }); |
michael@0 | 84 | |
michael@0 | 85 | function exitHandler (code, signal) { |
michael@0 | 86 | assert.equal(code, null, 'error has `code` as null'); |
michael@0 | 87 | assert.equal(signal, 'SIGTERM', |
michael@0 | 88 | 'error has `signal` as SIGTERM by default'); |
michael@0 | 89 | if (++count === 3) complete(); |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | function closeHandler (code, signal) { |
michael@0 | 93 | assert.equal(code, null, 'error has `code` as null'); |
michael@0 | 94 | assert.equal(signal, 'SIGTERM', |
michael@0 | 95 | 'error has `signal` as SIGTERM by default'); |
michael@0 | 96 | if (++count === 3) complete(); |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | child.on('exit', exitHandler); |
michael@0 | 100 | child.on('close', closeHandler); |
michael@0 | 101 | |
michael@0 | 102 | function complete () { |
michael@0 | 103 | child.off('exit', exitHandler); |
michael@0 | 104 | child.off('close', closeHandler); |
michael@0 | 105 | done(); |
michael@0 | 106 | } |
michael@0 | 107 | }); |
michael@0 | 108 | }; |
michael@0 | 109 | |
michael@0 | 110 | exports.testExecFileCallbackSuccess = function (assert, done) { |
michael@0 | 111 | getScript('args').then(script => { |
michael@0 | 112 | execFile(script, ['--myargs', '-j', '-s'], { cwd: PROFILE_DIR }, function (err, stdout, stderr) { |
michael@0 | 113 | assert.ok(!err, 'no errors found'); |
michael@0 | 114 | assert.equal(stderr, '', 'stderr is empty'); |
michael@0 | 115 | // Trim output since different systems have different new line output |
michael@0 | 116 | assert.equal(stdout.trim(), '--myargs -j -s'.trim(), 'passes in correct arguments'); |
michael@0 | 117 | done(); |
michael@0 | 118 | }); |
michael@0 | 119 | }); |
michael@0 | 120 | }; |
michael@0 | 121 | |
michael@0 | 122 | exports.testExecFileCallbackError = function (assert, done) { |
michael@0 | 123 | execFile('not-real-command', { cwd: PROFILE_DIR }, function (err, stdout, stderr) { |
michael@0 | 124 | assert.ok(/NS_ERROR_FILE_UNRECOGNIZED_PATH/.test(err.message), |
michael@0 | 125 | 'error contains error message'); |
michael@0 | 126 | assert.ok(err.lineNumber >= 0, 'error contains lineNumber'); |
michael@0 | 127 | assert.ok(/resource:\/\//.test(err.fileName), 'error contains fileName'); |
michael@0 | 128 | assert.equal(stdout, '', 'stdout is empty'); |
michael@0 | 129 | assert.equal(stderr, '', 'stdout is empty'); |
michael@0 | 130 | done(); |
michael@0 | 131 | }); |
michael@0 | 132 | }; |
michael@0 | 133 | |
michael@0 | 134 | exports.testExecFileOptionsEnvironment = function (assert, done) { |
michael@0 | 135 | getScript('check-env').then(script => { |
michael@0 | 136 | execFile(script, { |
michael@0 | 137 | cwd: PROFILE_DIR, |
michael@0 | 138 | env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' } |
michael@0 | 139 | }, function (err, stdout, stderr) { |
michael@0 | 140 | assert.equal(stderr, '', 'stderr is empty'); |
michael@0 | 141 | assert.ok(!err, 'received `cwd` option'); |
michael@0 | 142 | assert.ok(/my-value-test/.test(stdout), |
michael@0 | 143 | 'receives environment option'); |
michael@0 | 144 | done(); |
michael@0 | 145 | }); |
michael@0 | 146 | }); |
michael@0 | 147 | }; |
michael@0 | 148 | |
michael@0 | 149 | exports.testExecFileOptionsTimeout = function (assert, done) { |
michael@0 | 150 | let count = 0; |
michael@0 | 151 | getScript('wait').then(script => { |
michael@0 | 152 | let child = execFile(script, { timeout: 100 }, (err, stdout, stderr) => { |
michael@0 | 153 | assert.equal(err.killed, true, 'error has `killed` property as true'); |
michael@0 | 154 | assert.equal(err.code, null, 'error has `code` as null'); |
michael@0 | 155 | assert.equal(err.signal, 'SIGTERM', |
michael@0 | 156 | 'error has `signal` as SIGTERM by default'); |
michael@0 | 157 | assert.equal(stdout, '', 'stdout is empty'); |
michael@0 | 158 | assert.equal(stderr, '', 'stderr is empty'); |
michael@0 | 159 | if (++count === 3) complete(); |
michael@0 | 160 | }); |
michael@0 | 161 | |
michael@0 | 162 | function exitHandler (code, signal) { |
michael@0 | 163 | assert.equal(code, null, 'error has `code` as null'); |
michael@0 | 164 | assert.equal(signal, 'SIGTERM', |
michael@0 | 165 | 'error has `signal` as SIGTERM by default'); |
michael@0 | 166 | if (++count === 3) complete(); |
michael@0 | 167 | } |
michael@0 | 168 | |
michael@0 | 169 | function closeHandler (code, signal) { |
michael@0 | 170 | assert.equal(code, null, 'error has `code` as null'); |
michael@0 | 171 | assert.equal(signal, 'SIGTERM', |
michael@0 | 172 | 'error has `signal` as SIGTERM by default'); |
michael@0 | 173 | if (++count === 3) complete(); |
michael@0 | 174 | } |
michael@0 | 175 | |
michael@0 | 176 | child.on('exit', exitHandler); |
michael@0 | 177 | child.on('close', closeHandler); |
michael@0 | 178 | |
michael@0 | 179 | function complete () { |
michael@0 | 180 | child.off('exit', exitHandler); |
michael@0 | 181 | child.off('close', closeHandler); |
michael@0 | 182 | done(); |
michael@0 | 183 | } |
michael@0 | 184 | }); |
michael@0 | 185 | }; |
michael@0 | 186 | |
michael@0 | 187 | /** |
michael@0 | 188 | * Not necessary to test for both `exec` and `execFile`, but |
michael@0 | 189 | * it is necessary to test both when the buffer is larger |
michael@0 | 190 | * and smaller than buffer size used by the subprocess library (1024) |
michael@0 | 191 | */ |
michael@0 | 192 | exports.testExecFileOptionsMaxBufferLargeStdOut = function (assert, done) { |
michael@0 | 193 | let count = 0; |
michael@0 | 194 | let stdoutChild; |
michael@0 | 195 | |
michael@0 | 196 | // Creates a buffer of 2000 to stdout, greater than 1024 |
michael@0 | 197 | getScript('large-out').then(script => { |
michael@0 | 198 | stdoutChild = execFile(script, ['10000'], { maxBuffer: 50 }, (err, stdout, stderr) => { |
michael@0 | 199 | assert.ok(/stdout maxBuffer exceeded/.test(err.toString()), |
michael@0 | 200 | 'error contains stdout maxBuffer exceeded message'); |
michael@0 | 201 | assert.ok(stdout.length >= 50, 'stdout has full buffer'); |
michael@0 | 202 | assert.equal(stderr, '', 'stderr is empty'); |
michael@0 | 203 | if (++count === 3) complete(); |
michael@0 | 204 | }); |
michael@0 | 205 | stdoutChild.on('exit', exitHandler); |
michael@0 | 206 | stdoutChild.on('close', closeHandler); |
michael@0 | 207 | }); |
michael@0 | 208 | |
michael@0 | 209 | function exitHandler (code, signal) { |
michael@0 | 210 | assert.equal(code, null, 'Exit code is null in exit handler'); |
michael@0 | 211 | assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler'); |
michael@0 | 212 | if (++count === 3) complete(); |
michael@0 | 213 | } |
michael@0 | 214 | |
michael@0 | 215 | function closeHandler (code, signal) { |
michael@0 | 216 | assert.equal(code, null, 'Exit code is null in close handler'); |
michael@0 | 217 | assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in close handler'); |
michael@0 | 218 | if (++count === 3) complete(); |
michael@0 | 219 | } |
michael@0 | 220 | |
michael@0 | 221 | function complete () { |
michael@0 | 222 | stdoutChild.off('exit', exitHandler); |
michael@0 | 223 | stdoutChild.off('close', closeHandler); |
michael@0 | 224 | done(); |
michael@0 | 225 | } |
michael@0 | 226 | }; |
michael@0 | 227 | |
michael@0 | 228 | exports.testExecFileOptionsMaxBufferLargeStdOErr = function (assert, done) { |
michael@0 | 229 | let count = 0; |
michael@0 | 230 | let stderrChild; |
michael@0 | 231 | // Creates a buffer of 2000 to stderr, greater than 1024 |
michael@0 | 232 | getScript('large-err').then(script => { |
michael@0 | 233 | stderrChild = execFile(script, ['10000'], { maxBuffer: 50 }, (err, stdout, stderr) => { |
michael@0 | 234 | assert.ok(/stderr maxBuffer exceeded/.test(err.toString()), |
michael@0 | 235 | 'error contains stderr maxBuffer exceeded message'); |
michael@0 | 236 | assert.ok(stderr.length >= 50, 'stderr has full buffer'); |
michael@0 | 237 | assert.equal(stdout, '', 'stdout is empty'); |
michael@0 | 238 | if (++count === 3) complete(); |
michael@0 | 239 | }); |
michael@0 | 240 | stderrChild.on('exit', exitHandler); |
michael@0 | 241 | stderrChild.on('close', closeHandler); |
michael@0 | 242 | }); |
michael@0 | 243 | |
michael@0 | 244 | function exitHandler (code, signal) { |
michael@0 | 245 | assert.equal(code, null, 'Exit code is null in exit handler'); |
michael@0 | 246 | assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler'); |
michael@0 | 247 | if (++count === 3) complete(); |
michael@0 | 248 | } |
michael@0 | 249 | |
michael@0 | 250 | function closeHandler (code, signal) { |
michael@0 | 251 | assert.equal(code, null, 'Exit code is null in close handler'); |
michael@0 | 252 | assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in close handler'); |
michael@0 | 253 | if (++count === 3) complete(); |
michael@0 | 254 | } |
michael@0 | 255 | |
michael@0 | 256 | function complete () { |
michael@0 | 257 | stderrChild.off('exit', exitHandler); |
michael@0 | 258 | stderrChild.off('close', closeHandler); |
michael@0 | 259 | done(); |
michael@0 | 260 | } |
michael@0 | 261 | }; |
michael@0 | 262 | |
michael@0 | 263 | /** |
michael@0 | 264 | * When total buffer is < process buffer (1024), the process will exit |
michael@0 | 265 | * and not get a chance to be killed for violating the maxBuffer, |
michael@0 | 266 | * although the error will still be sent through (node behaviour) |
michael@0 | 267 | */ |
michael@0 | 268 | exports.testExecFileOptionsMaxBufferSmallStdOut = function (assert, done) { |
michael@0 | 269 | let count = 0; |
michael@0 | 270 | let stdoutChild; |
michael@0 | 271 | |
michael@0 | 272 | // Creates a buffer of 60 to stdout, less than 1024 |
michael@0 | 273 | getScript('large-out').then(script => { |
michael@0 | 274 | stdoutChild = execFile(script, ['60'], { maxBuffer: 50 }, (err, stdout, stderr) => { |
michael@0 | 275 | assert.ok(/stdout maxBuffer exceeded/.test(err.toString()), |
michael@0 | 276 | 'error contains stdout maxBuffer exceeded message'); |
michael@0 | 277 | assert.ok(stdout.length >= 50, 'stdout has full buffer'); |
michael@0 | 278 | assert.equal(stderr, '', 'stderr is empty'); |
michael@0 | 279 | if (++count === 3) complete(); |
michael@0 | 280 | }); |
michael@0 | 281 | stdoutChild.on('exit', exitHandler); |
michael@0 | 282 | stdoutChild.on('close', closeHandler); |
michael@0 | 283 | }); |
michael@0 | 284 | |
michael@0 | 285 | function exitHandler (code, signal) { |
michael@0 | 286 | // Sometimes the buffer limit is hit before the process closes successfully |
michael@0 | 287 | // on both OSX/Windows |
michael@0 | 288 | if (code === null) { |
michael@0 | 289 | assert.equal(code, null, 'Exit code is null in exit handler'); |
michael@0 | 290 | assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler'); |
michael@0 | 291 | } |
michael@0 | 292 | else { |
michael@0 | 293 | assert.equal(code, 0, 'Exit code is 0 in exit handler'); |
michael@0 | 294 | assert.equal(signal, null, 'Signal is null in exit handler'); |
michael@0 | 295 | } |
michael@0 | 296 | if (++count === 3) complete(); |
michael@0 | 297 | } |
michael@0 | 298 | |
michael@0 | 299 | function closeHandler (code, signal) { |
michael@0 | 300 | // Sometimes the buffer limit is hit before the process closes successfully |
michael@0 | 301 | // on both OSX/Windows |
michael@0 | 302 | if (code === null) { |
michael@0 | 303 | assert.equal(code, null, 'Exit code is null in close handler'); |
michael@0 | 304 | assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in close handler'); |
michael@0 | 305 | } |
michael@0 | 306 | else { |
michael@0 | 307 | assert.equal(code, 0, 'Exit code is 0 in close handler'); |
michael@0 | 308 | assert.equal(signal, null, 'Signal is null in close handler'); |
michael@0 | 309 | } |
michael@0 | 310 | if (++count === 3) complete(); |
michael@0 | 311 | } |
michael@0 | 312 | |
michael@0 | 313 | function complete () { |
michael@0 | 314 | stdoutChild.off('exit', exitHandler); |
michael@0 | 315 | stdoutChild.off('close', closeHandler); |
michael@0 | 316 | done(); |
michael@0 | 317 | } |
michael@0 | 318 | }; |
michael@0 | 319 | |
michael@0 | 320 | exports.testExecFileOptionsMaxBufferSmallStdErr = function (assert, done) { |
michael@0 | 321 | let count = 0; |
michael@0 | 322 | let stderrChild; |
michael@0 | 323 | // Creates a buffer of 60 to stderr, less than 1024 |
michael@0 | 324 | getScript('large-err').then(script => { |
michael@0 | 325 | stderrChild = execFile(script, ['60'], { maxBuffer: 50 }, (err, stdout, stderr) => { |
michael@0 | 326 | assert.ok(/stderr maxBuffer exceeded/.test(err.toString()), |
michael@0 | 327 | 'error contains stderr maxBuffer exceeded message'); |
michael@0 | 328 | assert.ok(stderr.length >= 50, 'stderr has full buffer'); |
michael@0 | 329 | assert.equal(stdout, '', 'stdout is empty'); |
michael@0 | 330 | if (++count === 3) complete(); |
michael@0 | 331 | }); |
michael@0 | 332 | stderrChild.on('exit', exitHandler); |
michael@0 | 333 | stderrChild.on('close', closeHandler); |
michael@0 | 334 | }); |
michael@0 | 335 | |
michael@0 | 336 | function exitHandler (code, signal) { |
michael@0 | 337 | // Sometimes the buffer limit is hit before the process closes successfully |
michael@0 | 338 | // on both OSX/Windows |
michael@0 | 339 | if (code === null) { |
michael@0 | 340 | assert.equal(code, null, 'Exit code is null in exit handler'); |
michael@0 | 341 | assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler'); |
michael@0 | 342 | } |
michael@0 | 343 | else { |
michael@0 | 344 | assert.equal(code, 0, 'Exit code is 0 in exit handler'); |
michael@0 | 345 | assert.equal(signal, null, 'Signal is null in exit handler'); |
michael@0 | 346 | } |
michael@0 | 347 | if (++count === 3) complete(); |
michael@0 | 348 | } |
michael@0 | 349 | |
michael@0 | 350 | function closeHandler (code, signal) { |
michael@0 | 351 | // Sometimes the buffer limit is hit before the process closes successfully |
michael@0 | 352 | // on both OSX/Windows |
michael@0 | 353 | if (code === null) { |
michael@0 | 354 | assert.equal(code, null, 'Exit code is null in close handler'); |
michael@0 | 355 | assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in close handler'); |
michael@0 | 356 | } |
michael@0 | 357 | else { |
michael@0 | 358 | assert.equal(code, 0, 'Exit code is 0 in close handler'); |
michael@0 | 359 | assert.equal(signal, null, 'Signal is null in close handler'); |
michael@0 | 360 | } |
michael@0 | 361 | if (++count === 3) complete(); |
michael@0 | 362 | } |
michael@0 | 363 | |
michael@0 | 364 | function complete () { |
michael@0 | 365 | stderrChild.off('exit', exitHandler); |
michael@0 | 366 | stderrChild.off('close', closeHandler); |
michael@0 | 367 | done(); |
michael@0 | 368 | } |
michael@0 | 369 | }; |
michael@0 | 370 | |
michael@0 | 371 | exports.testChildExecFileKillSignal = function (assert, done) { |
michael@0 | 372 | getScript('wait').then(script => { |
michael@0 | 373 | execFile(script, { |
michael@0 | 374 | killSignal: 'beepbeep', |
michael@0 | 375 | timeout: 10 |
michael@0 | 376 | }, function (err, stdout, stderr) { |
michael@0 | 377 | assert.equal(err.signal, 'beepbeep', 'correctly used custom killSignal'); |
michael@0 | 378 | done(); |
michael@0 | 379 | }); |
michael@0 | 380 | }); |
michael@0 | 381 | }; |
michael@0 | 382 | |
michael@0 | 383 | exports.testChildProperties = function (assert, done) { |
michael@0 | 384 | getScript('check-env').then(script => { |
michael@0 | 385 | let child = spawn(script, { |
michael@0 | 386 | env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' } |
michael@0 | 387 | }); |
michael@0 | 388 | |
michael@0 | 389 | if (isWindows) |
michael@0 | 390 | assert.ok(true, 'Windows environment does not have `pid`'); |
michael@0 | 391 | else |
michael@0 | 392 | assert.ok(child.pid > 0, 'Child has a pid'); |
michael@0 | 393 | done(); |
michael@0 | 394 | }); |
michael@0 | 395 | }; |
michael@0 | 396 | |
michael@0 | 397 | exports.testChildStdinStreamLarge = function (assert, done) { |
michael@0 | 398 | let REPEAT = 2000; |
michael@0 | 399 | let allData = ''; |
michael@0 | 400 | // Use direct paths to more/cat, as we do not currently support calling non-files |
michael@0 | 401 | // from subprocess.jsm |
michael@0 | 402 | let child = spawn(CAT_PATH); |
michael@0 | 403 | |
michael@0 | 404 | child.stdout.on('data', onData); |
michael@0 | 405 | child.on('close', onClose); |
michael@0 | 406 | |
michael@0 | 407 | for (let i = 0; i < REPEAT; i++) |
michael@0 | 408 | emit(child.stdin, 'data', '12345\n'); |
michael@0 | 409 | |
michael@0 | 410 | emit(child.stdin, 'end'); |
michael@0 | 411 | |
michael@0 | 412 | function onData (data) { |
michael@0 | 413 | allData += data; |
michael@0 | 414 | } |
michael@0 | 415 | |
michael@0 | 416 | function onClose (code, signal) { |
michael@0 | 417 | child.stdout.off('data', onData); |
michael@0 | 418 | child.off('close', onClose); |
michael@0 | 419 | assert.equal(code, 0, 'exited succesfully'); |
michael@0 | 420 | assert.equal(signal, null, 'no kill signal given'); |
michael@0 | 421 | assert.equal(allData.replace(/\W/g, '').length, '12345'.length * REPEAT, |
michael@0 | 422 | 'all data processed from stdin'); |
michael@0 | 423 | done(); |
michael@0 | 424 | } |
michael@0 | 425 | }; |
michael@0 | 426 | |
michael@0 | 427 | exports.testChildStdinStreamSmall = function (assert, done) { |
michael@0 | 428 | let allData = ''; |
michael@0 | 429 | let child = spawn(CAT_PATH); |
michael@0 | 430 | child.stdout.on('data', onData); |
michael@0 | 431 | child.on('close', onClose); |
michael@0 | 432 | |
michael@0 | 433 | emit(child.stdin, 'data', '12345'); |
michael@0 | 434 | emit(child.stdin, 'end'); |
michael@0 | 435 | |
michael@0 | 436 | function onData (data) { |
michael@0 | 437 | allData += data; |
michael@0 | 438 | } |
michael@0 | 439 | |
michael@0 | 440 | function onClose (code, signal) { |
michael@0 | 441 | child.stdout.off('data', onData); |
michael@0 | 442 | child.off('close', onClose); |
michael@0 | 443 | assert.equal(code, 0, 'exited succesfully'); |
michael@0 | 444 | assert.equal(signal, null, 'no kill signal given'); |
michael@0 | 445 | assert.equal(allData.trim(), '12345', 'all data processed from stdin'); |
michael@0 | 446 | done(); |
michael@0 | 447 | } |
michael@0 | 448 | }; |
michael@0 | 449 | /* |
michael@0 | 450 | * This tests failures when an error is thrown attempting to |
michael@0 | 451 | * spawn the process, like an invalid command |
michael@0 | 452 | */ |
michael@0 | 453 | exports.testChildEventsSpawningError= function (assert, done) { |
michael@0 | 454 | let handlersCalled = 0; |
michael@0 | 455 | let child = execFile('i-do-not-exist', (err, stdout, stderr) => { |
michael@0 | 456 | assert.ok(err, 'error was passed into callback'); |
michael@0 | 457 | assert.equal(stdout, '', 'stdout is empty') |
michael@0 | 458 | assert.equal(stderr, '', 'stderr is empty'); |
michael@0 | 459 | if (++handlersCalled === 3) complete(); |
michael@0 | 460 | }); |
michael@0 | 461 | |
michael@0 | 462 | child.on('error', handleError); |
michael@0 | 463 | child.on('exit', handleExit); |
michael@0 | 464 | child.on('close', handleClose); |
michael@0 | 465 | |
michael@0 | 466 | function handleError (e) { |
michael@0 | 467 | assert.ok(e, 'error passed into error handler'); |
michael@0 | 468 | if (++handlersCalled === 3) complete(); |
michael@0 | 469 | } |
michael@0 | 470 | |
michael@0 | 471 | function handleClose (code, signal) { |
michael@0 | 472 | assert.equal(code, -1, |
michael@0 | 473 | 'process was never spawned, therefore exit code is -1'); |
michael@0 | 474 | assert.equal(signal, null, 'signal should be null'); |
michael@0 | 475 | if (++handlersCalled === 3) complete(); |
michael@0 | 476 | } |
michael@0 | 477 | |
michael@0 | 478 | function handleExit (code, signal) { |
michael@0 | 479 | assert.fail('Close event should not be called on init failure'); |
michael@0 | 480 | } |
michael@0 | 481 | |
michael@0 | 482 | function complete () { |
michael@0 | 483 | child.off('error', handleError); |
michael@0 | 484 | child.off('exit', handleExit); |
michael@0 | 485 | child.off('close', handleClose); |
michael@0 | 486 | done(); |
michael@0 | 487 | } |
michael@0 | 488 | }; |
michael@0 | 489 | |
michael@0 | 490 | exports.testSpawnOptions = function (assert, done) { |
michael@0 | 491 | let count = 0; |
michael@0 | 492 | let envStdout = ''; |
michael@0 | 493 | let cwdStdout = ''; |
michael@0 | 494 | let checkEnv, checkPwd, envChild, cwdChild; |
michael@0 | 495 | getScript('check-env').then(script => { |
michael@0 | 496 | checkEnv = script; |
michael@0 | 497 | return getScript('check-pwd'); |
michael@0 | 498 | }).then(script => { |
michael@0 | 499 | checkPwd = script; |
michael@0 | 500 | |
michael@0 | 501 | envChild = spawn(checkEnv, { |
michael@0 | 502 | env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' } |
michael@0 | 503 | }); |
michael@0 | 504 | cwdChild = spawn(checkPwd, { cwd: PROFILE_DIR }); |
michael@0 | 505 | |
michael@0 | 506 | // Do these need to be unbound? |
michael@0 | 507 | envChild.stdout.on('data', data => envStdout += data); |
michael@0 | 508 | cwdChild.stdout.on('data', data => cwdStdout += data); |
michael@0 | 509 | |
michael@0 | 510 | envChild.on('close', envClose); |
michael@0 | 511 | cwdChild.on('close', cwdClose); |
michael@0 | 512 | }); |
michael@0 | 513 | |
michael@0 | 514 | function envClose () { |
michael@0 | 515 | assert.equal(envStdout.trim(), 'my-value-test', 'spawn correctly passed in ENV'); |
michael@0 | 516 | if (++count === 2) complete(); |
michael@0 | 517 | } |
michael@0 | 518 | |
michael@0 | 519 | function cwdClose () { |
michael@0 | 520 | // Check for PROFILE_DIR in the output because |
michael@0 | 521 | // some systems resolve symbolic links, and on OSX |
michael@0 | 522 | // /var -> /private/var |
michael@0 | 523 | let isCorrectPath = ~cwdStdout.trim().indexOf(PROFILE_DIR); |
michael@0 | 524 | assert.ok(isCorrectPath, 'spawn correctly passed in cwd'); |
michael@0 | 525 | if (++count === 2) complete(); |
michael@0 | 526 | } |
michael@0 | 527 | |
michael@0 | 528 | function complete () { |
michael@0 | 529 | envChild.off('close', envClose); |
michael@0 | 530 | cwdChild.off('close', cwdClose); |
michael@0 | 531 | done(); |
michael@0 | 532 | } |
michael@0 | 533 | }; |
michael@0 | 534 | |
michael@0 | 535 | exports.testFork = function (assert) { |
michael@0 | 536 | assert.throws(function () { |
michael@0 | 537 | fork(); |
michael@0 | 538 | }, /not currently supported/, 'fork() correctly throws an unsupported error'); |
michael@0 | 539 | }; |
michael@0 | 540 | |
michael@0 | 541 | after(exports, cleanUp); |
michael@0 | 542 | |
michael@0 | 543 | require("test").run(exports); |
michael@0 | 544 | |
michael@0 | 545 | // Test disabled because of bug 979675 |
michael@0 | 546 | module.exports = {}; |