summaryrefslogtreecommitdiff
path: root/test/async-hooks/test-improper-unwind.js
blob: a62512db974ac6893a2503b8f7d3662054437956 (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
// Flags: --expose-internals
'use strict';

const common = require('../common');
const assert = require('assert');
const internal_async_hooks = require('internal/async_hooks');
const { spawn } = require('child_process');
const corruptedMsg = /async hook stack has become corrupted/;
const heartbeatMsg = /heartbeat: still alive/;

const {
  newAsyncId, getDefaultTriggerAsyncId,
  emitInit, emitBefore, emitAfter
} = internal_async_hooks;

const initHooks = require('./init-hooks');

if (process.argv[2] === 'child') {
  const hooks = initHooks();
  hooks.enable();

  // In both the below two cases 'before' of event2 is nested inside 'before'
  // of event1.
  // Therefore the 'after' of event2 needs to occur before the
  // 'after' of event 1.
  // The first test of the two below follows that rule,
  // the second one doesn't.

  const eventOneId = newAsyncId();
  const eventTwoId = newAsyncId();
  const triggerId = getDefaultTriggerAsyncId();
  emitInit(eventOneId, 'event1', triggerId, {});
  emitInit(eventTwoId, 'event2', triggerId, {});

  // Proper unwind
  emitBefore(eventOneId, triggerId);
  emitBefore(eventTwoId, triggerId);
  emitAfter(eventTwoId);
  emitAfter(eventOneId);

  // Improper unwind
  emitBefore(eventOneId, triggerId);
  emitBefore(eventTwoId, triggerId);

  console.log('heartbeat: still alive');
  emitAfter(eventOneId);
} else {
  const args = ['--expose-internals']
    .concat(process.argv.slice(1))
    .concat('child');
  let errData = Buffer.from('');
  let outData = Buffer.from('');

  const child = spawn(process.execPath, args);
  child.stderr.on('data', (d) => { errData = Buffer.concat([ errData, d ]); });
  child.stdout.on('data', (d) => { outData = Buffer.concat([ outData, d ]); });

  child.on('close', common.mustCall((code) => {
    assert.strictEqual(code, 1);
    assert.ok(heartbeatMsg.test(outData.toString()),
              'did not crash until we reached offending line of code ' +
              `(found ${outData})`);
    assert.ok(corruptedMsg.test(errData.toString()),
              'printed error contains corrupted message ' +
              `(found ${errData})`);
  }));
}