• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2// Flags: --expose-internals
3
4const common = require('../common');
5if (!common.hasCrypto)
6  common.skip('missing crypto');
7const http2 = require('http2');
8const { internalBinding } = require('internal/test/binding');
9const {
10  constants,
11  Http2Stream,
12  nghttp2ErrorString
13} = internalBinding('http2');
14const { NghttpError } = require('internal/http2/util');
15
16// Tests error handling within pushStream
17// - NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE (should emit session error)
18// - NGHTTP2_ERR_STREAM_CLOSED (should emit stream error)
19// - every other NGHTTP2 error from binding (should emit stream error)
20
21const specificTestKeys = [
22  'NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE',
23  'NGHTTP2_ERR_STREAM_CLOSED',
24];
25
26const specificTests = [
27  {
28    ngError: constants.NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE,
29    error: {
30      code: 'ERR_HTTP2_OUT_OF_STREAMS',
31      name: 'Error',
32      message: 'No stream ID is available because ' +
33               'maximum stream ID has been reached'
34    },
35    type: 'stream'
36  },
37  {
38    ngError: constants.NGHTTP2_ERR_STREAM_CLOSED,
39    error: {
40      code: 'ERR_HTTP2_INVALID_STREAM',
41      name: 'Error'
42    },
43    type: 'stream'
44  },
45];
46
47const genericTests = Object.getOwnPropertyNames(constants)
48  .filter((key) => (
49    key.indexOf('NGHTTP2_ERR') === 0 && specificTestKeys.indexOf(key) < 0
50  ))
51  .map((key) => ({
52    ngError: constants[key],
53    error: {
54      code: 'ERR_HTTP2_ERROR',
55      constructor: NghttpError,
56      name: 'Error',
57      message: nghttp2ErrorString(constants[key])
58    },
59    type: 'stream'
60  }));
61
62
63const tests = specificTests.concat(genericTests);
64
65let currentError;
66
67// Mock submitPushPromise because we only care about testing error handling
68Http2Stream.prototype.pushPromise = () => currentError.ngError;
69
70const server = http2.createServer();
71server.on('stream', common.mustCall((stream, headers) => {
72  stream.pushStream({}, common.expectsError(currentError.error));
73  stream.respond();
74  stream.end();
75}, tests.length));
76
77server.listen(0, common.mustCall(() => runTest(tests.shift())));
78
79function runTest(test) {
80  const url = `http://localhost:${server.address().port}`;
81
82  const client = http2.connect(url);
83  const req = client.request();
84
85  currentError = test;
86  req.resume();
87  req.end();
88
89  req.on('close', common.mustCall(() => {
90    client.close();
91
92    if (!tests.length) {
93      server.close();
94    } else {
95      runTest(tests.shift());
96    }
97  }));
98}
99