summaryrefslogtreecommitdiff
path: root/test/parallel/test-http2-ping.js
blob: 993867bb21c6f2717a213cfbcf94810feac253fa (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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
'use strict';

const common = require('../common');
if (!common.hasCrypto)
  common.skip('missing crypto');

const async_hooks = require('async_hooks');
const assert = require('assert');
const http2 = require('http2');
const { inspect } = require('util');

const pings = new Set();
const events = [0, 0, 0, 0];

const hook = async_hooks.createHook({
  init(id, type, trigger, resource) {
    if (type === 'HTTP2PING') {
      pings.add(id);
      events[0]++;
    }
  },
  before(id) {
    if (pings.has(id)) {
      events[1]++;
    }
  },
  after(id) {
    if (pings.has(id)) {
      events[2]++;
    }
  },
  destroy(id) {
    if (pings.has(id)) {
      events[3]++;
    }
  }
});
hook.enable();

process.on('exit', () => {
  assert.deepStrictEqual(events, [4, 4, 4, 4]);
});

const server = http2.createServer();
server.on('stream', common.mustCall((stream) => {
  assert(stream.session.ping(common.mustCall((err, duration, ret) => {
    assert.strictEqual(err, null);
    assert.strictEqual(typeof duration, 'number');
    assert.strictEqual(ret.length, 8);
    stream.end('ok');
  })));
  stream.respond();
}));

server.listen(0, common.mustCall(() => {
  const client = http2.connect(`http://localhost:${server.address().port}`,
                               { maxOutstandingPings: 2 });
  client.on('connect', common.mustCall(() => {
    {
      const payload = Buffer.from('abcdefgh');
      assert(client.ping(payload, common.mustCall((err, duration, ret) => {
        assert.strictEqual(err, null);
        assert.strictEqual(typeof duration, 'number');
        assert.deepStrictEqual(payload, ret);
      })));
    }
    {
      const payload = Buffer.from('abcdefgi');
      assert(client.ping(payload, common.mustCall((err, duration, ret) => {
        assert.strictEqual(err, null);
        assert.strictEqual(typeof duration, 'number');
        assert.deepStrictEqual(payload, ret);
      })));
    }

    // Only max 2 pings at a time based on the maxOutstandingPings option
    assert(!client.ping(common.expectsError({
      code: 'ERR_HTTP2_PING_CANCEL',
      type: Error,
      message: 'HTTP2 ping cancelled'
    })));

    // Should throw if payload is not of type ArrayBufferView
    {
      [1, true, {}, []].forEach((payload) =>
        common.expectsError(
          () => client.ping(payload),
          {
            type: TypeError,
            code: 'ERR_INVALID_ARG_TYPE',
            message: 'The "payload" argument must be one of type Buffer, ' +
                     `TypedArray, or DataView. Received type ${typeof payload}`
          }
        )
      );
    }

    // Should throw if payload length is not 8
    {
      const shortPayload = Buffer.from('abcdefg');
      const longPayload = Buffer.from('abcdefghi');
      [shortPayload, longPayload].forEach((payloadWithInvalidLength) =>
        common.expectsError(
          () => client.ping(payloadWithInvalidLength),
          {
            type: RangeError,
            code: 'ERR_HTTP2_PING_LENGTH',
            message: 'HTTP2 ping payload must be 8 bytes'
          }
        )
      );
    }

    // Should throw error is callback is not of type function
    {
      const payload = Buffer.from('abcdefgh');
      [1, true, {}, []].forEach((invalidCallback) =>
        common.expectsError(
          () => client.ping(payload, invalidCallback),
          {
            type: TypeError,
            code: 'ERR_INVALID_CALLBACK',
            message: 'Callback must be a function. ' +
                     `Received ${inspect(invalidCallback)}`
          }
        )
      );
    }

    const req = client.request();
    req.resume();
    req.on('end', common.mustCall(() => {
      client.close();
      server.close();
    }));
  }));
}));