summaryrefslogtreecommitdiff
path: root/test/async-hooks/test-callback-error.js
blob: a4b8a99f33e8582898836addcf41db9fddda9e1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
'use strict';
const common = require('../common');
const assert = require('assert');
const { spawnSync, fork } = require('child_process');
const async_hooks = require('async_hooks');
const initHooks = require('./init-hooks');

const arg = process.argv[2];
switch (arg) {
  case 'test_init_callback':
    initHooks({
      oninit: common.mustCall(() => { throw new Error(arg); })
    }).enable();
    async_hooks.emitInit(
      async_hooks.newUid(),
      `${arg}_type`,
      async_hooks.executionAsyncId()
    );
    return;

  case 'test_callback':
    initHooks({
      onbefore: common.mustCall(() => { throw new Error(arg); })
    }).enable();
    const newAsyncId = async_hooks.newUid();
    async_hooks.emitInit(
      newAsyncId,
      `${arg}_type`,
      async_hooks.executionAsyncId()
    );
    async_hooks.emitBefore(newAsyncId, async_hooks.executionAsyncId());
    return;

  case 'test_callback_abort':
    initHooks({
      oninit: common.mustCall(() => { throw new Error(arg); })
    }).enable();
    async_hooks.emitInit(
      async_hooks.newUid(),
      `${arg}_type`,
      async_hooks.executionAsyncId()
    );
    return;
}

// this part should run only for the master test
assert.ok(!arg);
{
  // console.log should stay until this test's flakiness is solved
  console.log('start case 1');
  console.time('end case 1');
  const child = spawnSync(process.execPath, [__filename, 'test_init_callback']);
  assert.ifError(child.error);
  const test_init_first_line = child.stderr.toString().split(/[\r\n]+/g)[0];
  assert.strictEqual(test_init_first_line, 'Error: test_init_callback');
  assert.strictEqual(child.status, 1);
  console.timeEnd('end case 1');
}

{
  console.log('start case 2');
  console.time('end case 2');
  const child = spawnSync(process.execPath, [__filename, 'test_callback']);
  assert.ifError(child.error);
  const test_callback_first_line = child.stderr.toString().split(/[\r\n]+/g)[0];
  assert.strictEqual(test_callback_first_line, 'Error: test_callback');
  assert.strictEqual(child.status, 1);
  console.timeEnd('end case 2');
}

{
  console.log('start case 3');
  console.time('end case 3');
  // Timeout is set because this case is known to be problematic, so stderr is
  // logged for further analysis.
  // Ref: https://github.com/nodejs/node/issues/13527
  // Ref: https://github.com/nodejs/node/pull/13559
  const opts = {
    execArgv: ['--abort-on-uncaught-exception'],
    silent: true
  };
  const child = fork(__filename, ['test_callback_abort'], opts);

  let stdout = '';
  child.stdout.on('data', (data) => {
    stdout += data;
  });

  let stderr = '';
  child.stderr.on('data', (data) => {
    stderr += data;
  });

  const tO = setTimeout(() => {
    console.log(stderr);
    child.kill('SIGKILL');
    process.exit(1);
  }, 15 * 1000);
  tO.unref();

  child.on('close', (code, signal) => {
    clearTimeout(tO);
    if (common.isWindows) {
      assert.strictEqual(code, 3);
      assert.strictEqual(signal, null);
    } else {
      assert.strictEqual(code, null);
      // most posix systems will show 'SIGABRT', but alpine34 does not
      if (signal !== 'SIGABRT') {
        console.log(`parent recived signal ${signal}\nchild's stderr:`);
        console.log(stderr);
        process.exit(1);
      }
      assert.strictEqual(signal, 'SIGABRT');
    }
    assert.strictEqual(stdout, '');
    const firstLineStderr = stderr.split(/[\r\n]+/g)[0].trim();
    assert.strictEqual(firstLineStderr, 'Error: test_callback_abort');
  });
  console.timeEnd('end case 3');
}