• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2// Flags: --expose-internals
3const common = require('../common');
4const initHooks = require('./init-hooks');
5const { checkInvocations } = require('./hook-checks');
6const assert = require('assert');
7const { async_id_symbol } = require('internal/async_hooks').symbols;
8const http = require('http');
9
10// Checks that the async resource used in init in case of a reused handle
11// is not reused. Test is based on parallel\test-async-hooks-http-agent.js.
12
13const hooks = initHooks();
14hooks.enable();
15
16const reqAsyncIds = [];
17let socket;
18let responses = 0;
19
20// Make sure a single socket is transparently reused for 2 requests.
21const agent = new http.Agent({
22  keepAlive: true,
23  keepAliveMsecs: Infinity,
24  maxSockets: 1
25});
26
27const verifyRequest = (idx) => (res) => {
28  reqAsyncIds[idx] = res.socket[async_id_symbol];
29  assert.ok(reqAsyncIds[idx] > 0, `${reqAsyncIds[idx]} > 0`);
30  if (socket) {
31    // Check that both requests share their socket.
32    assert.strictEqual(res.socket, socket);
33  } else {
34    socket = res.socket;
35  }
36
37  res.on('data', common.mustCallAtLeast(() => {}));
38  res.on('end', common.mustCall(() => {
39    if (++responses === 2) {
40      // Clean up to let the event loop stop.
41      server.close();
42      agent.destroy();
43    }
44  }));
45};
46
47const server = http.createServer(common.mustCall((req, res) => {
48  req.once('data', common.mustCallAtLeast(() => {
49    res.writeHead(200, { 'Content-Type': 'text/plain' });
50    res.write('foo');
51  }));
52  req.on('end', common.mustCall(() => {
53    res.end('bar');
54  }));
55}, 2)).listen(0, common.mustCall(() => {
56  const port = server.address().port;
57  const payload = 'hello world';
58
59  // First request.
60  const r1 = http.request({
61    agent, port, method: 'POST'
62  }, common.mustCall(verifyRequest(0)));
63  r1.end(payload);
64
65  // Second request. Sent in parallel with the first one.
66  const r2 = http.request({
67    agent, port, method: 'POST'
68  }, common.mustCall(verifyRequest(1)));
69  r2.end(payload);
70}));
71
72
73process.on('exit', onExit);
74
75function onExit() {
76  hooks.disable();
77  hooks.sanityCheck();
78  const activities = hooks.activities;
79
80  // Verify both invocations
81  const first = activities.filter((x) => x.uid === reqAsyncIds[0])[0];
82  checkInvocations(first, { init: 1, destroy: 1 }, 'when process exits');
83
84  const second = activities.filter((x) => x.uid === reqAsyncIds[1])[0];
85  checkInvocations(second, { init: 1, destroy: 1 }, 'when process exits');
86
87  // Verify reuse handle has been wrapped
88  assert.strictEqual(first.type, second.type);
89  assert.ok(first.handle !== second.handle, 'Resource reused');
90  assert.ok(first.handle === second.handle.handle,
91            'Resource not wrapped correctly');
92}
93