diff options
author | 2022-10-25 00:44:25 -0700 | |
---|---|---|
committer | 2022-10-25 00:44:25 -0700 | |
commit | 02c920f4fd09ddc1a32cb2e92c6f391875415949 (patch) | |
tree | 4f524f5ce9d672fadb8740c68cc9b1a8410a714f /test/bun.js/tcp-server.test.ts | |
parent | 1b50ecc52b55df0c00f991c8206d4ced84ad89b8 (diff) | |
download | bun-02c920f4fd09ddc1a32cb2e92c6f391875415949.tar.gz bun-02c920f4fd09ddc1a32cb2e92c6f391875415949.tar.zst bun-02c920f4fd09ddc1a32cb2e92c6f391875415949.zip |
TCP & TLS Socket API (#1374)
* TCP Socket API
* Wip
* Add snippet for StringDecoder
* Rename `close` to `stop`, replace `close` with `end`
* Add a tcp echo server test
* Some docs
* Update README.md
* Fix build
* Update README.md
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'test/bun.js/tcp-server.test.ts')
-rw-r--r-- | test/bun.js/tcp-server.test.ts | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/test/bun.js/tcp-server.test.ts b/test/bun.js/tcp-server.test.ts new file mode 100644 index 000000000..f0dfc8ce5 --- /dev/null +++ b/test/bun.js/tcp-server.test.ts @@ -0,0 +1,114 @@ +import { listen, connect, finalizationCounter } from "bun"; +import { expect, describe, it } from "bun:test"; +import * as JSC from "bun:jsc"; + +var decoder = new TextDecoder(); + +it("echo server 1 on 1", async () => { + // wrap it in a separate closure so the GC knows to clean it up + // the sockets & listener don't escape the closure + await (async function () { + var resolve, reject, serverResolve, serverReject; + var prom = new Promise((resolve1, reject1) => { + resolve = resolve1; + reject = reject1; + }); + var serverProm = new Promise((resolve1, reject1) => { + serverResolve = resolve1; + serverReject = reject1; + }); + + var serverData, clientData; + const handlers = { + open(socket) { + socket.data.counter = 1; + if (!socket.data?.isServer) { + clientData = socket.data; + clientData.sendQueue = ["client: Hello World! " + 0]; + if (!socket.write("client: Hello World! " + 0)) { + socket.data = { pending: "server: Hello World! " + 0 }; + } + } else { + serverData = socket.data; + serverData.sendQueue = ["server: Hello World! " + 0]; + } + + if (clientData) clientData.other = serverData; + if (serverData) serverData.other = clientData; + if (clientData) clientData.other = serverData; + if (serverData) serverData.other = clientData; + }, + data(socket, buffer) { + const msg = `${ + socket.data.isServer ? "server:" : "client:" + } Hello World! ${socket.data.counter++}`; + socket.data.sendQueue.push(msg); + + expect(decoder.decode(buffer)).toBe(socket.data.other.sendQueue.pop()); + + if (socket.data.counter > 10) { + if (!socket.data.finished) { + socket.data.finished = true; + if (socket.data.isServer) { + setTimeout(() => { + serverResolve(); + socket.end(); + }, 1); + } else { + setTimeout(() => { + resolve(); + socket.end(); + }, 1); + } + } + } + + if (!socket.write(msg)) { + socket.data.pending = msg; + return; + } + }, + error(socket, error) { + reject(error); + }, + drain(socket) { + reject(new Error("Unexpected backpressure")); + }, + }; + + var server = listen({ + socket: handlers, + hostname: "localhost", + port: 8084, + data: { + isServer: true, + counter: 0, + }, + }); + connect({ + socket: handlers, + hostname: "localhost", + port: 8084, + data: { + counter: 0, + }, + }); + await Promise.all([prom, serverProm]); + server.stop(); + server = serverData = clientData = undefined; + Bun.gc(true); + })(); + + // Tell the garbage collector for sure that we're done with the sockets + await new Promise((resolve, reject) => { + setTimeout(() => { + Bun.gc(true); + resolve(); + }, 1); + }); + + // assert we don't leak the sockets + // we expect 1 because that's the prototype / structure + expect(JSC.heapStats().objectTypeCounts.TCPSocket).toBe(1); + expect(JSC.heapStats().objectTypeCounts.Listener).toBe(1); +}); |