11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci// Flags: --expose-internals
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ciconst common = require('../common');
51cb0ef41Sopenharmony_ciif (!common.hasCrypto)
61cb0ef41Sopenharmony_ci  common.skip('missing crypto');
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst { internalBinding } = require('internal/test/binding');
91cb0ef41Sopenharmony_ciconst {
101cb0ef41Sopenharmony_ci  constants,
111cb0ef41Sopenharmony_ci  Http2Session,
121cb0ef41Sopenharmony_ci  nghttp2ErrorString
131cb0ef41Sopenharmony_ci} = internalBinding('http2');
141cb0ef41Sopenharmony_ciconst http2 = require('http2');
151cb0ef41Sopenharmony_ciconst { NghttpError } = require('internal/http2/util');
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci// Tests error handling within requestOnConnect
181cb0ef41Sopenharmony_ci// - NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE (should emit session error)
191cb0ef41Sopenharmony_ci// - NGHTTP2_ERR_INVALID_ARGUMENT (should emit stream error)
201cb0ef41Sopenharmony_ci// - every other NGHTTP2 error from binding (should emit session error)
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ciconst specificTestKeys = [
231cb0ef41Sopenharmony_ci  'NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE',
241cb0ef41Sopenharmony_ci  'NGHTTP2_ERR_INVALID_ARGUMENT',
251cb0ef41Sopenharmony_ci];
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciconst specificTests = [
281cb0ef41Sopenharmony_ci  {
291cb0ef41Sopenharmony_ci    ngError: constants.NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE,
301cb0ef41Sopenharmony_ci    error: {
311cb0ef41Sopenharmony_ci      code: 'ERR_HTTP2_OUT_OF_STREAMS',
321cb0ef41Sopenharmony_ci      name: 'Error',
331cb0ef41Sopenharmony_ci      message: 'No stream ID is available because ' +
341cb0ef41Sopenharmony_ci               'maximum stream ID has been reached'
351cb0ef41Sopenharmony_ci    },
361cb0ef41Sopenharmony_ci    type: 'stream'
371cb0ef41Sopenharmony_ci  },
381cb0ef41Sopenharmony_ci  {
391cb0ef41Sopenharmony_ci    ngError: constants.NGHTTP2_ERR_INVALID_ARGUMENT,
401cb0ef41Sopenharmony_ci    error: {
411cb0ef41Sopenharmony_ci      code: 'ERR_HTTP2_STREAM_SELF_DEPENDENCY',
421cb0ef41Sopenharmony_ci      name: 'Error',
431cb0ef41Sopenharmony_ci      message: 'A stream cannot depend on itself'
441cb0ef41Sopenharmony_ci    },
451cb0ef41Sopenharmony_ci    type: 'stream'
461cb0ef41Sopenharmony_ci  },
471cb0ef41Sopenharmony_ci];
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ciconst genericTests = Object.getOwnPropertyNames(constants)
501cb0ef41Sopenharmony_ci  .filter((key) => (
511cb0ef41Sopenharmony_ci    key.indexOf('NGHTTP2_ERR') === 0 && specificTestKeys.indexOf(key) < 0
521cb0ef41Sopenharmony_ci  ))
531cb0ef41Sopenharmony_ci  .map((key) => ({
541cb0ef41Sopenharmony_ci    ngError: constants[key],
551cb0ef41Sopenharmony_ci    error: {
561cb0ef41Sopenharmony_ci      code: 'ERR_HTTP2_ERROR',
571cb0ef41Sopenharmony_ci      constructor: NghttpError,
581cb0ef41Sopenharmony_ci      name: 'Error',
591cb0ef41Sopenharmony_ci      message: nghttp2ErrorString(constants[key])
601cb0ef41Sopenharmony_ci    },
611cb0ef41Sopenharmony_ci    type: 'session'
621cb0ef41Sopenharmony_ci  }));
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ciconst tests = specificTests.concat(genericTests);
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_cilet currentError;
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci// Mock submitRequest because we only care about testing error handling
691cb0ef41Sopenharmony_ciHttp2Session.prototype.request = () => currentError;
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ciconst server = http2.createServer(common.mustNotCall());
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ciserver.listen(0, common.mustCall(() => runTest(tests.shift())));
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_cifunction runTest(test) {
761cb0ef41Sopenharmony_ci  const client = http2.connect(`http://localhost:${server.address().port}`);
771cb0ef41Sopenharmony_ci  client.on('close', common.mustCall());
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  const req = client.request({ ':method': 'POST' });
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  currentError = test.ngError;
821cb0ef41Sopenharmony_ci  req.resume();
831cb0ef41Sopenharmony_ci  req.end();
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci  const errorMustCall = common.expectsError(test.error);
861cb0ef41Sopenharmony_ci  const errorMustNotCall = common.mustNotCall(
871cb0ef41Sopenharmony_ci    `${test.error.code} should emit on ${test.type}`
881cb0ef41Sopenharmony_ci  );
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  if (test.type === 'stream') {
911cb0ef41Sopenharmony_ci    client.on('error', errorMustNotCall);
921cb0ef41Sopenharmony_ci    req.on('error', errorMustCall);
931cb0ef41Sopenharmony_ci  } else {
941cb0ef41Sopenharmony_ci    client.on('error', errorMustCall);
951cb0ef41Sopenharmony_ci    req.on('error', (err) => {
961cb0ef41Sopenharmony_ci      common.expectsError({
971cb0ef41Sopenharmony_ci        code: 'ERR_HTTP2_STREAM_CANCEL'
981cb0ef41Sopenharmony_ci      })(err);
991cb0ef41Sopenharmony_ci      common.expectsError({
1001cb0ef41Sopenharmony_ci        code: 'ERR_HTTP2_ERROR'
1011cb0ef41Sopenharmony_ci      })(err.cause);
1021cb0ef41Sopenharmony_ci    });
1031cb0ef41Sopenharmony_ci  }
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  req.on('end', common.mustNotCall());
1061cb0ef41Sopenharmony_ci  req.on('close', common.mustCall(() => {
1071cb0ef41Sopenharmony_ci    client.destroy();
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci    if (!tests.length) {
1101cb0ef41Sopenharmony_ci      server.close();
1111cb0ef41Sopenharmony_ci    } else {
1121cb0ef41Sopenharmony_ci      runTest(tests.shift());
1131cb0ef41Sopenharmony_ci    }
1141cb0ef41Sopenharmony_ci  }));
1151cb0ef41Sopenharmony_ci}
116