11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ci// This test makes sure that when throwing an error from a domain, and then
41cb0ef41Sopenharmony_ci// handling that error in an uncaughtException handler by throwing an error
51cb0ef41Sopenharmony_ci// again, the exit code, signal and error messages are the ones we expect with
61cb0ef41Sopenharmony_ci// and without using --abort-on-uncaught-exception.
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst common = require('../common');
91cb0ef41Sopenharmony_ciconst assert = require('assert');
101cb0ef41Sopenharmony_ciconst child_process = require('child_process');
111cb0ef41Sopenharmony_ciconst domain = require('domain');
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciconst uncaughtExceptionHandlerErrMsg = 'boom from uncaughtException handler';
141cb0ef41Sopenharmony_ciconst domainErrMsg = 'boom from domain';
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciconst RAN_UNCAUGHT_EXCEPTION_HANDLER_EXIT_CODE = 42;
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciif (process.argv[2] === 'child') {
191cb0ef41Sopenharmony_ci  process.on('uncaughtException', common.mustCall(function onUncaught() {
201cb0ef41Sopenharmony_ci    if (process.execArgv.includes('--abort-on-uncaught-exception')) {
211cb0ef41Sopenharmony_ci      // When passing --abort-on-uncaught-exception to the child process,
221cb0ef41Sopenharmony_ci      // we want to make sure that this handler (the process' uncaughtException
231cb0ef41Sopenharmony_ci      // event handler) wasn't called. Unfortunately we can't parse the child
241cb0ef41Sopenharmony_ci      // process' output to do that, since on Windows the standard error output
251cb0ef41Sopenharmony_ci      // is not properly flushed in V8's Isolate::Throw right before the
261cb0ef41Sopenharmony_ci      // process aborts due to an uncaught exception, and thus the error
271cb0ef41Sopenharmony_ci      // message representing the error that was thrown cannot be read by the
281cb0ef41Sopenharmony_ci      // parent process. So instead of parsing the child process' standard
291cb0ef41Sopenharmony_ci      // error, the parent process will check that in the case
301cb0ef41Sopenharmony_ci      // --abort-on-uncaught-exception was passed, the process did not exit
311cb0ef41Sopenharmony_ci      // with exit code RAN_UNCAUGHT_EXCEPTION_HANDLER_EXIT_CODE.
321cb0ef41Sopenharmony_ci      process.exit(RAN_UNCAUGHT_EXCEPTION_HANDLER_EXIT_CODE);
331cb0ef41Sopenharmony_ci    } else {
341cb0ef41Sopenharmony_ci      // On the other hand, when not passing --abort-on-uncaught-exception to
351cb0ef41Sopenharmony_ci      // the node process, we want to throw in this event handler to make sure
361cb0ef41Sopenharmony_ci      // that the proper error message, exit code and signal are the ones we
371cb0ef41Sopenharmony_ci      // expect.
381cb0ef41Sopenharmony_ci      throw new Error(uncaughtExceptionHandlerErrMsg);
391cb0ef41Sopenharmony_ci    }
401cb0ef41Sopenharmony_ci  }));
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  const d = domain.create();
431cb0ef41Sopenharmony_ci  d.run(common.mustCall(function() {
441cb0ef41Sopenharmony_ci    throw new Error(domainErrMsg);
451cb0ef41Sopenharmony_ci  }));
461cb0ef41Sopenharmony_ci} else {
471cb0ef41Sopenharmony_ci  runTestWithoutAbortOnUncaughtException();
481cb0ef41Sopenharmony_ci  runTestWithAbortOnUncaughtException();
491cb0ef41Sopenharmony_ci}
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_cifunction runTestWithoutAbortOnUncaughtException() {
521cb0ef41Sopenharmony_ci  child_process.exec(
531cb0ef41Sopenharmony_ci    createTestCmdLine(),
541cb0ef41Sopenharmony_ci    function onTestDone(err, stdout, stderr) {
551cb0ef41Sopenharmony_ci      // When _not_ passing --abort-on-uncaught-exception, the process'
561cb0ef41Sopenharmony_ci      // uncaughtException handler _must_ be called, and thus the error
571cb0ef41Sopenharmony_ci      // message must include only the message of the error thrown from the
581cb0ef41Sopenharmony_ci      // process' uncaughtException handler.
591cb0ef41Sopenharmony_ci      assert(stderr.includes(uncaughtExceptionHandlerErrMsg),
601cb0ef41Sopenharmony_ci             'stderr output must include proper uncaughtException ' +
611cb0ef41Sopenharmony_ci             'handler\'s error\'s message');
621cb0ef41Sopenharmony_ci      assert(!stderr.includes(domainErrMsg),
631cb0ef41Sopenharmony_ci             'stderr output must not include domain\'s error\'s message');
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci      assert.notStrictEqual(err.code, 0,
661cb0ef41Sopenharmony_ci                            'child process should have exited with a ' +
671cb0ef41Sopenharmony_ci                            'non-zero exit code, but did not');
681cb0ef41Sopenharmony_ci    }
691cb0ef41Sopenharmony_ci  );
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_cifunction runTestWithAbortOnUncaughtException() {
731cb0ef41Sopenharmony_ci  child_process.exec(createTestCmdLine({
741cb0ef41Sopenharmony_ci    withAbortOnUncaughtException: true
751cb0ef41Sopenharmony_ci  }), function onTestDone(err, stdout, stderr) {
761cb0ef41Sopenharmony_ci    assert.notStrictEqual(err.code, RAN_UNCAUGHT_EXCEPTION_HANDLER_EXIT_CODE,
771cb0ef41Sopenharmony_ci                          'child process should not have run its ' +
781cb0ef41Sopenharmony_ci                          'uncaughtException event handler');
791cb0ef41Sopenharmony_ci    assert(common.nodeProcessAborted(err.code, err.signal),
801cb0ef41Sopenharmony_ci           'process should have aborted, but did not');
811cb0ef41Sopenharmony_ci  });
821cb0ef41Sopenharmony_ci}
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_cifunction createTestCmdLine(options) {
851cb0ef41Sopenharmony_ci  let testCmd = '';
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  if (!common.isWindows) {
881cb0ef41Sopenharmony_ci    // Do not create core files, as it can take a lot of disk space on
891cb0ef41Sopenharmony_ci    // continuous testing and developers' machines
901cb0ef41Sopenharmony_ci    testCmd += 'ulimit -c 0 && ';
911cb0ef41Sopenharmony_ci  }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  testCmd += `"${process.argv[0]}"`;
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  if (options && options.withAbortOnUncaughtException) {
961cb0ef41Sopenharmony_ci    testCmd += ' --abort-on-uncaught-exception';
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  testCmd += ` "${process.argv[1]}" child`;
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  return testCmd;
1021cb0ef41Sopenharmony_ci}
103