11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciif (!common.hasCrypto)
51cb0ef41Sopenharmony_ci  common.skip('missing crypto');
61cb0ef41Sopenharmony_ciconst assert = require('assert');
71cb0ef41Sopenharmony_ciconst h2 = require('http2');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciconst server = h2.createServer();
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciserver.on(
121cb0ef41Sopenharmony_ci  'stream',
131cb0ef41Sopenharmony_ci  common.mustCall((stream) => {
141cb0ef41Sopenharmony_ci    const assertSettings = (settings) => {
151cb0ef41Sopenharmony_ci      assert.strictEqual(typeof settings, 'object');
161cb0ef41Sopenharmony_ci      assert.strictEqual(typeof settings.headerTableSize, 'number');
171cb0ef41Sopenharmony_ci      assert.strictEqual(typeof settings.enablePush, 'boolean');
181cb0ef41Sopenharmony_ci      assert.strictEqual(typeof settings.initialWindowSize, 'number');
191cb0ef41Sopenharmony_ci      assert.strictEqual(typeof settings.maxFrameSize, 'number');
201cb0ef41Sopenharmony_ci      assert.strictEqual(typeof settings.maxConcurrentStreams, 'number');
211cb0ef41Sopenharmony_ci      assert.strictEqual(typeof settings.maxHeaderListSize, 'number');
221cb0ef41Sopenharmony_ci      assert.strictEqual(typeof settings.maxHeaderSize, 'number');
231cb0ef41Sopenharmony_ci    };
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci    const localSettings = stream.session.localSettings;
261cb0ef41Sopenharmony_ci    const remoteSettings = stream.session.remoteSettings;
271cb0ef41Sopenharmony_ci    assertSettings(localSettings);
281cb0ef41Sopenharmony_ci    assertSettings(remoteSettings);
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci    // Test that stored settings are returned when called for second time
311cb0ef41Sopenharmony_ci    assert.strictEqual(stream.session.localSettings, localSettings);
321cb0ef41Sopenharmony_ci    assert.strictEqual(stream.session.remoteSettings, remoteSettings);
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci    stream.respond({
351cb0ef41Sopenharmony_ci      'content-type': 'text/html',
361cb0ef41Sopenharmony_ci      ':status': 200
371cb0ef41Sopenharmony_ci    });
381cb0ef41Sopenharmony_ci    stream.end('hello world');
391cb0ef41Sopenharmony_ci  })
401cb0ef41Sopenharmony_ci);
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ciserver.on('session', (session) => {
431cb0ef41Sopenharmony_ci  session.settings({
441cb0ef41Sopenharmony_ci    maxConcurrentStreams: 2
451cb0ef41Sopenharmony_ci  });
461cb0ef41Sopenharmony_ci});
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ciserver.listen(
491cb0ef41Sopenharmony_ci  0,
501cb0ef41Sopenharmony_ci  common.mustCall(() => {
511cb0ef41Sopenharmony_ci    const client = h2.connect(`http://localhost:${server.address().port}`, {
521cb0ef41Sopenharmony_ci      settings: {
531cb0ef41Sopenharmony_ci        enablePush: false,
541cb0ef41Sopenharmony_ci        initialWindowSize: 123456
551cb0ef41Sopenharmony_ci      }
561cb0ef41Sopenharmony_ci    });
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci    client.on(
591cb0ef41Sopenharmony_ci      'localSettings',
601cb0ef41Sopenharmony_ci      common.mustCall((settings) => {
611cb0ef41Sopenharmony_ci        assert(settings);
621cb0ef41Sopenharmony_ci        assert.strictEqual(settings.enablePush, false);
631cb0ef41Sopenharmony_ci        assert.strictEqual(settings.initialWindowSize, 123456);
641cb0ef41Sopenharmony_ci        assert.strictEqual(settings.maxFrameSize, 16384);
651cb0ef41Sopenharmony_ci      }, 2)
661cb0ef41Sopenharmony_ci    );
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci    let calledOnce = false;
691cb0ef41Sopenharmony_ci    client.on(
701cb0ef41Sopenharmony_ci      'remoteSettings',
711cb0ef41Sopenharmony_ci      common.mustCall((settings) => {
721cb0ef41Sopenharmony_ci        assert(settings);
731cb0ef41Sopenharmony_ci        assert.strictEqual(
741cb0ef41Sopenharmony_ci          settings.maxConcurrentStreams,
751cb0ef41Sopenharmony_ci          calledOnce ? 2 : (2 ** 32) - 1
761cb0ef41Sopenharmony_ci        );
771cb0ef41Sopenharmony_ci        calledOnce = true;
781cb0ef41Sopenharmony_ci      }, 2)
791cb0ef41Sopenharmony_ci    );
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci    const headers = { ':path': '/' };
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci    const req = client.request(headers);
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci    req.on('ready', common.mustCall(() => {
861cb0ef41Sopenharmony_ci      // pendingSettingsAck will be true if a SETTINGS frame
871cb0ef41Sopenharmony_ci      // has been sent but we are still waiting for an acknowledgement
881cb0ef41Sopenharmony_ci      assert(client.pendingSettingsAck);
891cb0ef41Sopenharmony_ci    }));
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci    // State will only be valid after connect event is emitted
921cb0ef41Sopenharmony_ci    req.on('ready', common.mustCall(() => {
931cb0ef41Sopenharmony_ci      client.settings({ maxHeaderListSize: 1 }, common.mustCall());
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci      // Verify valid error ranges
961cb0ef41Sopenharmony_ci      [
971cb0ef41Sopenharmony_ci        ['headerTableSize', -1],
981cb0ef41Sopenharmony_ci        ['headerTableSize', 2 ** 32],
991cb0ef41Sopenharmony_ci        ['initialWindowSize', -1],
1001cb0ef41Sopenharmony_ci        ['initialWindowSize', 2 ** 32],
1011cb0ef41Sopenharmony_ci        ['maxFrameSize', 16383],
1021cb0ef41Sopenharmony_ci        ['maxFrameSize', 2 ** 24],
1031cb0ef41Sopenharmony_ci        ['maxHeaderListSize', -1],
1041cb0ef41Sopenharmony_ci        ['maxHeaderListSize', 2 ** 32],
1051cb0ef41Sopenharmony_ci        ['maxHeaderSize', -1],
1061cb0ef41Sopenharmony_ci        ['maxHeaderSize', 2 ** 32],
1071cb0ef41Sopenharmony_ci      ].forEach((i) => {
1081cb0ef41Sopenharmony_ci        const settings = {};
1091cb0ef41Sopenharmony_ci        settings[i[0]] = i[1];
1101cb0ef41Sopenharmony_ci        assert.throws(
1111cb0ef41Sopenharmony_ci          () => client.settings(settings),
1121cb0ef41Sopenharmony_ci          {
1131cb0ef41Sopenharmony_ci            name: 'RangeError',
1141cb0ef41Sopenharmony_ci            code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
1151cb0ef41Sopenharmony_ci            message: `Invalid value for setting "${i[0]}": ${i[1]}`
1161cb0ef41Sopenharmony_ci          }
1171cb0ef41Sopenharmony_ci        );
1181cb0ef41Sopenharmony_ci      });
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci      // Error checks for enablePush
1211cb0ef41Sopenharmony_ci      [1, {}, 'test', [], null, Infinity, NaN].forEach((i) => {
1221cb0ef41Sopenharmony_ci        assert.throws(
1231cb0ef41Sopenharmony_ci          () => client.settings({ enablePush: i }),
1241cb0ef41Sopenharmony_ci          {
1251cb0ef41Sopenharmony_ci            name: 'TypeError',
1261cb0ef41Sopenharmony_ci            code: 'ERR_HTTP2_INVALID_SETTING_VALUE',
1271cb0ef41Sopenharmony_ci            message: `Invalid value for setting "enablePush": ${i}`
1281cb0ef41Sopenharmony_ci          }
1291cb0ef41Sopenharmony_ci        );
1301cb0ef41Sopenharmony_ci      });
1311cb0ef41Sopenharmony_ci    }));
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci    req.on('response', common.mustCall());
1341cb0ef41Sopenharmony_ci    req.resume();
1351cb0ef41Sopenharmony_ci    req.on('end', common.mustCall(() => {
1361cb0ef41Sopenharmony_ci      server.close();
1371cb0ef41Sopenharmony_ci      client.close();
1381cb0ef41Sopenharmony_ci    }));
1391cb0ef41Sopenharmony_ci    req.end();
1401cb0ef41Sopenharmony_ci  })
1411cb0ef41Sopenharmony_ci);
142