File
Blob: src/workerd/api/node/tests/net-nodejs-test.js
| 1 | // Copyright (c) 2017-2022 Cloudflare, Inc. |
| 2 | // Licensed under the Apache 2.0 license found in the LICENSE file or at: |
| 3 | // https://opensource.org/licenses/Apache-2.0 |
| 4 | // |
| 5 | // Copyright Joyent, Inc. and other Node contributors. |
| 6 | // |
| 7 | // Permission is hereby granted, free of charge, to any person obtaining a |
| 8 | // copy of this software and associated documentation files (the |
| 9 | // "Software"), to deal in the Software without restriction, including |
| 10 | // without limitation the rights to use, copy, modify, merge, publish, |
| 11 | // distribute, sublicense, and/or sell copies of the Software, and to permit |
| 12 | // persons to whom the Software is furnished to do so, subject to the |
| 13 | // following conditions: |
| 14 | // |
| 15 | // The above copyright notice and this permission notice shall be included |
| 16 | // in all copies or substantial portions of the Software. |
| 17 | // |
| 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
| 21 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
| 22 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT ORs |
| 23 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| 24 | // USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | |
| 26 | import { fail, ok, strictEqual, deepStrictEqual, throws } from 'node:assert'; |
| 27 | import { mock } from 'node:test'; |
| 28 | import { once } from 'node:events'; |
| 29 | import * as net from 'node:net'; |
| 30 | import * as tls from 'node:tls'; |
| 31 | |
| 32 | export const checkPortsSetCorrectly = { |
| 33 | test(ctrl, env, ctx) { |
| 34 | const keys = [ |
| 35 | 'SIDECAR_HOSTNAME', |
| 36 | 'SERVER_PORT', |
| 37 | 'ECHO_SERVER_PORT', |
| 38 | 'TIMEOUT_SERVER_PORT', |
| 39 | 'END_SERVER_PORT', |
| 40 | 'SERVER_THAT_DIES_PORT', |
| 41 | 'RECONNECT_SERVER_PORT', |
| 42 | ]; |
| 43 | for (const key of keys) { |
| 44 | strictEqual(typeof env[key], 'string'); |
| 45 | ok(env[key].length > 0); |
| 46 | } |
| 47 | }, |
| 48 | }; |
| 49 | |
| 50 | // test/parallel/test-net-access-byteswritten.js |
| 51 | export const testNetAccessBytesWritten = { |
| 52 | test() { |
| 53 | // Check that the bytesWritten getter doesn't crash if object isn't |
| 54 | // constructed. |
| 55 | strictEqual(net.Socket.prototype.bytesWritten, undefined); |
| 56 | strictEqual( |
| 57 | Object.getPrototypeOf(tls.TLSSocket).prototype.bytesWritten, |
| 58 | undefined |
| 59 | ); |
| 60 | strictEqual(tls.TLSSocket.prototype.bytesWritten, undefined); |
| 61 | }, |
| 62 | }; |
| 63 | |
| 64 | // test/parallel/test-net-after-close.js |
| 65 | export const testNetAfterClose = { |
| 66 | async test(ctrl, env, ctx) { |
| 67 | const { promise, resolve } = Promise.withResolvers(); |
| 68 | const c = net.connect(Number(env.SERVER_PORT), env.SIDECAR_HOSTNAME); |
| 69 | c.resume(); |
| 70 | c.on('close', () => resolve()); |
| 71 | await promise; |
| 72 | |
| 73 | // Calling functions / accessing properties of a closed socket should not throw |
| 74 | c.setNoDelay(); |
| 75 | c.setKeepAlive(); |
| 76 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions |
| 77 | c.bufferSize; |
| 78 | c.pause(); |
| 79 | c.resume(); |
| 80 | c.address(); |
| 81 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions |
| 82 | c.remoteAddress; |
| 83 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions |
| 84 | c.remotePort; |
| 85 | }, |
| 86 | }; |
| 87 | |
| 88 | // test/parallel/test-net-allow-half-open.js |
| 89 | export const testNetAllowHalfOpen = { |
| 90 | async test(ctrl, env, ctx) { |
| 91 | // Verify that the socket closes properly when the other end closes |
| 92 | // and allowHalfOpen is false. |
| 93 | |
| 94 | const { promise, resolve } = Promise.withResolvers(); |
| 95 | const c = net.connect(Number(env.SERVER_PORT), env.SIDECAR_HOSTNAME); |
| 96 | strictEqual(c.allowHalfOpen, false); |
| 97 | c.resume(); |
| 98 | |
| 99 | const endFn = mock.fn(() => { |
| 100 | queueMicrotask(() => { |
| 101 | ok(!c.destroyed); |
| 102 | }); |
| 103 | }); |
| 104 | const finishFn = mock.fn(() => { |
| 105 | ok(!c.destroyed); |
| 106 | }); |
| 107 | const closeFn = mock.fn(resolve); |
| 108 | c.on('end', endFn); |
| 109 | |
| 110 | // Even tho we're not writing anything, since the socket receives a |
| 111 | // EOS and allowHalfOpen is false, the socket should close both the |
| 112 | // readable and writable sides, meaning we should definitely get a |
| 113 | // finish event. |
| 114 | c.on('finish', finishFn); |
| 115 | c.on('close', closeFn); |
| 116 | await promise; |
| 117 | strictEqual(endFn.mock.callCount(), 1); |
| 118 | strictEqual(finishFn.mock.callCount(), 1); |
| 119 | strictEqual(closeFn.mock.callCount(), 1); |
| 120 | }, |
| 121 | }; |
| 122 | |
| 123 | // test/parallel/test-net-better-error-messages-port-hostname.js |
| 124 | export const testNetBetterErrorMessagesPortHostname = { |
| 125 | async test() { |
| 126 | // This is intentionally not a completely faithful reproduction of the |
| 127 | // original test, as we don't have the ability to mock DNS lookups. |
| 128 | const { promise, resolve, reject } = Promise.withResolvers(); |
| 129 | const c = net.connect(0, 'invalid address'); |
| 130 | c.on('connect', () => { |
| 131 | reject(new Error('should not connect')); |
| 132 | }); |
| 133 | const errorFn = mock.fn((error) => { |
| 134 | // TODO(review): Currently our errors do not match the errors that |
| 135 | // Node.js produces. Do we need them to? Specifically, in a case like |
| 136 | // this, Node.js' error would have a meaningful `code` property along |
| 137 | // with `hostname` and `syscall` properties. We, instead, are passing |
| 138 | // along the underlying error returned from the internal Socket API. |
| 139 | try { |
| 140 | strictEqual(error.message, 'Specified address could not be parsed.'); |
| 141 | } catch (err) { |
| 142 | console.log(err.message); |
| 143 | } |
| 144 | resolve(); |
| 145 | }); |
| 146 | c.on('error', errorFn); |
| 147 | await promise; |
| 148 | strictEqual(errorFn.mock.callCount(), 1); |
| 149 | }, |
| 150 | }; |
| 151 | |
| 152 | // test/parallel/test-net-binary.js |
| 153 | export const testNetBinary = { |
| 154 | async test(ctrl, env, ctx) { |
| 155 | const { promise, resolve } = Promise.withResolvers(); |
| 156 | |
| 157 | // Connect to the echo server |
| 158 | const c = net.connect(env.ECHO_SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 159 | c.setEncoding('latin1'); |
| 160 | let result = ''; |
| 161 | c.on('data', (chunk) => { |
| 162 | result += chunk; |
| 163 | }); |
| 164 | |
| 165 | let binaryString = ''; |
| 166 | for (let i = 255; i >= 0; i--) { |
| 167 | c.write(String.fromCharCode(i), 'latin1'); |
| 168 | binaryString += String.fromCharCode(i); |
| 169 | } |
| 170 | c.end(); |
| 171 | c.on('close', () => { |
| 172 | resolve(); |
| 173 | }); |
| 174 | await promise; |
| 175 | strictEqual(result, binaryString); |
| 176 | }, |
| 177 | }; |
| 178 | |
| 179 | // test/parallel/test-net-buffersize.js |
| 180 | export const testNetBuffersize = { |
| 181 | async test(ctrl, env, ctx) { |
| 182 | const { promise, resolve } = Promise.withResolvers(); |
| 183 | const c = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 184 | const finishFn = mock.fn(() => { |
| 185 | strictEqual(c.bufferSize, 0); |
| 186 | resolve(); |
| 187 | }); |
| 188 | c.on('finish', finishFn); |
| 189 | |
| 190 | strictEqual(c.bufferSize, 0); |
| 191 | c.write('a'); |
| 192 | c.end(); |
| 193 | strictEqual(c.bufferSize, 1); |
| 194 | await promise; |
| 195 | strictEqual(finishFn.mock.callCount(), 1); |
| 196 | }, |
| 197 | }; |
| 198 | |
| 199 | // test/parallel/test-net-bytes-read.js |
| 200 | export const testNetBytesRead = { |
| 201 | async test(ctrl, env, ctx) { |
| 202 | const { promise, resolve } = Promise.withResolvers(); |
| 203 | // Connect to the echo server |
| 204 | const c = net.connect(env.ECHO_SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 205 | c.resume(); |
| 206 | c.write('hello'); |
| 207 | c.end(); |
| 208 | const endFn = mock.fn(() => { |
| 209 | strictEqual(c.bytesRead, 5); |
| 210 | resolve(); |
| 211 | }); |
| 212 | c.on('end', endFn); |
| 213 | |
| 214 | await promise; |
| 215 | |
| 216 | strictEqual(endFn.mock.callCount(), 1); |
| 217 | }, |
| 218 | }; |
| 219 | |
| 220 | export const testNetBytesStats = { |
| 221 | async test(ctrl, env) { |
| 222 | // This is intentionally not a completely faithful reproduction of the |
| 223 | // original test which checks the bytesRead on the server side. |
| 224 | // Connect to the echo server |
| 225 | const { promise, resolve } = Promise.withResolvers(); |
| 226 | const c = net.connect(env.ECHO_SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 227 | let bytesDelivered = 0; |
| 228 | c.on('data', (chunk) => (bytesDelivered += chunk.byteLength)); |
| 229 | c.write('hello'); |
| 230 | c.end(); |
| 231 | const endFn = mock.fn(() => { |
| 232 | strictEqual(c.bytesWritten, 0); |
| 233 | strictEqual(bytesDelivered, 5); |
| 234 | strictEqual(c.bytesRead, 5); |
| 235 | resolve(); |
| 236 | }); |
| 237 | c.on('end', endFn); |
| 238 | |
| 239 | await promise; |
| 240 | strictEqual(endFn.mock.callCount(), 1); |
| 241 | }, |
| 242 | }; |
| 243 | |
| 244 | // test/parallel/test-net-bytes-written-large.js |
| 245 | const N = 10000000; |
| 246 | export const testNetBytesWrittenLargeVariant1 = { |
| 247 | async test(ctrl, env, ctx) { |
| 248 | const { promise, resolve } = Promise.withResolvers(); |
| 249 | const c = net.connect(env.ECHO_SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 250 | c.resume(); |
| 251 | |
| 252 | const writeFn = mock.fn(() => { |
| 253 | strictEqual(c.bytesWritten, N); |
| 254 | resolve(); |
| 255 | }); |
| 256 | |
| 257 | c.end(Buffer.alloc(N), writeFn); |
| 258 | |
| 259 | await promise; |
| 260 | }, |
| 261 | }; |
| 262 | |
| 263 | // test/parallel/test-net-can-reset-timeout.js |
| 264 | export const testNetCanResetTimeout = { |
| 265 | async test(ctrl, env, ctx) { |
| 266 | const { promise, resolve } = Promise.withResolvers(); |
| 267 | const c = net.connect(env.TIMEOUT_SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 268 | const dataFn = mock.fn(() => { |
| 269 | c.end(); |
| 270 | }); |
| 271 | c.on('data', dataFn); |
| 272 | c.on('end', resolve); |
| 273 | |
| 274 | await promise; |
| 275 | |
| 276 | strictEqual(dataFn.mock.callCount(), 1); |
| 277 | }, |
| 278 | }; |
| 279 | |
| 280 | async function assertAbort(socket, testName) { |
| 281 | try { |
| 282 | await once(socket, 'close'); |
| 283 | fail(`close ${testName} should have thrown`); |
| 284 | } catch (err) { |
| 285 | strictEqual(err.name, 'AbortError', err.message); |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | // test/parallel/test-net-connect-abort-controller.js |
| 290 | export const testNetConnectAbortControllerPostAbort = { |
| 291 | async test(ctrl, env, ctx) { |
| 292 | const ac = new AbortController(); |
| 293 | const { signal } = ac; |
| 294 | const socket = net.connect({ |
| 295 | host: env.SIDECAR_HOSTNAME, |
| 296 | port: env.SERVER_PORT, |
| 297 | signal, |
| 298 | }); |
| 299 | ac.abort(); |
| 300 | await assertAbort(socket, 'postAbort'); |
| 301 | }, |
| 302 | }; |
| 303 | |
| 304 | export const testNetConnectAbortControllerPreAbort = { |
| 305 | async test(ctrl, env, ctx) { |
| 306 | const ac = new AbortController(); |
| 307 | const { signal } = ac; |
| 308 | ac.abort(); |
| 309 | const socket = net.connect({ |
| 310 | host: env.SIDECAR_HOSTNAME, |
| 311 | port: env.SERVER_PORT, |
| 312 | signal, |
| 313 | }); |
| 314 | await assertAbort(socket, 'preAbort'); |
| 315 | }, |
| 316 | }; |
| 317 | |
| 318 | export const testNetConnectAbortControllerTickAbort = { |
| 319 | async test(ctrl, env, ctx) { |
| 320 | const ac = new AbortController(); |
| 321 | const { signal } = ac; |
| 322 | queueMicrotask(() => ac.abort()); |
| 323 | const socket = net.connect({ |
| 324 | host: env.SIDECAR_HOSTNAME, |
| 325 | port: env.SERVER_PORT, |
| 326 | signal, |
| 327 | }); |
| 328 | await assertAbort(socket, 'tickAbort'); |
| 329 | }, |
| 330 | }; |
| 331 | |
| 332 | export const testNetConnectAbortControllerConstructor = { |
| 333 | async test() { |
| 334 | const ac = new AbortController(); |
| 335 | const { signal } = ac; |
| 336 | ac.abort(); |
| 337 | const socket = new net.Socket({ signal }); |
| 338 | await assertAbort(socket, 'testConstructor'); |
| 339 | }, |
| 340 | }; |
| 341 | |
| 342 | export const testNetConnectAbortControllerConstructorPost = { |
| 343 | async test() { |
| 344 | const ac = new AbortController(); |
| 345 | const { signal } = ac; |
| 346 | const socket = new net.Socket({ signal }); |
| 347 | ac.abort(); |
| 348 | await assertAbort(socket, 'testConstructorPost'); |
| 349 | }, |
| 350 | }; |
| 351 | |
| 352 | export const testNetConnectAbortControllerConstructorPostTick = { |
| 353 | async test() { |
| 354 | const ac = new AbortController(); |
| 355 | const { signal } = ac; |
| 356 | queueMicrotask(() => ac.abort()); |
| 357 | const socket = new net.Socket({ signal }); |
| 358 | await assertAbort(socket, 'testConstructorPostTick'); |
| 359 | }, |
| 360 | }; |
| 361 | |
| 362 | // test/parallel/test-net-connect-after-destroy.js |
| 363 | export const testNetConnectAfterDestroy = { |
| 364 | async test() { |
| 365 | // Connect to something that we need to lookup, then delay |
| 366 | // the lookup so that the connect attempt happens after the |
| 367 | // destroy |
| 368 | const lookup = mock.fn((host, options, callback) => { |
| 369 | setTimeout(() => callback(null, 'localhost'), 100); |
| 370 | }); |
| 371 | const c = net.connect({ |
| 372 | port: 80, |
| 373 | host: 'example.org', |
| 374 | lookup, |
| 375 | }); |
| 376 | c.on('connect', () => { |
| 377 | throw new Error('should not connect'); |
| 378 | }); |
| 379 | c.destroy(); |
| 380 | strictEqual(c.destroyed, true); |
| 381 | strictEqual(lookup.mock.callCount(), 1); |
| 382 | }, |
| 383 | }; |
| 384 | |
| 385 | // test/parallel/test-net-connect-buffer.js |
| 386 | export const testNetConnectBuffer = { |
| 387 | async test(ctrl, env, ctx) { |
| 388 | const { promise, resolve } = Promise.withResolvers(); |
| 389 | const c = net.connect({ |
| 390 | port: env.ECHO_SERVER_PORT, |
| 391 | host: env.SIDECAR_HOSTNAME, |
| 392 | highWaterMark: 0, |
| 393 | }); |
| 394 | |
| 395 | strictEqual(c.pending, true); |
| 396 | strictEqual(c.connecting, true); |
| 397 | strictEqual(c.readyState, 'opening'); |
| 398 | strictEqual(c.bytesWritten, 0); |
| 399 | |
| 400 | // Write a string that contains a multi-byte character sequence to test that |
| 401 | // `bytesWritten` is incremented with the # of bytes, not # of characters. |
| 402 | const a = "L'รtat, c'est "; |
| 403 | const b = 'moi'; |
| 404 | |
| 405 | let result = ''; |
| 406 | c.setEncoding('utf8'); |
| 407 | c.on('data', (chunk) => { |
| 408 | result += chunk; |
| 409 | }); |
| 410 | const endFn = mock.fn(() => { |
| 411 | strictEqual(result, a + b); |
| 412 | }); |
| 413 | c.on('end', endFn); |
| 414 | |
| 415 | const writeFn = mock.fn(() => { |
| 416 | strictEqual(c.pending, false); |
| 417 | strictEqual(c.connecting, false); |
| 418 | strictEqual(c.readyState, 'readOnly'); |
| 419 | strictEqual(c.bytesWritten, Buffer.from(a + b).length); |
| 420 | }); |
| 421 | c.write(a, writeFn); |
| 422 | |
| 423 | const closeFn = mock.fn(() => { |
| 424 | resolve(); |
| 425 | }); |
| 426 | c.on('close', closeFn); |
| 427 | |
| 428 | c.end(b); |
| 429 | |
| 430 | await promise; |
| 431 | strictEqual(closeFn.mock.callCount(), 1); |
| 432 | strictEqual(writeFn.mock.callCount(), 1); |
| 433 | strictEqual(endFn.mock.callCount(), 1); |
| 434 | }, |
| 435 | }; |
| 436 | |
| 437 | // test/parallel/test-net-connect-destroy.js |
| 438 | export const testNetConnectDestroy = { |
| 439 | async test(ctrl, env, ctx) { |
| 440 | const { promise, resolve } = Promise.withResolvers(); |
| 441 | const c = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 442 | c.on('close', () => resolve()); |
| 443 | c.destroy(); |
| 444 | await promise; |
| 445 | }, |
| 446 | }; |
| 447 | |
| 448 | // test/parallel/test-net-connect-immediate-destroy.js |
| 449 | export const testNetConnectImmediateDestroy = { |
| 450 | async test(ctrl, env, ctx) { |
| 451 | const connectFn = mock.fn(); |
| 452 | const socket = net.connect( |
| 453 | env.SERVER_PORT, |
| 454 | env.SIDECAR_HOSTNAME, |
| 455 | connectFn |
| 456 | ); |
| 457 | socket.destroy(); |
| 458 | await Promise.resolve(); |
| 459 | strictEqual(connectFn.mock.callCount(), 0); |
| 460 | }, |
| 461 | }; |
| 462 | |
| 463 | // test/parallel/test-net-connect-immediate-finish.js |
| 464 | export const testNetConnectImmediateFinish = { |
| 465 | async text(ctrl, env, ctx) { |
| 466 | const { promise, resolve } = Promise.withResolvers(); |
| 467 | const c = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 468 | c.end(); |
| 469 | c.on('finish', () => resolve()); |
| 470 | await promise; |
| 471 | }, |
| 472 | }; |
| 473 | |
| 474 | // test/parallel/test-net-connect-keepalive.js |
| 475 | // test/parallel/test-net-keepalive.js |
| 476 | // We don't actually support keep alive so this test does |
| 477 | // something different than the original Node.js test |
| 478 | export const testNetConnectKeepAlive = { |
| 479 | async test() { |
| 480 | // We are not throwing on truthy keepAlive value for mysql/redis clients. |
| 481 | // throws(() => new net.Socket({ keepAlive: true })); |
| 482 | const c = new net.Socket(); |
| 483 | c.setKeepAlive(false); |
| 484 | c.setKeepAlive(true); |
| 485 | // throws(() => c.setKeepAlive(true)); |
| 486 | }, |
| 487 | }; |
| 488 | |
| 489 | // test/parallel/test-net-connect-memleak.js |
| 490 | export const testNetConnectMemleak = { |
| 491 | async test(ctrl, env, ctx) { |
| 492 | const { promise, resolve } = Promise.withResolvers(); |
| 493 | const connectFn = mock.fn(() => resolve()); |
| 494 | const c = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME, connectFn); |
| 495 | c.emit('connect'); |
| 496 | await promise; |
| 497 | strictEqual(connectFn.mock.callCount(), 1); |
| 498 | }, |
| 499 | }; |
| 500 | |
| 501 | // test/parallel/test-net-connect-no-arg.js |
| 502 | export const testNetConnectNoArg = { |
| 503 | test() { |
| 504 | throws(() => net.connect(), { |
| 505 | code: 'ERR_MISSING_ARGS', |
| 506 | message: 'The "options" or "port" or "path" argument must be specified', |
| 507 | }); |
| 508 | throws(() => new net.Socket().connect(), { |
| 509 | code: 'ERR_MISSING_ARGS', |
| 510 | message: 'The "options" or "port" or "path" argument must be specified', |
| 511 | }); |
| 512 | throws(() => net.connect({}), { |
| 513 | code: 'ERR_MISSING_ARGS', |
| 514 | message: 'The "options" or "port" or "path" argument must be specified', |
| 515 | }); |
| 516 | throws(() => new net.Socket().connect({}), { |
| 517 | code: 'ERR_MISSING_ARGS', |
| 518 | message: 'The "options" or "port" or "path" argument must be specified', |
| 519 | }); |
| 520 | }, |
| 521 | }; |
| 522 | |
| 523 | // test/parallel/test-net-connect-options-allowhalfopen.js |
| 524 | // Simplified version of the equivalent Node.js test |
| 525 | export const testNetConnectOptionsAllowHalfOpen = { |
| 526 | async test(ctrl, env, ctx) { |
| 527 | const { promise, resolve, reject } = Promise.withResolvers(); |
| 528 | const c = net.connect({ |
| 529 | host: env.SIDECAR_HOSTNAME, |
| 530 | port: env.SERVER_PORT, |
| 531 | allowHalfOpen: true, |
| 532 | }); |
| 533 | c.resume(); |
| 534 | const writeFn = mock.fn(() => { |
| 535 | c.write('hello', (err) => { |
| 536 | if (err) reject(err); |
| 537 | resolve(); |
| 538 | }); |
| 539 | }); |
| 540 | const endFn = mock.fn(() => { |
| 541 | strictEqual(c.readable, false); |
| 542 | strictEqual(c.writable, true); |
| 543 | queueMicrotask(writeFn); |
| 544 | }); |
| 545 | c.on('end', endFn); |
| 546 | await promise; |
| 547 | }, |
| 548 | }; |
| 549 | |
| 550 | // test/parallel/test-net-connect-options-fd.js |
| 551 | // We do not support the fd option so this test does something different |
| 552 | // than the original Node.js test |
| 553 | export const testNetConnectOptionsFd = { |
| 554 | async test() { |
| 555 | throws(() => new net.Socket({ fd: 42 })); |
| 556 | }, |
| 557 | }; |
| 558 | |
| 559 | // test/parallel/test-net-connect-options-invalid.js |
| 560 | export const testNetConnectOptionsInvalid = { |
| 561 | test() { |
| 562 | ['objectMode', 'readableObjectMode', 'writableObjectMode'].forEach( |
| 563 | (invalidKey) => { |
| 564 | const option = { |
| 565 | port: 8080, |
| 566 | [invalidKey]: true, |
| 567 | }; |
| 568 | const message = `The property 'options.${invalidKey}' is not supported. Received true`; |
| 569 | |
| 570 | throws(() => net.connect(option), { |
| 571 | code: 'ERR_INVALID_ARG_VALUE', |
| 572 | name: 'TypeError', |
| 573 | message: new RegExp(message), |
| 574 | }); |
| 575 | } |
| 576 | ); |
| 577 | }, |
| 578 | }; |
| 579 | |
| 580 | // test/parallel/test-net-connect-options-ipv6.js |
| 581 | // TODO(soon): sidecar-supervisor assigns IPv4 addresses only. IPv6 support should be added. |
| 582 | /* |
| 583 | export const testNetConnectOptionsIpv6 = { |
| 584 | async test(ctrl, env, ctx) { |
| 585 | const { promise, resolve } = Promise.withResolvers(); |
| 586 | const c = net.connect({ host: '::1', port: env.SERVER_PORT }); |
| 587 | c.on('connect', () => resolve()); |
| 588 | await promise; |
| 589 | }, |
| 590 | }; |
| 591 | */ |
| 592 | |
| 593 | // test/parallel/test-net-connect-options-path.js |
| 594 | // We do not support the path option so this test does something different |
| 595 | // than the original Node.js test |
| 596 | export const testNetConnectOptionsPath = { |
| 597 | async test() { |
| 598 | throws(() => net.connect({ path: '/tmp/sock' })); |
| 599 | }, |
| 600 | }; |
| 601 | |
| 602 | // test/parallel/test-net-connect-options-port.js |
| 603 | // TODO(soon): Update this test. |
| 604 | export const testNetConnectOptionsPort = { |
| 605 | async test() { |
| 606 | [true, false].forEach((port) => { |
| 607 | throws(() => net.connect(port), { |
| 608 | code: 'ERR_INVALID_ARG_TYPE', |
| 609 | name: 'TypeError', |
| 610 | }); |
| 611 | }); |
| 612 | [-1, 65537].forEach((port) => { |
| 613 | throws(() => net.connect(port), { |
| 614 | code: 'ERR_SOCKET_BAD_PORT', |
| 615 | }); |
| 616 | }); |
| 617 | }, |
| 618 | }; |
| 619 | |
| 620 | // test/parallel/test-net-connect-paused-connection.js |
| 621 | // The original test is a bit different given that it uses unref to avoid |
| 622 | // the paused connection from keeping the process alive. We don't have unref |
| 623 | // so let's just make sure things clean up okay when the IoContext is destroyed. |
| 624 | export const testNetConnectPausedConnection = { |
| 625 | test(ctrl, env, ctx) { |
| 626 | net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME).pause(); |
| 627 | }, |
| 628 | }; |
| 629 | |
| 630 | // test/parallel/test-net-connect-reset.js |
| 631 | export const testNetConnectReset = { |
| 632 | async test() { |
| 633 | const { promise, resolve } = Promise.withResolvers(); |
| 634 | const socket = new net.Socket(); |
| 635 | socket.resetAndDestroy(); |
| 636 | // Emit error if socket is not connecting/connected |
| 637 | socket.on('error', (err) => { |
| 638 | strictEqual(err.code, 'ERR_SOCKET_CLOSED'); |
| 639 | strictEqual(err.name, 'Error'); |
| 640 | resolve(); |
| 641 | }); |
| 642 | await promise; |
| 643 | }, |
| 644 | }; |
| 645 | |
| 646 | // test/parallel/test-net-dns-custom-lookup.js |
| 647 | // test/parallel/test-net-dns-lookup.js |
| 648 | export const testNetDnsCustomLookup = { |
| 649 | async test(ctrl, env, ctx) { |
| 650 | const { promise, resolve } = Promise.withResolvers(); |
| 651 | const lookup = mock.fn((host, options, callback) => { |
| 652 | strictEqual(host, 'localhost'); |
| 653 | strictEqual(options.family, 4); |
| 654 | queueMicrotask(() => callback(null, '127.0.0.1', 4)); |
| 655 | }); |
| 656 | const c = net.connect({ |
| 657 | port: env.SERVER_PORT, |
| 658 | host: 'localhost', |
| 659 | lookup, |
| 660 | family: 4, |
| 661 | }); |
| 662 | c.on('lookup', (err, ip, type) => { |
| 663 | strictEqual(err, null); |
| 664 | strictEqual(ip, '127.0.0.1'); |
| 665 | strictEqual(type, 4); |
| 666 | resolve(); |
| 667 | }); |
| 668 | await promise; |
| 669 | strictEqual(lookup.mock.callCount(), 1); |
| 670 | }, |
| 671 | }; |
| 672 | |
| 673 | // test/parallel/test-net-dns-error.js |
| 674 | // This test differs from original Node.js test since our error code for isValidHost |
| 675 | // is different from Node.js. |
| 676 | export const testNetDnsError = { |
| 677 | async test() { |
| 678 | const p1 = Promise.withResolvers(); |
| 679 | const p2 = Promise.withResolvers(); |
| 680 | const host = '*'.repeat(64); |
| 681 | const socket = net.connect(42, host, () => |
| 682 | p1.reject(new Error('Should not have called')) |
| 683 | ); |
| 684 | socket.on('error', function (err) { |
| 685 | strictEqual(err.name, 'TypeError'); |
| 686 | strictEqual( |
| 687 | err.message, |
| 688 | 'Specified address is empty string, contains unsupported characters or is too long.' |
| 689 | ); |
| 690 | p1.resolve(); |
| 691 | }); |
| 692 | socket.on('lookup', function (err, ip, type) { |
| 693 | strictEqual(err.name, 'TypeError'); |
| 694 | strictEqual( |
| 695 | err.message, |
| 696 | 'Specified address is empty string, contains unsupported characters or is too long.' |
| 697 | ); |
| 698 | strictEqual(ip, undefined); |
| 699 | strictEqual(type, undefined); |
| 700 | p2.resolve(); |
| 701 | }); |
| 702 | await Promise.all([p1, p2]); |
| 703 | }, |
| 704 | }; |
| 705 | |
| 706 | // test/parallel/test-net-dns-lookup-skip.js |
| 707 | export const testNetDnsLookupSkip = { |
| 708 | async test(ctrl, env, ctx) { |
| 709 | const lookup = mock.fn(); |
| 710 | [env.SIDECAR_HOSTNAME, '::1'].forEach((host) => { |
| 711 | net.connect({ host, port: env.SERVER_PORT, lookup }).destroy(); |
| 712 | }); |
| 713 | strictEqual(lookup.mock.callCount(), 0); |
| 714 | }, |
| 715 | }; |
| 716 | |
| 717 | // test/parallel/test-net-during-close.js |
| 718 | export const testNetDuringClose = { |
| 719 | test(ctrl, env, ctx) { |
| 720 | const c = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 721 | c.destroy(); |
| 722 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions |
| 723 | c.remoteAddress; |
| 724 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions |
| 725 | c.remoteFamily; |
| 726 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions |
| 727 | c.remotePort; |
| 728 | }, |
| 729 | }; |
| 730 | |
| 731 | // test/parallel/test-net-end-destroyed.js |
| 732 | export const testNetEndDestroyed = { |
| 733 | async test(ctrl, env, ctx) { |
| 734 | const { promise, resolve } = Promise.withResolvers(); |
| 735 | const c = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 736 | c.resume(); |
| 737 | |
| 738 | const endFn = mock.fn(() => { |
| 739 | strictEqual(c.destroyed, false); |
| 740 | resolve(); |
| 741 | }); |
| 742 | c.on('end', endFn); |
| 743 | await promise; |
| 744 | }, |
| 745 | }; |
| 746 | |
| 747 | // test/parallel/test-net-end-without-connect.js |
| 748 | export const testNetEndWithoutConnect = { |
| 749 | async test() { |
| 750 | const { promise, resolve } = Promise.withResolvers(); |
| 751 | const c = new net.Socket(); |
| 752 | const endFn = mock.fn(() => { |
| 753 | strictEqual(c.writable, false); |
| 754 | resolve(); |
| 755 | }); |
| 756 | c.end(endFn); |
| 757 | await promise; |
| 758 | }, |
| 759 | }; |
| 760 | |
| 761 | // test/parallel/test-net-isip.js |
| 762 | export const testNetIsIp = { |
| 763 | test() { |
| 764 | strictEqual(net.isIP('127.0.0.1'), 4); |
| 765 | strictEqual(net.isIP('x127.0.0.1'), 0); |
| 766 | strictEqual(net.isIP('example.com'), 0); |
| 767 | strictEqual(net.isIP('0000:0000:0000:0000:0000:0000:0000:0000'), 6); |
| 768 | strictEqual(net.isIP('0000:0000:0000:0000:0000:0000:0000:0000::0000'), 0); |
| 769 | strictEqual(net.isIP('1050:0:0:0:5:600:300c:326b'), 6); |
| 770 | strictEqual(net.isIP('2001:252:0:1::2008:6'), 6); |
| 771 | strictEqual(net.isIP('2001:dead:beef:1::2008:6'), 6); |
| 772 | strictEqual(net.isIP('2001::'), 6); |
| 773 | strictEqual(net.isIP('2001:dead::'), 6); |
| 774 | strictEqual(net.isIP('2001:dead:beef::'), 6); |
| 775 | strictEqual(net.isIP('2001:dead:beef:1::'), 6); |
| 776 | strictEqual(net.isIP('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'), 6); |
| 777 | strictEqual(net.isIP(':2001:252:0:1::2008:6:'), 0); |
| 778 | strictEqual(net.isIP(':2001:252:0:1::2008:6'), 0); |
| 779 | strictEqual(net.isIP('2001:252:0:1::2008:6:'), 0); |
| 780 | strictEqual(net.isIP('2001:252::1::2008:6'), 0); |
| 781 | strictEqual(net.isIP('::2001:252:1:2008:6'), 6); |
| 782 | strictEqual(net.isIP('::2001:252:1:1.1.1.1'), 6); |
| 783 | strictEqual(net.isIP('::2001:252:1:255.255.255.255'), 6); |
| 784 | strictEqual(net.isIP('::2001:252:1:255.255.255.255.76'), 0); |
| 785 | strictEqual(net.isIP('fe80::2008%eth0'), 6); |
| 786 | strictEqual(net.isIP('fe80::2008%eth0.0'), 6); |
| 787 | strictEqual(net.isIP('fe80::2008%eth0@1'), 0); |
| 788 | strictEqual(net.isIP('::anything'), 0); |
| 789 | strictEqual(net.isIP('::1'), 6); |
| 790 | strictEqual(net.isIP('::'), 6); |
| 791 | strictEqual(net.isIP('0000:0000:0000:0000:0000:0000:12345:0000'), 0); |
| 792 | strictEqual(net.isIP('0'), 0); |
| 793 | strictEqual(net.isIP(), 0); |
| 794 | strictEqual(net.isIP(''), 0); |
| 795 | strictEqual(net.isIP(null), 0); |
| 796 | strictEqual(net.isIP(123), 0); |
| 797 | strictEqual(net.isIP(true), 0); |
| 798 | strictEqual(net.isIP({}), 0); |
| 799 | strictEqual( |
| 800 | net.isIP({ toString: () => '::2001:252:1:255.255.255.255' }), |
| 801 | 6 |
| 802 | ); |
| 803 | strictEqual(net.isIP({ toString: () => '127.0.0.1' }), 4); |
| 804 | strictEqual(net.isIP({ toString: () => 'bla' }), 0); |
| 805 | |
| 806 | strictEqual(net.isIPv4('127.0.0.1'), true); |
| 807 | strictEqual(net.isIPv4('example.com'), false); |
| 808 | strictEqual(net.isIPv4('2001:252:0:1::2008:6'), false); |
| 809 | strictEqual(net.isIPv4(), false); |
| 810 | strictEqual(net.isIPv4(''), false); |
| 811 | strictEqual(net.isIPv4(null), false); |
| 812 | strictEqual(net.isIPv4(123), false); |
| 813 | strictEqual(net.isIPv4(true), false); |
| 814 | strictEqual(net.isIPv4({}), false); |
| 815 | strictEqual( |
| 816 | net.isIPv4({ toString: () => '::2001:252:1:255.255.255.255' }), |
| 817 | false |
| 818 | ); |
| 819 | strictEqual(net.isIPv4({ toString: () => '127.0.0.1' }), true); |
| 820 | strictEqual(net.isIPv4({ toString: () => 'bla' }), false); |
| 821 | |
| 822 | strictEqual(net.isIPv6('127.0.0.1'), false); |
| 823 | strictEqual(net.isIPv6('example.com'), false); |
| 824 | strictEqual(net.isIPv6('2001:252:0:1::2008:6'), true); |
| 825 | strictEqual(net.isIPv6(), false); |
| 826 | strictEqual(net.isIPv6(''), false); |
| 827 | strictEqual(net.isIPv6(null), false); |
| 828 | strictEqual(net.isIPv6(123), false); |
| 829 | strictEqual(net.isIPv6(true), false); |
| 830 | strictEqual(net.isIPv6({}), false); |
| 831 | strictEqual( |
| 832 | net.isIPv6({ toString: () => '::2001:252:1:255.255.255.255' }), |
| 833 | true |
| 834 | ); |
| 835 | strictEqual(net.isIPv6({ toString: () => '127.0.0.1' }), false); |
| 836 | strictEqual(net.isIPv6({ toString: () => 'bla' }), false); |
| 837 | }, |
| 838 | }; |
| 839 | |
| 840 | // test/parallel/test-net-isipv4.js |
| 841 | export const testNetIsIpv4 = { |
| 842 | test() { |
| 843 | const v4 = [ |
| 844 | '0.0.0.0', |
| 845 | '8.8.8.8', |
| 846 | '127.0.0.1', |
| 847 | '100.100.100.100', |
| 848 | '192.168.0.1', |
| 849 | '18.101.25.153', |
| 850 | '123.23.34.2', |
| 851 | '172.26.168.134', |
| 852 | '212.58.241.131', |
| 853 | '128.0.0.0', |
| 854 | '23.71.254.72', |
| 855 | '223.255.255.255', |
| 856 | '192.0.2.235', |
| 857 | '99.198.122.146', |
| 858 | '46.51.197.88', |
| 859 | '173.194.34.134', |
| 860 | ]; |
| 861 | |
| 862 | const v4not = [ |
| 863 | '.100.100.100.100', |
| 864 | '100..100.100.100.', |
| 865 | '100.100.100.100.', |
| 866 | '999.999.999.999', |
| 867 | '256.256.256.256', |
| 868 | '256.100.100.100.100', |
| 869 | '123.123.123', |
| 870 | 'http://123.123.123', |
| 871 | '1000.2.3.4', |
| 872 | '999.2.3.4', |
| 873 | '0000000192.168.0.200', |
| 874 | '192.168.0.2000000000', |
| 875 | ]; |
| 876 | |
| 877 | for (const ip of v4) { |
| 878 | strictEqual(net.isIPv4(ip), true); |
| 879 | } |
| 880 | |
| 881 | for (const ip of v4not) { |
| 882 | strictEqual(net.isIPv4(ip), false); |
| 883 | } |
| 884 | }, |
| 885 | }; |
| 886 | |
| 887 | // test/parallel/test-net-isipv6.js |
| 888 | export const testNetIsIpv6 = { |
| 889 | test() { |
| 890 | const v6 = [ |
| 891 | '::', |
| 892 | '1::', |
| 893 | '::1', |
| 894 | '1::8', |
| 895 | '1::7:8', |
| 896 | '1:2:3:4:5:6:7:8', |
| 897 | '1:2:3:4:5:6::8', |
| 898 | '1:2:3:4:5:6:7::', |
| 899 | '1:2:3:4:5::7:8', |
| 900 | '1:2:3:4:5::8', |
| 901 | '1:2:3::8', |
| 902 | '1::4:5:6:7:8', |
| 903 | '1::6:7:8', |
| 904 | '1::3:4:5:6:7:8', |
| 905 | '1:2:3:4::6:7:8', |
| 906 | '1:2::4:5:6:7:8', |
| 907 | '::2:3:4:5:6:7:8', |
| 908 | '1:2::8', |
| 909 | '2001:0000:1234:0000:0000:C1C0:ABCD:0876', |
| 910 | '3ffe:0b00:0000:0000:0001:0000:0000:000a', |
| 911 | 'FF02:0000:0000:0000:0000:0000:0000:0001', |
| 912 | '0000:0000:0000:0000:0000:0000:0000:0001', |
| 913 | '0000:0000:0000:0000:0000:0000:0000:0000', |
| 914 | '::ffff:192.168.1.26', |
| 915 | '2::10', |
| 916 | 'ff02::1', |
| 917 | 'fe80::', |
| 918 | '2002::', |
| 919 | '2001:db8::', |
| 920 | '2001:0db8:1234::', |
| 921 | '::ffff:0:0', |
| 922 | '::ffff:192.168.1.1', |
| 923 | '1:2:3:4::8', |
| 924 | '1::2:3:4:5:6:7', |
| 925 | '1::2:3:4:5:6', |
| 926 | '1::2:3:4:5', |
| 927 | '1::2:3:4', |
| 928 | '1::2:3', |
| 929 | '::2:3:4:5:6:7', |
| 930 | '::2:3:4:5:6', |
| 931 | '::2:3:4:5', |
| 932 | '::2:3:4', |
| 933 | '::2:3', |
| 934 | '::8', |
| 935 | '1:2:3:4:5:6::', |
| 936 | '1:2:3:4:5::', |
| 937 | '1:2:3:4::', |
| 938 | '1:2:3::', |
| 939 | '1:2::', |
| 940 | '1:2:3:4::7:8', |
| 941 | '1:2:3::7:8', |
| 942 | '1:2::7:8', |
| 943 | '1:2:3:4:5:6:1.2.3.4', |
| 944 | '1:2:3:4:5::1.2.3.4', |
| 945 | '1:2:3:4::1.2.3.4', |
| 946 | '1:2:3::1.2.3.4', |
| 947 | '1:2::1.2.3.4', |
| 948 | '1::1.2.3.4', |
| 949 | '1:2:3:4::5:1.2.3.4', |
| 950 | '1:2:3::5:1.2.3.4', |
| 951 | '1:2::5:1.2.3.4', |
| 952 | '1::5:1.2.3.4', |
| 953 | '1::5:11.22.33.44', |
| 954 | 'fe80::217:f2ff:254.7.237.98', |
| 955 | 'fe80::217:f2ff:fe07:ed62', |
| 956 | '2001:DB8:0:0:8:800:200C:417A', |
| 957 | 'FF01:0:0:0:0:0:0:101', |
| 958 | '0:0:0:0:0:0:0:1', |
| 959 | '0:0:0:0:0:0:0:0', |
| 960 | '2001:DB8::8:800:200C:417A', |
| 961 | 'FF01::101', |
| 962 | '0:0:0:0:0:0:13.1.68.3', |
| 963 | '0:0:0:0:0:FFFF:129.144.52.38', |
| 964 | '::13.1.68.3', |
| 965 | '::FFFF:129.144.52.38', |
| 966 | 'fe80:0000:0000:0000:0204:61ff:fe9d:f156', |
| 967 | 'fe80:0:0:0:204:61ff:fe9d:f156', |
| 968 | 'fe80::204:61ff:fe9d:f156', |
| 969 | 'fe80:0:0:0:204:61ff:254.157.241.86', |
| 970 | 'fe80::204:61ff:254.157.241.86', |
| 971 | 'fe80::1', |
| 972 | '2001:0db8:85a3:0000:0000:8a2e:0370:7334', |
| 973 | '2001:db8:85a3:0:0:8a2e:370:7334', |
| 974 | '2001:db8:85a3::8a2e:370:7334', |
| 975 | '2001:0db8:0000:0000:0000:0000:1428:57ab', |
| 976 | '2001:0db8:0000:0000:0000::1428:57ab', |
| 977 | '2001:0db8:0:0:0:0:1428:57ab', |
| 978 | '2001:0db8:0:0::1428:57ab', |
| 979 | '2001:0db8::1428:57ab', |
| 980 | '2001:db8::1428:57ab', |
| 981 | '::ffff:12.34.56.78', |
| 982 | '::ffff:0c22:384e', |
| 983 | '2001:0db8:1234:0000:0000:0000:0000:0000', |
| 984 | '2001:0db8:1234:ffff:ffff:ffff:ffff:ffff', |
| 985 | '2001:db8:a::123', |
| 986 | '::ffff:192.0.2.128', |
| 987 | '::ffff:c000:280', |
| 988 | 'a:b:c:d:e:f:f1:f2', |
| 989 | 'a:b:c::d:e:f:f1', |
| 990 | 'a:b:c::d:e:f', |
| 991 | 'a:b:c::d:e', |
| 992 | 'a:b:c::d', |
| 993 | '::a', |
| 994 | '::a:b:c', |
| 995 | '::a:b:c:d:e:f:f1', |
| 996 | 'a::', |
| 997 | 'a:b:c::', |
| 998 | 'a:b:c:d:e:f:f1::', |
| 999 | 'a:bb:ccc:dddd:000e:00f:0f::', |
| 1000 | '0:a:0:a:0:0:0:a', |
| 1001 | '0:a:0:0:a:0:0:a', |
| 1002 | '2001:db8:1:1:1:1:0:0', |
| 1003 | '2001:db8:1:1:1:0:0:0', |
| 1004 | '2001:db8:1:1:0:0:0:0', |
| 1005 | '2001:db8:1:0:0:0:0:0', |
| 1006 | '2001:db8:0:0:0:0:0:0', |
| 1007 | '2001:0:0:0:0:0:0:0', |
| 1008 | 'A:BB:CCC:DDDD:000E:00F:0F::', |
| 1009 | '0:0:0:0:0:0:0:a', |
| 1010 | '0:0:0:0:a:0:0:0', |
| 1011 | '0:0:0:a:0:0:0:0', |
| 1012 | 'a:0:0:a:0:0:a:a', |
| 1013 | 'a:0:0:a:0:0:0:a', |
| 1014 | 'a:0:0:0:a:0:0:a', |
| 1015 | 'a:0:0:0:a:0:0:0', |
| 1016 | 'a:0:0:0:0:0:0:0', |
| 1017 | 'fe80::7:8%eth0', |
| 1018 | 'fe80::7:8%1', |
| 1019 | ]; |
| 1020 | |
| 1021 | const v6not = [ |
| 1022 | '', |
| 1023 | '1:', |
| 1024 | ':1', |
| 1025 | '11:36:12', |
| 1026 | '02001:0000:1234:0000:0000:C1C0:ABCD:0876', |
| 1027 | '2001:0000:1234:0000:00001:C1C0:ABCD:0876', |
| 1028 | '2001:0000:1234: 0000:0000:C1C0:ABCD:0876', |
| 1029 | '2001:1:1:1:1:1:255Z255X255Y255', |
| 1030 | '3ffe:0b00:0000:0001:0000:0000:000a', |
| 1031 | 'FF02:0000:0000:0000:0000:0000:0000:0000:0001', |
| 1032 | '3ffe:b00::1::a', |
| 1033 | '::1111:2222:3333:4444:5555:6666::', |
| 1034 | '1:2:3::4:5::7:8', |
| 1035 | '12345::6:7:8', |
| 1036 | '1::5:400.2.3.4', |
| 1037 | '1::5:260.2.3.4', |
| 1038 | '1::5:256.2.3.4', |
| 1039 | '1::5:1.256.3.4', |
| 1040 | '1::5:1.2.256.4', |
| 1041 | '1::5:1.2.3.256', |
| 1042 | '1::5:300.2.3.4', |
| 1043 | '1::5:1.300.3.4', |
| 1044 | '1::5:1.2.300.4', |
| 1045 | '1::5:1.2.3.300', |
| 1046 | '1::5:900.2.3.4', |
| 1047 | '1::5:1.900.3.4', |
| 1048 | '1::5:1.2.900.4', |
| 1049 | '1::5:1.2.3.900', |
| 1050 | '1::5:300.300.300.300', |
| 1051 | '1::5:3000.30.30.30', |
| 1052 | '1::400.2.3.4', |
| 1053 | '1::260.2.3.4', |
| 1054 | '1::256.2.3.4', |
| 1055 | '1::1.256.3.4', |
| 1056 | '1::1.2.256.4', |
| 1057 | '1::1.2.3.256', |
| 1058 | '1::300.2.3.4', |
| 1059 | '1::1.300.3.4', |
| 1060 | '1::1.2.300.4', |
| 1061 | '1::1.2.3.300', |
| 1062 | '1::900.2.3.4', |
| 1063 | '1::1.900.3.4', |
| 1064 | '1::1.2.900.4', |
| 1065 | '1::1.2.3.900', |
| 1066 | '1::300.300.300.300', |
| 1067 | '1::3000.30.30.30', |
| 1068 | '::400.2.3.4', |
| 1069 | '::260.2.3.4', |
| 1070 | '::256.2.3.4', |
| 1071 | '::1.256.3.4', |
| 1072 | '::1.2.256.4', |
| 1073 | '::1.2.3.256', |
| 1074 | '::300.2.3.4', |
| 1075 | '::1.300.3.4', |
| 1076 | '::1.2.300.4', |
| 1077 | '::1.2.3.300', |
| 1078 | '::900.2.3.4', |
| 1079 | '::1.900.3.4', |
| 1080 | '::1.2.900.4', |
| 1081 | '::1.2.3.900', |
| 1082 | '::300.300.300.300', |
| 1083 | '::3000.30.30.30', |
| 1084 | '2001:DB8:0:0:8:800:200C:417A:221', |
| 1085 | 'FF01::101::2', |
| 1086 | '1111:2222:3333:4444::5555:', |
| 1087 | '1111:2222:3333::5555:', |
| 1088 | '1111:2222::5555:', |
| 1089 | '1111::5555:', |
| 1090 | '::5555:', |
| 1091 | ':::', |
| 1092 | '1111:', |
| 1093 | ':', |
| 1094 | ':1111:2222:3333:4444::5555', |
| 1095 | ':1111:2222:3333::5555', |
| 1096 | ':1111:2222::5555', |
| 1097 | ':1111::5555', |
| 1098 | ':::5555', |
| 1099 | '1.2.3.4:1111:2222:3333:4444::5555', |
| 1100 | '1.2.3.4:1111:2222:3333::5555', |
| 1101 | '1.2.3.4:1111:2222::5555', |
| 1102 | '1.2.3.4:1111::5555', |
| 1103 | '1.2.3.4::5555', |
| 1104 | '1.2.3.4::', |
| 1105 | 'fe80:0000:0000:0000:0204:61ff:254.157.241.086', |
| 1106 | '123', |
| 1107 | 'ldkfj', |
| 1108 | '2001::FFD3::57ab', |
| 1109 | '2001:db8:85a3::8a2e:37023:7334', |
| 1110 | '2001:db8:85a3::8a2e:370k:7334', |
| 1111 | '1:2:3:4:5:6:7:8:9', |
| 1112 | '1::2::3', |
| 1113 | '1:::3:4:5', |
| 1114 | '1:2:3::4:5:6:7:8:9', |
| 1115 | '::ffff:2.3.4', |
| 1116 | '::ffff:257.1.2.3', |
| 1117 | '::ffff:12345678901234567890.1.26', |
| 1118 | '2001:0000:1234:0000:0000:C1C0:ABCD:0876 0', |
| 1119 | '02001:0000:1234:0000:0000:C1C0:ABCD:0876', |
| 1120 | ]; |
| 1121 | |
| 1122 | for (const ip of v6) { |
| 1123 | strictEqual(net.isIPv6(ip), true); |
| 1124 | } |
| 1125 | |
| 1126 | for (const ip of v6not) { |
| 1127 | strictEqual(net.isIPv6(ip), false); |
| 1128 | } |
| 1129 | }, |
| 1130 | }; |
| 1131 | |
| 1132 | // test/parallel/test-net-large-string.js |
| 1133 | export const testNetLargeString = { |
| 1134 | async test(ctrl, env, ctx) { |
| 1135 | const { promise, resolve } = Promise.withResolvers(); |
| 1136 | const c = net.connect(env.ECHO_SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1137 | let response = ''; |
| 1138 | const size = 40 * 1024; |
| 1139 | const data = 'ใ'.repeat(size); |
| 1140 | c.setEncoding('utf8'); |
| 1141 | c.on('data', (data) => (response += data)); |
| 1142 | c.end(data); |
| 1143 | c.on('close', resolve); |
| 1144 | await promise; |
| 1145 | strictEqual(response.length, size); |
| 1146 | strictEqual(response, data); |
| 1147 | }, |
| 1148 | }; |
| 1149 | |
| 1150 | // test/parallel/test-net-local-address-port.js |
| 1151 | // The localAddress information is a non-op in our implementation |
| 1152 | export const testNetLocalAddressPort = { |
| 1153 | async test(ctrl, env, ctx) { |
| 1154 | const { promise, resolve } = Promise.withResolvers(); |
| 1155 | const c = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1156 | c.on('connect', () => { |
| 1157 | strictEqual(c.localAddress, '0.0.0.0'); |
| 1158 | strictEqual(c.localPort, 0); |
| 1159 | resolve(); |
| 1160 | }); |
| 1161 | await promise; |
| 1162 | }, |
| 1163 | }; |
| 1164 | |
| 1165 | // test/parallel/test-net-localerror.js |
| 1166 | export const testNetLocalError = { |
| 1167 | async test() { |
| 1168 | const connect = (opts, code, type) => { |
| 1169 | throws(() => net.connect(opts), { code, name: type.name }); |
| 1170 | }; |
| 1171 | |
| 1172 | connect( |
| 1173 | { |
| 1174 | host: 'localhost', |
| 1175 | port: 0, |
| 1176 | localAddress: 'foobar', |
| 1177 | }, |
| 1178 | 'ERR_INVALID_IP_ADDRESS', |
| 1179 | TypeError |
| 1180 | ); |
| 1181 | |
| 1182 | connect( |
| 1183 | { |
| 1184 | host: 'localhost', |
| 1185 | port: 0, |
| 1186 | localPort: 'foobar', |
| 1187 | }, |
| 1188 | 'ERR_INVALID_ARG_TYPE', |
| 1189 | TypeError |
| 1190 | ); |
| 1191 | }, |
| 1192 | }; |
| 1193 | |
| 1194 | // test/parallel/test-net-onread-static-buffer.js |
| 1195 | export const testNetOnReadStaticBuffer = { |
| 1196 | async test(ctrl, env, ctx) { |
| 1197 | const { promise, resolve } = Promise.withResolvers(); |
| 1198 | const buffer = Buffer.alloc(1024); |
| 1199 | const fn = mock.fn((nread, buf) => { |
| 1200 | strictEqual(nread, 5); |
| 1201 | strictEqual(buf.buffer.byteLength, 1024); |
| 1202 | resolve(); |
| 1203 | }); |
| 1204 | const c = net.connect({ |
| 1205 | port: env.ECHO_SERVER_PORT, |
| 1206 | host: env.SIDECAR_HOSTNAME, |
| 1207 | onread: { |
| 1208 | buffer, |
| 1209 | callback: fn, |
| 1210 | }, |
| 1211 | }); |
| 1212 | c.on('data', () => { |
| 1213 | throw new Error('Should not have failed'); |
| 1214 | }); |
| 1215 | c.write('hello'); |
| 1216 | await promise; |
| 1217 | strictEqual(fn.mock.callCount(), 1); |
| 1218 | }, |
| 1219 | }; |
| 1220 | |
| 1221 | export const testNetReconnect = { |
| 1222 | async test(ctrl, env) { |
| 1223 | const { promise, resolve } = Promise.withResolvers(); |
| 1224 | const N = 50; |
| 1225 | const client = net.connect(env.RECONNECT_SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1226 | |
| 1227 | client.setEncoding('UTF8'); |
| 1228 | |
| 1229 | const onDataFn = mock.fn((chunk) => { |
| 1230 | strictEqual(chunk, 'hello\r\n'); |
| 1231 | client.end(); |
| 1232 | }); |
| 1233 | client.on('data', onDataFn); |
| 1234 | |
| 1235 | const endFn = mock.fn(() => {}); |
| 1236 | client.on('end', endFn); |
| 1237 | |
| 1238 | const closeFn = mock.fn((had_error) => { |
| 1239 | strictEqual(had_error, false); |
| 1240 | if (closeFn.mock.callCount() < N) { |
| 1241 | client.connect(env.RECONNECT_SERVER_PORT, env.SIDECAR_HOSTNAME); // reconnect |
| 1242 | } else { |
| 1243 | resolve(); |
| 1244 | } |
| 1245 | }); |
| 1246 | client.on('close', closeFn); |
| 1247 | |
| 1248 | await promise; |
| 1249 | strictEqual(closeFn.mock.callCount(), N + 1); |
| 1250 | strictEqual(onDataFn.mock.callCount(), N + 1); |
| 1251 | strictEqual(endFn.mock.callCount(), N + 1); |
| 1252 | }, |
| 1253 | }; |
| 1254 | |
| 1255 | // test/parallel/test-net-remote-address-port.js |
| 1256 | // test/parallel/test-net-remote-address.js |
| 1257 | export const testNetRemoteAddress = { |
| 1258 | async test(ctrl, env, ctx) { |
| 1259 | const { promise, resolve } = Promise.withResolvers(); |
| 1260 | const c = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1261 | c.on('connect', () => { |
| 1262 | strictEqual(c.remoteAddress, env.SIDECAR_HOSTNAME); |
| 1263 | strictEqual(c.remotePort, parseInt(env.SERVER_PORT)); |
| 1264 | resolve(); |
| 1265 | }); |
| 1266 | await promise; |
| 1267 | }, |
| 1268 | }; |
| 1269 | |
| 1270 | // // test/parallel/test-net-socket-byteswritten.js |
| 1271 | export const testNetSocketBytesWritten = { |
| 1272 | async test(ctrl, env) { |
| 1273 | const { promise, resolve } = Promise.withResolvers(); |
| 1274 | const socket = net.connect(env.END_SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1275 | |
| 1276 | // Cork the socket, then write twice; this should cause a writev, which |
| 1277 | // previously caused an err in the bytesWritten count. |
| 1278 | socket.cork(); |
| 1279 | |
| 1280 | socket.write('one'); |
| 1281 | socket.write(Buffer.from('twรธ', 'utf8')); |
| 1282 | |
| 1283 | socket.uncork(); |
| 1284 | |
| 1285 | // one = 3 bytes, twรธ = 4 bytes |
| 1286 | strictEqual(socket.bytesWritten, 3 + 4); |
| 1287 | |
| 1288 | const connectFn = mock.fn(() => { |
| 1289 | strictEqual(socket.bytesWritten, 3 + 4); |
| 1290 | }); |
| 1291 | socket.on('connect', connectFn); |
| 1292 | |
| 1293 | socket.on('end', function () { |
| 1294 | strictEqual(socket.bytesWritten, 3 + 4); |
| 1295 | resolve(); |
| 1296 | }); |
| 1297 | |
| 1298 | await promise; |
| 1299 | strictEqual(connectFn.mock.callCount(), 1); |
| 1300 | }, |
| 1301 | }; |
| 1302 | |
| 1303 | // test/parallel/test-net-socket-connect-invalid-autoselectfamily.js |
| 1304 | export const testSocketConnectInvalidAutoselectFamily = { |
| 1305 | async test() { |
| 1306 | throws( |
| 1307 | () => { |
| 1308 | net.connect({ port: 8080, autoSelectFamily: 'INVALID' }); |
| 1309 | }, |
| 1310 | { code: 'ERR_INVALID_ARG_TYPE' } |
| 1311 | ); |
| 1312 | }, |
| 1313 | }; |
| 1314 | |
| 1315 | // test/parallel/test-net-socket-connect-invalid-autoselectfamilyattempttimeout.js |
| 1316 | export const testSocketConnectInvalidAutoselectFamilyTimeout = { |
| 1317 | async test() { |
| 1318 | for (const autoSelectFamilyAttemptTimeout of [-10, 0]) { |
| 1319 | throws( |
| 1320 | () => { |
| 1321 | net.connect({ |
| 1322 | port: 8080, |
| 1323 | autoSelectFamily: true, |
| 1324 | autoSelectFamilyAttemptTimeout, |
| 1325 | }); |
| 1326 | }, |
| 1327 | { code: 'ERR_OUT_OF_RANGE' } |
| 1328 | ); |
| 1329 | |
| 1330 | throws( |
| 1331 | () => { |
| 1332 | net.setDefaultAutoSelectFamilyAttemptTimeout( |
| 1333 | autoSelectFamilyAttemptTimeout |
| 1334 | ); |
| 1335 | }, |
| 1336 | { code: 'ERR_OUT_OF_RANGE' } |
| 1337 | ); |
| 1338 | } |
| 1339 | |
| 1340 | // Check the default value of autoSelectFamilyAttemptTimeout is 10 |
| 1341 | // if passed number is less than 10 |
| 1342 | for (const autoSelectFamilyAttemptTimeout of [1, 9]) { |
| 1343 | net.setDefaultAutoSelectFamilyAttemptTimeout( |
| 1344 | autoSelectFamilyAttemptTimeout |
| 1345 | ); |
| 1346 | strictEqual(net.getDefaultAutoSelectFamilyAttemptTimeout(), 10); |
| 1347 | } |
| 1348 | }, |
| 1349 | }; |
| 1350 | |
| 1351 | // test/parallel/test-net-socket-connect-without-cb.js |
| 1352 | export const testNetSocketConnectWithoutCb = { |
| 1353 | async test(ctrl, env) { |
| 1354 | const { promise, resolve } = Promise.withResolvers(); |
| 1355 | const client = new net.Socket(); |
| 1356 | client.on('connect', resolve); |
| 1357 | client.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1358 | await promise; |
| 1359 | }, |
| 1360 | }; |
| 1361 | |
| 1362 | // test/parallel/test-net-socket-connecting.js |
| 1363 | export const testNetSocketConnecting = { |
| 1364 | async test(ctrl, env) { |
| 1365 | const { promise, resolve } = Promise.withResolvers(); |
| 1366 | const client = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME, () => { |
| 1367 | strictEqual(client.connecting, false); |
| 1368 | |
| 1369 | // Legacy getter |
| 1370 | strictEqual(client._connecting, false); |
| 1371 | resolve(); |
| 1372 | }); |
| 1373 | strictEqual(client.connecting, true); |
| 1374 | |
| 1375 | // Legacy getter |
| 1376 | strictEqual(client._connecting, true); |
| 1377 | await promise; |
| 1378 | }, |
| 1379 | }; |
| 1380 | |
| 1381 | // test/parallel/test-net-socket-destroy-send.js |
| 1382 | export const testNetSocketDestroySend = { |
| 1383 | async test(ctrl, env) { |
| 1384 | const { promise, resolve, reject } = Promise.withResolvers(); |
| 1385 | const conn = net.createConnection(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1386 | |
| 1387 | conn.on('connect', function () { |
| 1388 | // Test destroy returns this, even on multiple calls when it short-circuits. |
| 1389 | strictEqual(conn, conn.destroy().destroy()); |
| 1390 | conn.on('error', reject); |
| 1391 | |
| 1392 | conn.write(Buffer.from('kaboom'), (err) => { |
| 1393 | strictEqual(err.code, 'ERR_STREAM_DESTROYED'); |
| 1394 | strictEqual(err.name, 'Error'); |
| 1395 | strictEqual( |
| 1396 | err.message, |
| 1397 | 'Cannot call write after a stream was destroyed' |
| 1398 | ); |
| 1399 | resolve(); |
| 1400 | }); |
| 1401 | }); |
| 1402 | |
| 1403 | await promise; |
| 1404 | }, |
| 1405 | }; |
| 1406 | |
| 1407 | // test/parallel/test-net-socket-end-callback.js |
| 1408 | export const testNetSocketEndCallback = { |
| 1409 | async test(ctrl, env) { |
| 1410 | const { promise, resolve } = Promise.withResolvers(); |
| 1411 | const connect = (...args) => { |
| 1412 | const socket = net.createConnection( |
| 1413 | env.SERVER_PORT, |
| 1414 | env.SIDECAR_HOSTNAME, |
| 1415 | () => { |
| 1416 | socket.end(...args); |
| 1417 | } |
| 1418 | ); |
| 1419 | }; |
| 1420 | |
| 1421 | let count = 0; |
| 1422 | const cb = mock.fn(() => { |
| 1423 | if (++count === 3) { |
| 1424 | resolve(); |
| 1425 | } |
| 1426 | }); |
| 1427 | |
| 1428 | connect(cb); |
| 1429 | connect('foo', cb); |
| 1430 | connect('foo', 'utf8', cb); |
| 1431 | await promise; |
| 1432 | strictEqual(cb.mock.callCount(), 3); |
| 1433 | }, |
| 1434 | }; |
| 1435 | |
| 1436 | // test/parallel/test-net-socket-no-halfopen-enforcer.js |
| 1437 | export const testNetSocketNoHalfopenEnforcer = { |
| 1438 | async test() { |
| 1439 | const socket = new net.Socket({ allowHalfOpen: false }); |
| 1440 | strictEqual(socket.listenerCount('end'), 1); |
| 1441 | }, |
| 1442 | }; |
| 1443 | |
| 1444 | // test/parallel/test-net-socket-ready-without-cb.js |
| 1445 | export const testNetSocketReadyWithoutCb = { |
| 1446 | async test(ctrl, env) { |
| 1447 | const { promise, resolve } = Promise.withResolvers(); |
| 1448 | const client = new net.Socket(); |
| 1449 | client.on('ready', resolve); |
| 1450 | client.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1451 | await promise; |
| 1452 | }, |
| 1453 | }; |
| 1454 | |
| 1455 | // test/parallel/test-net-socket-reset-send.js |
| 1456 | export const testNetSocketResetSend = { |
| 1457 | async test(ctrl, env) { |
| 1458 | const { promise, resolve, reject } = Promise.withResolvers(); |
| 1459 | const conn = net.createConnection(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1460 | conn.on('connect', () => { |
| 1461 | strictEqual(conn, conn.resetAndDestroy().destroy()); |
| 1462 | conn.on('error', reject); |
| 1463 | |
| 1464 | conn.write(Buffer.from('fzfzfzfzfz'), (err) => { |
| 1465 | strictEqual(err.code, 'ERR_STREAM_DESTROYED'); |
| 1466 | strictEqual(err.name, 'Error'); |
| 1467 | strictEqual( |
| 1468 | err.message, |
| 1469 | 'Cannot call write after a stream was destroyed' |
| 1470 | ); |
| 1471 | resolve(); |
| 1472 | }); |
| 1473 | }); |
| 1474 | await promise; |
| 1475 | }, |
| 1476 | }; |
| 1477 | |
| 1478 | // test/parallel/test-net-socket-timeout.js |
| 1479 | export const testNetSocketTimeout = { |
| 1480 | async test(ctrl, env) { |
| 1481 | // Verify that invalid delays throw |
| 1482 | const s = new net.Socket(); |
| 1483 | const nonNumericDelays = [ |
| 1484 | '100', |
| 1485 | true, |
| 1486 | false, |
| 1487 | undefined, |
| 1488 | null, |
| 1489 | '', |
| 1490 | {}, |
| 1491 | () => {}, |
| 1492 | [], |
| 1493 | ]; |
| 1494 | const badRangeDelays = [-0.001, -1, -Infinity, Infinity, NaN]; |
| 1495 | const validDelays = [0, 0.001, 1, 1e6]; |
| 1496 | const invalidCallbacks = [ |
| 1497 | 1, |
| 1498 | '100', |
| 1499 | true, |
| 1500 | false, |
| 1501 | null, |
| 1502 | {}, |
| 1503 | [], |
| 1504 | Symbol('test'), |
| 1505 | ]; |
| 1506 | |
| 1507 | for (let i = 0; i < nonNumericDelays.length; i++) { |
| 1508 | throws( |
| 1509 | () => { |
| 1510 | s.setTimeout(nonNumericDelays[i], () => {}); |
| 1511 | }, |
| 1512 | { code: 'ERR_INVALID_ARG_TYPE' }, |
| 1513 | nonNumericDelays[i] |
| 1514 | ); |
| 1515 | } |
| 1516 | |
| 1517 | for (let i = 0; i < badRangeDelays.length; i++) { |
| 1518 | throws( |
| 1519 | () => { |
| 1520 | s.setTimeout(badRangeDelays[i], () => {}); |
| 1521 | }, |
| 1522 | { code: 'ERR_OUT_OF_RANGE' }, |
| 1523 | badRangeDelays[i] |
| 1524 | ); |
| 1525 | } |
| 1526 | |
| 1527 | for (let i = 0; i < validDelays.length; i++) { |
| 1528 | s.setTimeout(validDelays[i], () => {}); |
| 1529 | } |
| 1530 | |
| 1531 | for (let i = 0; i < invalidCallbacks.length; i++) { |
| 1532 | [0, 1].forEach((msec) => |
| 1533 | throws(() => s.setTimeout(msec, invalidCallbacks[i]), { |
| 1534 | code: 'ERR_INVALID_ARG_TYPE', |
| 1535 | name: 'TypeError', |
| 1536 | }) |
| 1537 | ); |
| 1538 | } |
| 1539 | |
| 1540 | { |
| 1541 | const { promise, resolve, reject } = Promise.withResolvers(); |
| 1542 | const socket = net.createConnection( |
| 1543 | env.SERVER_PORT, |
| 1544 | env.SIDECAR_HOSTNAME |
| 1545 | ); |
| 1546 | strictEqual( |
| 1547 | socket.setTimeout(1, () => { |
| 1548 | socket.destroy(); |
| 1549 | strictEqual( |
| 1550 | socket.setTimeout(1, () => |
| 1551 | reject(new Error('Should not have called setTimeout callback')) |
| 1552 | ), |
| 1553 | socket |
| 1554 | ); |
| 1555 | resolve(); |
| 1556 | }), |
| 1557 | socket |
| 1558 | ); |
| 1559 | await promise; |
| 1560 | } |
| 1561 | }, |
| 1562 | }; |
| 1563 | |
| 1564 | // test/parallel/test-net-socket-write-after-close.js |
| 1565 | export const testNetSocketWriteAfterClose = { |
| 1566 | async test(ctrl, env) { |
| 1567 | { |
| 1568 | const { promise, resolve } = Promise.withResolvers(); |
| 1569 | const client = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME, () => { |
| 1570 | client.on('error', (err) => { |
| 1571 | strictEqual(err.name, 'Error'); |
| 1572 | // Node.js tests for a different error message. |
| 1573 | strictEqual(err.message, 'Socket is closed'); |
| 1574 | strictEqual(err.code, 'ERR_SOCKET_CLOSED'); |
| 1575 | resolve(); |
| 1576 | }); |
| 1577 | client._handle = null; |
| 1578 | client.write('foo'); |
| 1579 | }); |
| 1580 | await promise; |
| 1581 | } |
| 1582 | }, |
| 1583 | }; |
| 1584 | |
| 1585 | // test/parallel/test-net-socket-write-error.js |
| 1586 | export const testNetSocketWriteError = { |
| 1587 | async test(ctrl, env) { |
| 1588 | const { promise, resolve, reject } = Promise.withResolvers(); |
| 1589 | const client = net.createConnection( |
| 1590 | env.SERVER_PORT, |
| 1591 | env.SIDECAR_HOSTNAME, |
| 1592 | () => { |
| 1593 | client.on('error', reject); |
| 1594 | throws( |
| 1595 | () => { |
| 1596 | client.write(1337); |
| 1597 | }, |
| 1598 | { |
| 1599 | code: 'ERR_INVALID_ARG_TYPE', |
| 1600 | name: 'TypeError', |
| 1601 | } |
| 1602 | ); |
| 1603 | |
| 1604 | resolve(); |
| 1605 | } |
| 1606 | ); |
| 1607 | await promise; |
| 1608 | }, |
| 1609 | }; |
| 1610 | |
| 1611 | // test/parallel/test-net-sync-cork.js |
| 1612 | export const testNetSyncCork = { |
| 1613 | async test(ctrl, env) { |
| 1614 | const N = 100; |
| 1615 | const buf = Buffer.alloc(2, 'a'); |
| 1616 | |
| 1617 | const { promise, resolve } = Promise.withResolvers(); |
| 1618 | const conn = net.connect(env.SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1619 | |
| 1620 | conn.on('connect', () => { |
| 1621 | let res = true; |
| 1622 | let i = 0; |
| 1623 | for (; i < N && res; i++) { |
| 1624 | conn.cork(); |
| 1625 | conn.write(buf); |
| 1626 | res = conn.write(buf); |
| 1627 | conn.uncork(); |
| 1628 | } |
| 1629 | strictEqual(i, N); |
| 1630 | resolve(); |
| 1631 | }); |
| 1632 | await promise; |
| 1633 | }, |
| 1634 | }; |
| 1635 | |
| 1636 | // test/parallel/test-net-timeout-no-handle.js |
| 1637 | export const testNetTimeoutNoHandle = { |
| 1638 | async test() { |
| 1639 | const { promise, resolve, reject } = Promise.withResolvers(); |
| 1640 | const socket = new net.Socket(); |
| 1641 | socket.setTimeout(50); |
| 1642 | |
| 1643 | socket.on('timeout', () => { |
| 1644 | strictEqual(socket._handle, null); |
| 1645 | resolve(); |
| 1646 | }); |
| 1647 | |
| 1648 | socket.on('connect', reject); |
| 1649 | |
| 1650 | // Since the timeout is unrefed, the code will exit without this |
| 1651 | setTimeout(() => {}, 200); |
| 1652 | await promise; |
| 1653 | }, |
| 1654 | }; |
| 1655 | |
| 1656 | // test/parallel/test-net-writable.js |
| 1657 | export const testNetWritable = { |
| 1658 | async test(ctrl, env) { |
| 1659 | const { promise, resolve } = Promise.withResolvers(); |
| 1660 | const socket = net.connect(env.SERVER_THAT_DIES_PORT, env.SIDECAR_HOSTNAME); |
| 1661 | socket.on('end', () => { |
| 1662 | strictEqual(socket.writable, true); |
| 1663 | socket.write('hello world'); |
| 1664 | resolve(); |
| 1665 | }); |
| 1666 | await promise; |
| 1667 | }, |
| 1668 | }; |
| 1669 | |
| 1670 | // test/parallel/test-net-write-arguments.js |
| 1671 | export const testNetWriteArguments = { |
| 1672 | async test() { |
| 1673 | const socket = net.Stream({ highWaterMark: 0 }); |
| 1674 | |
| 1675 | throws( |
| 1676 | () => { |
| 1677 | socket.write(null); |
| 1678 | }, |
| 1679 | { |
| 1680 | code: 'ERR_STREAM_NULL_VALUES', |
| 1681 | name: 'TypeError', |
| 1682 | message: 'May not write null values to stream', |
| 1683 | } |
| 1684 | ); |
| 1685 | |
| 1686 | [true, false, undefined, 1, 1.0, +Infinity, -Infinity, [], {}].forEach( |
| 1687 | (value) => { |
| 1688 | const socket = net.Stream({ highWaterMark: 0 }); |
| 1689 | // We need to check the callback since 'error' will only |
| 1690 | // be emitted once per instance. |
| 1691 | throws( |
| 1692 | () => { |
| 1693 | socket.write(value); |
| 1694 | }, |
| 1695 | { |
| 1696 | code: 'ERR_INVALID_ARG_TYPE', |
| 1697 | name: 'TypeError', |
| 1698 | } |
| 1699 | ); |
| 1700 | } |
| 1701 | ); |
| 1702 | }, |
| 1703 | }; |
| 1704 | |
| 1705 | // test/parallel/test-net-write-cb-on-destroy-before-connect.js |
| 1706 | export const testNetWriteCbOnDestroyBefureConnected = { |
| 1707 | async test(ctrl, env) { |
| 1708 | const { promise, resolve } = Promise.withResolvers(); |
| 1709 | const socket = new net.Socket(); |
| 1710 | |
| 1711 | socket.on('connect', () => { |
| 1712 | throw new Error('Connect should not have been called'); |
| 1713 | }); |
| 1714 | |
| 1715 | socket.connect(Number(env.SERVER_PORT), env.SIDECAR_HOSTNAME); |
| 1716 | |
| 1717 | ok(socket.connecting); |
| 1718 | |
| 1719 | socket.write('foo', (err) => { |
| 1720 | strictEqual(err.code, 'ERR_SOCKET_CLOSED_BEFORE_CONNECTION'); |
| 1721 | strictEqual(err.name, 'Error'); |
| 1722 | resolve(); |
| 1723 | }); |
| 1724 | |
| 1725 | socket.destroy(); |
| 1726 | await promise; |
| 1727 | }, |
| 1728 | }; |
| 1729 | |
| 1730 | // test/parallel/test-net-write-connect-write.js |
| 1731 | export const testNetWriteConnectWrite = { |
| 1732 | async test(ctrl, env) { |
| 1733 | const { promise, resolve } = Promise.withResolvers(); |
| 1734 | const conn = net.connect(env.ECHO_SERVER_PORT, env.SIDECAR_HOSTNAME); |
| 1735 | let received = ''; |
| 1736 | |
| 1737 | conn.setEncoding('utf8'); |
| 1738 | conn.on('connect', function () { |
| 1739 | conn.write(' after'); |
| 1740 | }); |
| 1741 | conn.on('data', function (buf) { |
| 1742 | received += buf; |
| 1743 | conn.end(); |
| 1744 | }); |
| 1745 | conn.write('before'); |
| 1746 | |
| 1747 | conn.on('end', function () { |
| 1748 | strictEqual(received, 'before after'); |
| 1749 | resolve(); |
| 1750 | }); |
| 1751 | await promise; |
| 1752 | }, |
| 1753 | }; |
| 1754 | |
| 1755 | export const testSocketAddress = { |
| 1756 | test() { |
| 1757 | // Test constructor with default options |
| 1758 | const addr1 = new net.SocketAddress(); |
| 1759 | strictEqual(addr1.address, '127.0.0.1'); |
| 1760 | strictEqual(addr1.port, 0); |
| 1761 | strictEqual(addr1.family, 'ipv4'); |
| 1762 | strictEqual(addr1.flowlabel, 0); |
| 1763 | |
| 1764 | // Test constructor with IPv4 options |
| 1765 | const addr2 = new net.SocketAddress({ |
| 1766 | address: '192.168.1.1', |
| 1767 | port: 8080, |
| 1768 | family: 'ipv4', |
| 1769 | }); |
| 1770 | strictEqual(addr2.address, '192.168.1.1'); |
| 1771 | strictEqual(addr2.port, 8080); |
| 1772 | strictEqual(addr2.family, 'ipv4'); |
| 1773 | strictEqual(addr2.flowlabel, 0); |
| 1774 | |
| 1775 | // Test constructor with IPv6 options |
| 1776 | const addr3 = new net.SocketAddress({ |
| 1777 | address: '::1', |
| 1778 | port: 3000, |
| 1779 | family: 'ipv6', |
| 1780 | flowlabel: 123, |
| 1781 | }); |
| 1782 | strictEqual(addr3.address, '::1'); |
| 1783 | strictEqual(addr3.port, 3000); |
| 1784 | strictEqual(addr3.family, 'ipv6'); |
| 1785 | strictEqual(addr3.flowlabel, 123); |
| 1786 | |
| 1787 | // Test default IPv6 address |
| 1788 | const addr4 = new net.SocketAddress({ family: 'ipv6' }); |
| 1789 | strictEqual(addr4.address, '::'); |
| 1790 | strictEqual(addr4.family, 'ipv6'); |
| 1791 | |
| 1792 | // Test toJSON method |
| 1793 | const addr5 = new net.SocketAddress({ |
| 1794 | address: '10.0.0.1', |
| 1795 | port: 9000, |
| 1796 | family: 'ipv4', |
| 1797 | }); |
| 1798 | const json = addr5.toJSON(); |
| 1799 | strictEqual(json.address, '10.0.0.1'); |
| 1800 | strictEqual(json.port, 9000); |
| 1801 | strictEqual(json.family, 'ipv4'); |
| 1802 | strictEqual(json.flowlabel, 0); |
| 1803 | |
| 1804 | // Test isSocketAddress static method |
| 1805 | ok(net.SocketAddress.isSocketAddress(addr1)); |
| 1806 | ok(net.SocketAddress.isSocketAddress(addr2)); |
| 1807 | ok(!net.SocketAddress.isSocketAddress({})); |
| 1808 | ok(!net.SocketAddress.isSocketAddress(null)); |
| 1809 | ok(!net.SocketAddress.isSocketAddress('string')); |
| 1810 | |
| 1811 | // Test parse static method with IPv4 |
| 1812 | const parsed1 = net.SocketAddress.parse('192.168.1.100:8080'); |
| 1813 | ok(parsed1); |
| 1814 | strictEqual(parsed1.address, '192.168.1.100'); |
| 1815 | strictEqual(parsed1.port, 8080); |
| 1816 | strictEqual(parsed1.family, 'ipv4'); |
| 1817 | |
| 1818 | // Test parse static method with IPv6 |
| 1819 | const parsed2 = net.SocketAddress.parse('[::1]:3000'); |
| 1820 | ok(parsed2); |
| 1821 | strictEqual(parsed2.address, '::1'); |
| 1822 | strictEqual(parsed2.port, 3000); |
| 1823 | strictEqual(parsed2.family, 'ipv6'); |
| 1824 | |
| 1825 | // Test parse with invalid input |
| 1826 | strictEqual(net.SocketAddress.parse('invalid'), undefined); |
| 1827 | strictEqual(net.SocketAddress.parse(''), undefined); |
| 1828 | |
| 1829 | // Test constructor validation - invalid family |
| 1830 | throws(() => new net.SocketAddress({ family: 'invalid' }), { |
| 1831 | code: 'ERR_INVALID_ARG_VALUE', |
| 1832 | }); |
| 1833 | |
| 1834 | // Test constructor validation - invalid IPv4 address |
| 1835 | throws( |
| 1836 | () => |
| 1837 | new net.SocketAddress({ |
| 1838 | address: '300.300.300.300', |
| 1839 | family: 'ipv4', |
| 1840 | }), |
| 1841 | { |
| 1842 | code: 'ERR_INVALID_ADDRESS', |
| 1843 | } |
| 1844 | ); |
| 1845 | |
| 1846 | // Test constructor validation - invalid IPv6 address |
| 1847 | throws( |
| 1848 | () => |
| 1849 | new net.SocketAddress({ |
| 1850 | address: 'invalid::ipv6', |
| 1851 | family: 'ipv6', |
| 1852 | }), |
| 1853 | { |
| 1854 | code: 'ERR_INVALID_ADDRESS', |
| 1855 | } |
| 1856 | ); |
| 1857 | |
| 1858 | // Test constructor validation - invalid port |
| 1859 | throws(() => new net.SocketAddress({ port: -1 }), { |
| 1860 | code: 'ERR_SOCKET_BAD_PORT', |
| 1861 | }); |
| 1862 | |
| 1863 | throws(() => new net.SocketAddress({ port: 65536 }), { |
| 1864 | code: 'ERR_SOCKET_BAD_PORT', |
| 1865 | }); |
| 1866 | |
| 1867 | // Test family case insensitive |
| 1868 | const addr6 = new net.SocketAddress({ family: 'IPv4' }); |
| 1869 | strictEqual(addr6.family, 'ipv4'); |
| 1870 | |
| 1871 | const addr7 = new net.SocketAddress({ family: 'IPv6' }); |
| 1872 | strictEqual(addr7.family, 'ipv6'); |
| 1873 | |
| 1874 | // Test port type coercion |
| 1875 | const addr8 = new net.SocketAddress({ port: '8080' }); |
| 1876 | console.log(typeof addr8.port); |
| 1877 | strictEqual(addr8.port, 8080); |
| 1878 | }, |
| 1879 | }; |
| 1880 | |
| 1881 | export const testBlockList = { |
| 1882 | test() { |
| 1883 | // Test BlockList constructor and static methods |
| 1884 | const bl = new net.BlockList(); |
| 1885 | ok(net.BlockList.isBlockList(bl)); |
| 1886 | ok(!net.BlockList.isBlockList({})); |
| 1887 | ok(!net.BlockList.isBlockList(null)); |
| 1888 | |
| 1889 | // Test addAddress with IPv4 |
| 1890 | bl.addAddress('192.168.1.1'); |
| 1891 | bl.addAddress('10.0.0.1', 'ipv4'); |
| 1892 | |
| 1893 | // Test check method with IPv4 addresses |
| 1894 | ok(bl.check('192.168.1.1')); |
| 1895 | ok(bl.check('10.0.0.1', 'ipv4')); |
| 1896 | ok(!bl.check('192.168.1.2')); |
| 1897 | ok(!bl.check('192.168.1.1', 'ipv6')); |
| 1898 | |
| 1899 | // Test addAddress with IPv6 |
| 1900 | bl.addAddress('2001:db8::1', 'ipv6'); |
| 1901 | ok(bl.check('2001:db8::1', 'ipv6')); |
| 1902 | ok(!bl.check('2001:db8::2', 'ipv6')); |
| 1903 | |
| 1904 | // Test addAddress with SocketAddress |
| 1905 | const addr1 = new net.SocketAddress({ address: '172.16.0.1', port: 80 }); |
| 1906 | bl.addAddress(addr1); |
| 1907 | ok(bl.check(addr1)); |
| 1908 | ok(bl.check('172.16.0.1')); |
| 1909 | |
| 1910 | // Test addRange with IPv4 |
| 1911 | bl.addRange('192.168.2.1', '192.168.2.10'); |
| 1912 | ok(bl.check('192.168.2.1')); |
| 1913 | ok(bl.check('192.168.2.5')); |
| 1914 | ok(bl.check('192.168.2.10')); |
| 1915 | ok(!bl.check('192.168.2.11')); |
| 1916 | ok(!bl.check('192.168.1.255')); |
| 1917 | |
| 1918 | // Test addRange with IPv6 |
| 1919 | bl.addRange('2001:db8::10', '2001:db8::20', 'ipv6'); |
| 1920 | ok(bl.check('2001:db8::15', 'ipv6')); |
| 1921 | ok(bl.check('2001:db8::10', 'ipv6')); |
| 1922 | ok(bl.check('2001:db8::20', 'ipv6')); |
| 1923 | ok(!bl.check('2001:db8::21', 'ipv6')); |
| 1924 | |
| 1925 | // Test addRange with SocketAddress |
| 1926 | const startAddr = new net.SocketAddress({ |
| 1927 | address: '172.16.1.1', |
| 1928 | port: 80, |
| 1929 | }); |
| 1930 | const endAddr = new net.SocketAddress({ address: '172.16.1.5', port: 80 }); |
| 1931 | bl.addRange(startAddr, endAddr); |
| 1932 | ok(bl.check('172.16.1.3')); |
| 1933 | ok(!bl.check('172.16.1.6')); |
| 1934 | |
| 1935 | // Test addSubnet with IPv4 |
| 1936 | bl.addSubnet('10.1.0.0', 24); |
| 1937 | ok(bl.check('10.1.0.1')); |
| 1938 | ok(bl.check('10.1.0.255')); |
| 1939 | ok(!bl.check('10.1.1.1')); |
| 1940 | |
| 1941 | // Test addSubnet with IPv6 |
| 1942 | bl.addSubnet('2001:db8::', 32, 'ipv6'); |
| 1943 | ok(bl.check('2001:db8::1', 'ipv6')); |
| 1944 | ok(bl.check('2001:db8:ffff::1', 'ipv6')); |
| 1945 | ok(!bl.check('2001:db9::1', 'ipv6')); |
| 1946 | |
| 1947 | // Test addSubnet with SocketAddress |
| 1948 | const subnetAddr = new net.SocketAddress({ |
| 1949 | address: '172.17.0.0', |
| 1950 | port: 80, |
| 1951 | }); |
| 1952 | bl.addSubnet(subnetAddr, 16); |
| 1953 | ok(bl.check('172.17.1.1')); |
| 1954 | ok(bl.check('172.17.255.255')); |
| 1955 | ok(!bl.check('172.18.0.1')); |
| 1956 | |
| 1957 | // Test rules getter |
| 1958 | const rules = bl.rules; |
| 1959 | ok(Array.isArray(rules)); |
| 1960 | ok(rules.length > 0); |
| 1961 | ok(rules.some((rule) => rule.includes('Address: IPv4 192.168.1.1'))); |
| 1962 | ok( |
| 1963 | rules.some((rule) => |
| 1964 | rule.includes('Range: IPv4 192.168.2.1-192.168.2.10') |
| 1965 | ) |
| 1966 | ); |
| 1967 | ok(rules.some((rule) => rule.includes('Subnet: IPv4 10.1.0.0/24'))); |
| 1968 | |
| 1969 | // Test toJSON |
| 1970 | const json = bl.toJSON(); |
| 1971 | ok(Array.isArray(json)); |
| 1972 | deepStrictEqual(json, rules); |
| 1973 | |
| 1974 | // Test fromJSON |
| 1975 | const bl2 = new net.BlockList(); |
| 1976 | bl2.fromJSON(['Address: IPv4 203.0.113.1', 'Subnet: IPv4 198.51.100.0/24']); |
| 1977 | ok(bl2.check('203.0.113.1')); |
| 1978 | ok(bl2.check('198.51.100.100')); |
| 1979 | ok(!bl2.check('203.0.113.2')); |
| 1980 | |
| 1981 | // Test error cases |
| 1982 | throws(() => bl.addAddress(123), { |
| 1983 | code: 'ERR_INVALID_ARG_TYPE', |
| 1984 | }); |
| 1985 | |
| 1986 | throws(() => bl.addAddress('invalid.ip'), { |
| 1987 | code: 'ERR_INVALID_IP_ADDRESS', |
| 1988 | }); |
| 1989 | |
| 1990 | throws(() => bl.addAddress('192.168.1.1', 'invalid'), { |
| 1991 | code: 'ERR_INVALID_ARG_VALUE', |
| 1992 | }); |
| 1993 | |
| 1994 | throws(() => bl.addRange('192.168.1.10', '192.168.1.1'), { |
| 1995 | code: 'ERR_INVALID_ARG_VALUE', |
| 1996 | }); |
| 1997 | |
| 1998 | throws(() => bl.addSubnet('192.168.1.0', 33), { |
| 1999 | code: 'ERR_OUT_OF_RANGE', |
| 2000 | }); |
| 2001 | |
| 2002 | throws(() => bl.addSubnet('192.168.1.0', -1), { |
| 2003 | code: 'ERR_OUT_OF_RANGE', |
| 2004 | }); |
| 2005 | |
| 2006 | // Test IPv4-mapped IPv6 addresses |
| 2007 | bl.addAddress('192.168.10.1'); |
| 2008 | ok(bl.check('::ffff:192.168.10.1', 'ipv6')); |
| 2009 | |
| 2010 | bl.addRange('192.168.11.1', '192.168.11.10'); |
| 2011 | ok(bl.check('::ffff:192.168.11.5', 'ipv6')); |
| 2012 | |
| 2013 | bl.addSubnet('192.168.12.0', 24); |
| 2014 | ok(bl.check('::ffff:192.168.12.100', 'ipv6')); |
| 2015 | }, |
| 2016 | }; |