diff options
author | 2023-03-07 12:22:34 -0800 | |
---|---|---|
committer | 2023-03-07 12:22:34 -0800 | |
commit | f7e4eb83694aa007a492ef66c28ffbe6a2dae791 (patch) | |
tree | 7af25aa5c42a2e1b2b47ba1df35f8caa9054cbeb /test/bun.js/websocket-server.test.ts | |
parent | 36275a44ce7a33587bd26aad120042ab95470ff3 (diff) | |
download | bun-f7e4eb83694aa007a492ef66c28ffbe6a2dae791.tar.gz bun-f7e4eb83694aa007a492ef66c28ffbe6a2dae791.tar.zst bun-f7e4eb83694aa007a492ef66c28ffbe6a2dae791.zip |
Reorganize tests (#2332)
Diffstat (limited to 'test/bun.js/websocket-server.test.ts')
-rw-r--r-- | test/bun.js/websocket-server.test.ts | 963 |
1 files changed, 0 insertions, 963 deletions
diff --git a/test/bun.js/websocket-server.test.ts b/test/bun.js/websocket-server.test.ts deleted file mode 100644 index 3205ff949..000000000 --- a/test/bun.js/websocket-server.test.ts +++ /dev/null @@ -1,963 +0,0 @@ -import { describe, expect, it } from "bun:test"; -import { gcTick } from "./gc"; -import { serve } from "bun"; - -var port = 4301; -function getPort() { - if (port > 4444) { - port = 4321; - } - - return port++; -} - -describe("websocket server", () => { - it("can do publish()", async done => { - var server = serve({ - port: getPort(), - websocket: { - open(ws) { - ws.subscribe("all"); - }, - message(ws, msg) {}, - close(ws) {}, - }, - fetch(req, server) { - if (server.upgrade(req)) { - return; - } - - return new Response("success"); - }, - }); - - await new Promise<void>((resolve2, reject2) => { - var socket = new WebSocket(`ws://${server.hostname}:${server.port}`); - var clientCounter = 0; - - socket.onmessage = e => { - expect(e.data).toBe("hello"); - resolve2(); - }; - socket.onopen = () => { - queueMicrotask(() => { - server.publish("all", "hello"); - }); - }; - }); - server.stop(true); - done(); - }); - - it("can do publish() with publishToSelf: false", async done => { - var server = serve({ - port: getPort(), - websocket: { - open(ws) { - ws.subscribe("all"); - ws.publish("all", "hey"); - server.publish("all", "hello"); - }, - message(ws, msg) { - if (new TextDecoder().decode(msg) !== "hello") { - done(new Error("unexpected message")); - } - }, - close(ws) {}, - publishToSelf: false, - }, - fetch(req, server) { - if (server.upgrade(req)) { - return; - } - - return new Response("success"); - }, - }); - - await new Promise<void>((resolve2, reject2) => { - var socket = new WebSocket(`ws://${server.hostname}:${server.port}`); - - socket.onmessage = e => { - expect(e.data).toBe("hello"); - resolve2(); - }; - }); - server.stop(true); - done(); - }); - - for (let method of ["publish", "publishText", "publishBinary"]) { - describe(method, () => { - it("in close() should work", async () => { - var count = 0; - var server = serve({ - port: getPort(), - websocket: { - open(ws) { - ws.subscribe("all"); - }, - message(ws, msg) {}, - close(ws) { - ws[method]("all", method === "publishBinary" ? Buffer.from("bye!") : "bye!"); - count++; - - if (count >= 2) { - server.stop(true); - } - }, - }, - fetch(req, server) { - if (server.upgrade(req)) { - return; - } - - return new Response("success"); - }, - }); - - try { - const first = await new Promise<WebSocket>((resolve2, reject2) => { - var socket = new WebSocket(`ws://${server.hostname}:${server.port}`); - socket.onopen = () => resolve2(socket); - }); - - await new Promise<WebSocket>((resolve2, reject2) => { - var socket = new WebSocket(`ws://${server.hostname}:${server.port}`); - socket.onopen = () => { - queueMicrotask(() => first.close()); - }; - socket.onmessage = ev => { - var msg = ev.data; - if (typeof msg !== "string") { - msg = new TextDecoder().decode(msg); - } - - if (msg === "bye!") { - socket.close(0); - resolve2(socket); - } else { - reject2(msg); - } - }; - }); - } finally { - server.stop(true); - } - }); - }); - } - - it("close inside open", async () => { - var resolve; - console.trace("here"); - var server = serve({ - port: getPort(), - websocket: { - open(ws) {}, - message(ws, msg) {}, - close() { - resolve(); - server.stop(true); - }, - }, - fetch(req, server) { - if ( - server.upgrade(req, { - data: "hello world", - - // check that headers works - headers: { - "x-a": "text/plain", - }, - }) - ) { - if (server.upgrade(req)) { - throw new Error("should not upgrade twice"); - } - return; - } - - return new Response("noooooo hello world"); - }, - }); - - await new Promise<void>((resolve_, reject) => { - resolve = resolve_; - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - websocket.onopen = () => { - websocket.close(); - }; - websocket.onmessage = e => {}; - websocket.onerror = e => {}; - }); - }); - - it("headers error doesn't crash", async () => { - await new Promise<void>((resolve, reject) => { - const server = serve({ - port: getPort(), - websocket: { - open(ws) { - ws.close(); - }, - message(ws, msg) {}, - close() { - resolve(); - server.stop(true); - }, - }, - error(err) { - resolve(); - server.stop(true); - }, - fetch(req, server) { - expect(() => { - if ( - server.upgrade(req, { - data: "hello world", - headers: 1238 as any, - }) - ) { - reject(new Error("should not upgrade")); - return new Response("should not upgrade"); - } - }).toThrow("upgrade options.headers must be a Headers or an object"); - resolve(); - return new Response("success"); - }, - }); - - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - websocket.onopen = () => websocket.close(); - websocket.onmessage = e => {}; - websocket.onerror = e => {}; - }); - }); - it("can do hello world", async () => { - const server = serve({ - port: getPort(), - websocket: { - open(ws) { - server.stop(); - }, - message(ws, msg) { - ws.send("hello world"); - }, - }, - fetch(req, server) { - server.stop(); - if ( - server.upgrade(req, { - data: "hello world", - - // check that headers works - headers: { - "x-a": "text/plain", - }, - }) - ) { - if (server.upgrade(req)) { - throw new Error("should not upgrade twice"); - } - return; - } - - return new Response("noooooo hello world"); - }, - }); - - await new Promise<void>((resolve, reject) => { - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - websocket.onopen = () => { - websocket.send("hello world"); - }; - websocket.onmessage = e => { - try { - expect(e.data).toBe("hello world"); - resolve(); - } catch (r) { - reject(r); - } finally { - websocket.close(); - } - }; - websocket.onerror = e => { - reject(e); - }; - }); - }); - - it("fetch() allows a Response object to be returned for an upgraded ServerWebSocket", () => { - const server = serve({ - port: getPort(), - websocket: { - open(ws) { - server.stop(); - }, - message(ws, msg) { - ws.send("hello world"); - }, - }, - error(err) { - console.error(err); - }, - fetch(req, server) { - server.stop(); - if ( - server.upgrade(req, { - data: "hello world", - - // check that headers works - headers: { - "x-a": "text/plain", - }, - }) - ) { - if (server.upgrade(req)) { - throw new Error("should not upgrade twice"); - } - return new Response("lol!", { - status: 101, - }); - } - - return new Response("noooooo hello world"); - }, - }); - - return new Promise<void>((resolve, reject) => { - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - websocket.onopen = () => { - websocket.send("hello world"); - }; - websocket.onmessage = e => { - try { - expect(e.data).toBe("hello world"); - resolve(); - } catch (r) { - reject(r); - } finally { - websocket.close(); - } - }; - websocket.onerror = e => { - reject(e); - }; - }); - }); - - it("fetch() allows a Promise<Response> object to be returned for an upgraded ServerWebSocket", () => { - const server = serve({ - port: getPort(), - websocket: { - async open(ws) { - server.stop(); - }, - async message(ws, msg) { - await 1; - ws.send("hello world"); - }, - }, - error(err) { - console.error(err); - }, - async fetch(req, server) { - server.stop(); - await 1; - if ( - server.upgrade(req, { - data: "hello world", - - // check that headers works - headers: { - "x-a": "text/plain", - }, - }) - ) { - if (server.upgrade(req)) { - throw new Error("should not upgrade twice"); - } - return new Response("lol!", { - status: 101, - }); - } - - return new Response("noooooo hello world"); - }, - }); - return new Promise<void>((resolve, reject) => { - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - websocket.onopen = () => { - websocket.send("hello world"); - }; - websocket.onmessage = e => { - try { - expect(e.data).toBe("hello world"); - resolve(); - } catch (r) { - reject(r); - } finally { - websocket.close(); - } - }; - websocket.onerror = e => { - reject(e); - }; - }); - }); - it("binaryType works", async () => { - var done = false; - const server = serve({ - port: getPort(), - websocket: { - open(ws) { - server.stop(); - }, - message(ws, msg) { - if (ws.binaryType === "uint8array") { - expect(ws.binaryType).toBe("uint8array"); - ws.binaryType = "arraybuffer"; - expect(ws.binaryType).toBe("arraybuffer"); - expect(msg instanceof Uint8Array).toBe(true); - } else { - expect(ws.binaryType).toBe("arraybuffer"); - expect(msg instanceof ArrayBuffer).toBe(true); - done = true; - } - - ws.send("hello world"); - }, - }, - fetch(req, server) { - server.stop(); - if (server.upgrade(req, { data: "hello world" })) { - if (server.upgrade(req)) { - throw new Error("should not upgrade twice"); - } - return; - } - - return new Response("noooooo hello world"); - }, - }); - - await new Promise<boolean>((resolve, reject) => { - var counter = 0; - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - websocket.onopen = () => { - websocket.send(Buffer.from("hello world")); - }; - websocket.onmessage = e => { - try { - expect(e.data).toBe("hello world"); - - if (counter++ > 0) { - websocket.close(); - resolve(done); - } - websocket.send(Buffer.from("oaksd")); - } catch (r) { - websocket.close(); - reject(r); - } - }; - websocket.onerror = e => { - reject(e); - }; - }); - }); - - it("does not upgrade for non-websocket connections", async () => { - await new Promise<void>(async (resolve, reject) => { - var server = serve({ - port: getPort(), - websocket: { - open(ws) { - ws.send("hello world"); - }, - message(ws, msg) {}, - }, - fetch(req, server) { - if (server.upgrade(req)) { - reject(new Error("should not upgrade")); - } - - return new Response("success"); - }, - }); - - const response = await fetch(`http://${server.hostname}:${server.port}`); - expect(await response.text()).toBe("success"); - resolve(); - server.stop(true); - }); - }); - - it("does not upgrade for non-websocket servers", async () => { - await new Promise<void>(async (resolve, reject) => { - const server = serve({ - port: getPort(), - fetch(req, server) { - server.stop(); - expect(() => { - server.upgrade(req); - }).toThrow('To enable websocket support, set the "websocket" object in Bun.serve({})'); - return new Response("success"); - }, - }); - - const response = await fetch(`http://${server.hostname}:${server.port}`); - expect(await response.text()).toBe("success"); - resolve(); - }); - }); - - it("async can do hello world", async () => { - const server = serve({ - port: getPort(), - websocket: { - async open(ws) { - server.stop(true); - ws.send("hello world"); - }, - message(ws, msg) {}, - }, - async fetch(req, server) { - server.stop(); - await 1; - if (server.upgrade(req)) return; - - return new Response("noooooo hello world"); - }, - }); - - await new Promise<void>((resolve, reject) => { - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - - websocket.onmessage = e => { - try { - expect(e.data).toBe("hello world"); - resolve(); - } catch (r) { - reject(r); - } finally { - websocket.close(); - } - }; - websocket.onerror = e => { - reject(e); - }; - }); - }); - - it("publishText()", async () => { - await new Promise<void>((resolve, reject) => { - var websocket; - var server = serve({ - port: getPort(), - websocket: { - async open(ws) { - // we don't care about the data - // we just want to make sure the DOMJIT call doesn't crash - for (let i = 0; i < 40_000; i++) ws.publishText("hello", "world"); - websocket.close(); - server.stop(true); - resolve(); - }, - message(ws, msg) {}, - }, - async fetch(req, server) { - await 1; - if (server.upgrade(req)) return; - - return new Response("noooooo hello world"); - }, - }); - - websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - }); - }); - - it("publishBinary()", async () => { - const bytes = Buffer.from("hello"); - - await new Promise<void>((resolve, reject) => { - var websocket; - var server = serve({ - port: getPort(), - websocket: { - async open(ws) { - // we don't care about the data - // we just want to make sure the DOMJIT call doesn't crash - for (let i = 0; i < 40_000; i++) ws.publishBinary("hello", bytes); - websocket.close(); - server.stop(true); - resolve(); - }, - message(ws, msg) {}, - }, - async fetch(req, server) { - await 1; - if (server.upgrade(req)) return; - - return new Response("noooooo hello world"); - }, - }); - - websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - }); - }); - - it("sendText()", async () => { - await new Promise<void>((resolve, reject) => { - var websocket; - var server = serve({ - port: getPort(), - websocket: { - async open(ws) { - // we don't care about the data - // we just want to make sure the DOMJIT call doesn't crash - for (let i = 0; i < 40_000; i++) ws.sendText("hello world", true); - resolve(); - websocket.close(); - server.stop(true); - }, - message(ws, msg) {}, - }, - async fetch(req, server) { - await 1; - if (server.upgrade(req)) return; - - return new Response("noooooo hello world"); - }, - }); - websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - }); - }); - - it("sendBinary()", async () => { - const bytes = Buffer.from("hello"); - await new Promise<void>((resolve, reject) => { - var websocket; - var server = serve({ - port: getPort(), - websocket: { - async open(ws) { - // we don't care about the data - // we just want to make sure the DOMJIT call doesn't crash - for (let i = 0; i < 40_000; i++) ws.sendBinary(bytes, true); - websocket.close(); - server.stop(true); - resolve(); - }, - message(ws, msg) {}, - }, - async fetch(req, server) { - await 1; - if (server.upgrade(req)) return; - - return new Response("noooooo hello world"); - }, - }); - - websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - }); - }); - - it("can do hello world corked", async () => { - const server = serve({ - port: getPort(), - websocket: { - open(ws) { - server.stop(); - ws.send("hello world"); - }, - message(ws, msg) { - ws.cork(() => { - ws.send("hello world"); - }); - }, - }, - fetch(req, server) { - server.stop(); - if (server.upgrade(req)) return; - return new Response("noooooo hello world"); - }, - }); - - await new Promise<void>((resolve, reject) => { - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - - websocket.onmessage = e => { - try { - expect(e.data).toBe("hello world"); - resolve(); - } catch (r) { - reject(r); - } finally { - websocket.close(); - } - }; - websocket.onerror = e => { - reject(e); - }; - }); - server.stop(true); - }); - - it("can do some back and forth", async () => { - var dataCount = 0; - const server = serve({ - port: getPort(), - websocket: { - open(ws) { - server.stop(); - }, - message(ws, msg) { - if (msg === "first") { - ws.send("first"); - return; - } - ws.send(`counter: ${dataCount++}`); - }, - }, - fetch(req, server) { - server.stop(); - if ( - server.upgrade(req, { - data: { count: 0 }, - }) - ) - return new Response("noooooo hello world"); - }, - }); - - await new Promise<void>((resolve, reject) => { - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - websocket.onerror = e => { - reject(e); - }; - - var counter = 0; - websocket.onopen = () => websocket.send("first"); - websocket.onmessage = e => { - try { - switch (counter++) { - case 0: { - expect(e.data).toBe("first"); - websocket.send("where are the loops"); - break; - } - case 1: { - expect(e.data).toBe("counter: 0"); - websocket.send("br0ther may i have some loops"); - break; - } - case 2: { - expect(e.data).toBe("counter: 1"); - websocket.send("br0ther may i have some loops"); - break; - } - case 3: { - expect(e.data).toBe("counter: 2"); - resolve(); - break; - } - } - } catch (r) { - reject(r); - websocket.close(); - } - }; - }); - server.stop(true); - }); - - it("send rope strings", async () => { - var ropey = "hello world".repeat(10); - var sendQueue: any[] = []; - for (var i = 0; i < 100; i++) { - sendQueue.push(ropey + " " + i); - } - - var serverCounter = 0; - var clientCounter = 0; - - const server = serve({ - port: getPort(), - websocket: { - open(ws) { - server.stop(); - }, - message(ws, msg) { - ws.send(sendQueue[serverCounter++] + " "); - gcTick(); - }, - }, - fetch(req, server) { - server.stop(); - if ( - server.upgrade(req, { - data: { count: 0 }, - }) - ) - return; - - return new Response("noooooo hello world"); - }, - }); - - await new Promise<void>((resolve, reject) => { - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - websocket.onerror = e => { - reject(e); - }; - - var counter = 0; - websocket.onopen = () => websocket.send("first"); - websocket.onmessage = e => { - try { - const expected = sendQueue[clientCounter++] + " "; - expect(e.data).toBe(expected); - websocket.send("next"); - if (clientCounter === sendQueue.length) { - websocket.close(); - resolve(); - } - } catch (r) { - reject(r); - console.error(r); - websocket.close(); - } - }; - }); - server.stop(true); - }); - - // this test sends 100 messages to 10 connected clients via pubsub - it("pub/sub", async () => { - var ropey = "hello world".repeat(10); - var sendQueue: any[] = []; - for (var i = 0; i < 100; i++) { - sendQueue.push(ropey + " " + i); - gcTick(); - } - var serverCounter = 0; - var clientCount = 0; - const server = serve({ - port: getPort(), - websocket: { - open(ws) { - server.stop(); - ws.subscribe("test"); - gcTick(); - if (!ws.isSubscribed("test")) { - throw new Error("not subscribed"); - } - ws.unsubscribe("test"); - if (ws.isSubscribed("test")) { - throw new Error("subscribed"); - } - ws.subscribe("test"); - clientCount++; - if (clientCount === 10) setTimeout(() => ws.publish("test", "hello world"), 1); - }, - message(ws, msg) { - if (serverCounter < sendQueue.length) ws.publish("test", sendQueue[serverCounter++] + " "); - }, - }, - fetch(req) { - gcTick(); - server.stop(); - if ( - server.upgrade(req, { - data: { count: 0 }, - }) - ) - return; - return new Response("noooooo hello world"); - }, - }); - - const connections = new Array(10); - const websockets = new Array(connections.length); - var doneCounter = 0; - await new Promise<void>(done => { - for (var i = 0; i < connections.length; i++) { - var j = i; - var resolve, reject, resolveConnection, rejectConnection; - connections[j] = new Promise((res, rej) => { - resolveConnection = res; - rejectConnection = rej; - }); - websockets[j] = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - gcTick(); - const websocket = new WebSocket(`ws://${server.hostname}:${server.port}`); - websocket.onerror = e => { - reject(e); - }; - websocket.onclose = () => { - doneCounter++; - if (doneCounter === connections.length) { - done(); - } - }; - var hasOpened = false; - websocket.onopen = () => { - if (!hasOpened) { - hasOpened = true; - resolve(websocket); - } - }; - - let clientCounter = -1; - var hasSentThisTick = false; - - websocket.onmessage = e => { - gcTick(); - - if (!hasOpened) { - hasOpened = true; - resolve(websocket); - } - - if (e.data === "hello world") { - clientCounter = 0; - websocket.send("first"); - return; - } - - try { - expect(!!sendQueue.find(a => a + " " === e.data)).toBe(true); - - if (!hasSentThisTick) { - websocket.send("second"); - hasSentThisTick = true; - queueMicrotask(() => { - hasSentThisTick = false; - }); - } - - gcTick(); - - if (clientCounter++ === sendQueue.length - 1) { - websocket.close(); - resolveConnection(); - } - } catch (r) { - console.error(r); - websocket.close(); - rejectConnection(r); - gcTick(); - } - }; - } - }); - expect(serverCounter).toBe(sendQueue.length); - server.stop(true); - }); -}); |