• 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 respond
17// - every other NGHTTP2 error from binding (should emit stream error)
18
19const specificTestKeys = [];
20
21const specificTests = [];
22
23const genericTests = Object.getOwnPropertyNames(constants)
24  .filter((key) => (
25    key.indexOf('NGHTTP2_ERR') === 0 && specificTestKeys.indexOf(key) < 0
26  ))
27  .map((key) => ({
28    ngError: constants[key],
29    error: {
30      code: 'ERR_HTTP2_ERROR',
31      constructor: NghttpError,
32      name: 'Error',
33      message: nghttp2ErrorString(constants[key])
34    },
35    type: 'stream'
36  }));
37
38
39const tests = specificTests.concat(genericTests);
40
41let currentError;
42
43// Mock submitResponse because we only care about testing error handling
44Http2Stream.prototype.respond = () => currentError.ngError;
45
46const server = http2.createServer();
47server.on('stream', common.mustCall((stream, headers) => {
48  const errorMustCall = common.expectsError(currentError.error);
49  const errorMustNotCall = common.mustNotCall(
50    `${currentError.error.code} should emit on ${currentError.type}`
51  );
52
53  if (currentError.type === 'stream') {
54    stream.session.on('error', errorMustNotCall);
55    stream.on('error', errorMustCall);
56    stream.on('error', common.mustCall(() => {
57      stream.destroy();
58    }));
59  } else {
60    stream.session.once('error', errorMustCall);
61    stream.on('error', errorMustNotCall);
62  }
63
64  stream.respond();
65}, tests.length));
66
67server.listen(0, common.mustCall(() => runTest(tests.shift())));
68
69function runTest(test) {
70  const port = server.address().port;
71  const url = `http://localhost:${port}`;
72  const headers = {
73    ':path': '/',
74    ':method': 'POST',
75    ':scheme': 'http',
76    ':authority': `localhost:${port}`
77  };
78
79  const client = http2.connect(url);
80  const req = client.request(headers);
81  req.on('error', common.expectsError({
82    code: 'ERR_HTTP2_STREAM_ERROR',
83    name: 'Error',
84    message: 'Stream closed with error code NGHTTP2_INTERNAL_ERROR'
85  }));
86
87  currentError = test;
88  req.resume();
89  req.end();
90
91  req.on('end', common.mustCall(() => {
92    client.close();
93
94    if (!tests.length) {
95      server.close();
96    } else {
97      runTest(tests.shift());
98    }
99  }));
100}
101