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