| // Flags: --expose-internals |
| 'use strict'; |
| |
| const common = require('../common'); |
| if (!common.hasQuic) |
| common.skip('missing quic'); |
| const { |
| throws, |
| } = require('node:assert'); |
| |
| const { internalBinding } = require('internal/test/binding'); |
| const quic = internalBinding('quic'); |
| |
| quic.setCallbacks({ |
| onEndpointClose() {}, |
| onSessionNew() {}, |
| onSessionClose() {}, |
| onSessionDatagram() {}, |
| onSessionDatagramStatus() {}, |
| onSessionHandshake() {}, |
| onSessionPathValidation() {}, |
| onSessionTicket() {}, |
| onSessionVersionNegotiation() {}, |
| onStreamCreated() {}, |
| onStreamBlocked() {}, |
| onStreamClose() {}, |
| onStreamReset() {}, |
| onStreamHeaders() {}, |
| onStreamTrailers() {}, |
| }); |
| |
| throws(() => new quic.Endpoint(), { |
| code: 'ERR_INVALID_ARG_TYPE', |
| message: 'options must be an object' |
| }); |
| |
| throws(() => new quic.Endpoint('a'), { |
| code: 'ERR_INVALID_ARG_TYPE', |
| message: 'options must be an object' |
| }); |
| |
| throws(() => new quic.Endpoint(null), { |
| code: 'ERR_INVALID_ARG_TYPE', |
| message: 'options must be an object' |
| }); |
| |
| throws(() => new quic.Endpoint(false), { |
| code: 'ERR_INVALID_ARG_TYPE', |
| message: 'options must be an object' |
| }); |
| |
| { |
| // Just Works... using all defaults |
| new quic.Endpoint({}); |
| } |
| |
| const cases = [ |
| { |
| key: 'retryTokenExpiration', |
| valid: [ |
| 1, 10, 100, 1000, 10000, 10000n, |
| ], |
| invalid: [-1, -1n, 'a', null, false, true, {}, [], () => {}] |
| }, |
| { |
| key: 'tokenExpiration', |
| valid: [ |
| 1, 10, 100, 1000, 10000, 10000n, |
| ], |
| invalid: [-1, -1n, 'a', null, false, true, {}, [], () => {}] |
| }, |
| { |
| key: 'maxConnectionsPerHost', |
| valid: [ |
| 1, 10, 100, 1000, 10000, 10000n, |
| ], |
| invalid: [-1, -1n, 'a', null, false, true, {}, [], () => {}] |
| }, |
| { |
| key: 'maxConnectionsTotal', |
| valid: [ |
| 1, 10, 100, 1000, 10000, 10000n, |
| ], |
| invalid: [-1, -1n, 'a', null, false, true, {}, [], () => {}] |
| }, |
| { |
| key: 'maxStatelessResetsPerHost', |
| valid: [ |
| 1, 10, 100, 1000, 10000, 10000n, |
| ], |
| invalid: [-1, -1n, 'a', null, false, true, {}, [], () => {}] |
| }, |
| { |
| key: 'addressLRUSize', |
| valid: [ |
| 1, 10, 100, 1000, 10000, 10000n, |
| ], |
| invalid: [-1, -1n, 'a', null, false, true, {}, [], () => {}] |
| }, |
| { |
| key: 'maxRetries', |
| valid: [ |
| 1, 10, 100, 1000, 10000, 10000n, |
| ], |
| invalid: [-1, -1n, 'a', null, false, true, {}, [], () => {}] |
| }, |
| { |
| key: 'maxPayloadSize', |
| valid: [ |
| 1, 10, 100, 1000, 10000, 10000n, |
| ], |
| invalid: [-1, -1n, 'a', null, false, true, {}, [], () => {}] |
| }, |
| { |
| key: 'unacknowledgedPacketThreshold', |
| valid: [ |
| 1, 10, 100, 1000, 10000, 10000n, |
| ], |
| invalid: [-1, -1n, 'a', null, false, true, {}, [], () => {}] |
| }, |
| { |
| key: 'validateAddress', |
| valid: [true, false, 0, 1, 'a'], |
| invalid: [], |
| }, |
| { |
| key: 'disableStatelessReset', |
| valid: [true, false, 0, 1, 'a'], |
| invalid: [], |
| }, |
| { |
| key: 'ipv6Only', |
| valid: [true, false, 0, 1, 'a'], |
| invalid: [], |
| }, |
| { |
| key: 'cc', |
| valid: [ |
| quic.CC_ALGO_RENO, |
| quic.CC_ALGO_CUBIC, |
| quic.CC_ALGO_BBR, |
| quic.CC_ALGO_BBR2, |
| quic.CC_ALGO_RENO_STR, |
| quic.CC_ALGO_CUBIC_STR, |
| quic.CC_ALGO_BBR_STR, |
| quic.CC_ALGO_BBR2_STR, |
| ], |
| invalid: [-1, 4, 1n, 'a', null, false, true, {}, [], () => {}], |
| }, |
| { |
| key: 'udpReceiveBufferSize', |
| valid: [0, 1, 2, 3, 4, 1000], |
| invalid: [-1, 'a', null, false, true, {}, [], () => {}], |
| }, |
| { |
| key: 'udpSendBufferSize', |
| valid: [0, 1, 2, 3, 4, 1000], |
| invalid: [-1, 'a', null, false, true, {}, [], () => {}], |
| }, |
| { |
| key: 'udpTTL', |
| valid: [0, 1, 2, 3, 4, 255], |
| invalid: [-1, 256, 'a', null, false, true, {}, [], () => {}], |
| }, |
| { |
| key: 'resetTokenSecret', |
| valid: [ |
| new Uint8Array(16), |
| new Uint16Array(8), |
| new Uint32Array(4), |
| ], |
| invalid: [ |
| 'a', null, false, true, {}, [], () => {}, |
| new Uint8Array(15), |
| new Uint8Array(17), |
| new ArrayBuffer(16), |
| ], |
| }, |
| { |
| key: 'tokenSecret', |
| valid: [ |
| new Uint8Array(16), |
| new Uint16Array(8), |
| new Uint32Array(4), |
| ], |
| invalid: [ |
| 'a', null, false, true, {}, [], () => {}, |
| new Uint8Array(15), |
| new Uint8Array(17), |
| new ArrayBuffer(16), |
| ], |
| }, |
| { |
| // Unknown options are ignored entirely for any value type |
| key: 'ignored', |
| valid: ['a', null, false, true, {}, [], () => {}], |
| invalid: [], |
| }, |
| ]; |
| |
| for (const { key, valid, invalid } of cases) { |
| for (const value of valid) { |
| const options = {}; |
| options[key] = value; |
| new quic.Endpoint(options); |
| } |
| |
| for (const value of invalid) { |
| const options = {}; |
| options[key] = value; |
| throws(() => new quic.Endpoint(options), { |
| code: 'ERR_INVALID_ARG_VALUE', |
| }); |
| } |
| } |