• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const common = require('../common');
4if (!common.hasCrypto)
5  common.skip('missing crypto');
6
7const async_hooks = require('async_hooks');
8const assert = require('assert');
9const http2 = require('http2');
10const { inspect } = require('util');
11
12const pings = new Set();
13const events = [0, 0, 0, 0];
14
15const hook = async_hooks.createHook({
16  init(id, type, trigger, resource) {
17    if (type === 'HTTP2PING') {
18      pings.add(id);
19      events[0]++;
20    }
21  },
22  before(id) {
23    if (pings.has(id)) {
24      events[1]++;
25    }
26  },
27  after(id) {
28    if (pings.has(id)) {
29      events[2]++;
30    }
31  },
32  destroy(id) {
33    if (pings.has(id)) {
34      events[3]++;
35    }
36  }
37});
38hook.enable();
39
40process.on('exit', () => {
41  assert.deepStrictEqual(events, [4, 4, 4, 4]);
42});
43
44const server = http2.createServer();
45server.on('stream', common.mustCall((stream) => {
46  assert(stream.session.ping(common.mustCall((err, duration, ret) => {
47    assert.strictEqual(err, null);
48    assert.strictEqual(typeof duration, 'number');
49    assert.strictEqual(ret.length, 8);
50    stream.end('ok');
51  })));
52  stream.respond();
53}));
54
55server.listen(0, common.mustCall(() => {
56  const client = http2.connect(`http://localhost:${server.address().port}`,
57                               { maxOutstandingPings: 2 });
58  client.on('connect', common.mustCall(() => {
59    {
60      const payload = Buffer.from('abcdefgh');
61      assert(client.ping(payload, common.mustCall((err, duration, ret) => {
62        assert.strictEqual(err, null);
63        assert.strictEqual(typeof duration, 'number');
64        assert.deepStrictEqual(payload, ret);
65      })));
66    }
67    {
68      const payload = Buffer.from('abcdefgi');
69      assert(client.ping(payload, common.mustCall((err, duration, ret) => {
70        assert.strictEqual(err, null);
71        assert.strictEqual(typeof duration, 'number');
72        assert.deepStrictEqual(payload, ret);
73      })));
74    }
75
76    // Only max 2 pings at a time based on the maxOutstandingPings option
77    assert(!client.ping(common.expectsError({
78      code: 'ERR_HTTP2_PING_CANCEL',
79      name: 'Error',
80      message: 'HTTP2 ping cancelled'
81    })));
82
83    // Should throw if payload is not of type ArrayBufferView
84    {
85      [1, true, {}, []].forEach((payload) =>
86        assert.throws(
87          () => client.ping(payload),
88          {
89            name: 'TypeError',
90            code: 'ERR_INVALID_ARG_TYPE',
91            message: 'The "payload" argument must be an instance of Buffer, ' +
92                     'TypedArray, or DataView.' +
93                     common.invalidArgTypeHelper(payload)
94          }
95        )
96      );
97    }
98
99    // Should throw if payload length is not 8
100    {
101      const shortPayload = Buffer.from('abcdefg');
102      const longPayload = Buffer.from('abcdefghi');
103      [shortPayload, longPayload].forEach((payloadWithInvalidLength) =>
104        assert.throws(
105          () => client.ping(payloadWithInvalidLength),
106          {
107            name: 'RangeError',
108            code: 'ERR_HTTP2_PING_LENGTH',
109            message: 'HTTP2 ping payload must be 8 bytes'
110          }
111        )
112      );
113    }
114
115    // Should throw error is callback is not of type function
116    {
117      const payload = Buffer.from('abcdefgh');
118      [1, true, {}, []].forEach((invalidCallback) =>
119        assert.throws(
120          () => client.ping(payload, invalidCallback),
121          {
122            name: 'TypeError',
123            code: 'ERR_INVALID_CALLBACK',
124            message: 'Callback must be a function. ' +
125                     `Received ${inspect(invalidCallback)}`
126          }
127        )
128      );
129    }
130
131    const req = client.request();
132    req.resume();
133    req.on('end', common.mustCall(() => {
134      client.close();
135      server.close();
136    }));
137  }));
138}));
139