/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; /* global structuredClone */ var gPort; var gExtraListener; function run_test() { info("Starting test at " + new Date().toTimeString()); initTestDevToolsServer(); add_task(test_socket_conn); add_task(test_socket_shutdown); add_test(test_pipe_conn); run_next_test(); } const { Actor } = require("resource://devtools/shared/protocol/Actor.js"); class EchoTestActor extends Actor { constructor(conn) { super(conn, { typeName: "EchoTestActor", methods: [] }); this.requestTypes = { echo: EchoTestActor.prototype.onEcho, }; } onEcho(request) { /* * Request packets are frozen. Copy request, so that * DevToolsServerConnection.onPacket can attach a 'from' property. */ return structuredClone(request); } } async function test_socket_conn() { Assert.equal(DevToolsServer.listeningSockets, 0); const AuthenticatorType = DevToolsServer.Authenticators.get("PROMPT"); const authenticator = new AuthenticatorType.Server(); authenticator.allowConnection = () => { return DevToolsServer.AuthenticationResult.ALLOW; }; const socketOptions = { authenticator, portOrPath: -1, }; const listener = new SocketListener(DevToolsServer, socketOptions); Assert.ok(listener); listener.open(); Assert.equal(DevToolsServer.listeningSockets, 1); gPort = DevToolsServer._listeners[0].port; info("DevTools server port is " + gPort); // Open a second, separate listener gExtraListener = new SocketListener(DevToolsServer, socketOptions); gExtraListener.open(); Assert.equal(DevToolsServer.listeningSockets, 2); Assert.ok(!DevToolsServer.hasConnection()); info("Starting long and unicode tests at " + new Date().toTimeString()); // We can't use EventEmitter.once as this is the second argument we care about... const onConnectionChange = new Promise(res => { DevToolsServer.once("connectionchange", (type, conn) => res(conn)); }); const transport = await DevToolsClient.socketConnect({ host: "127.0.0.1", port: gPort, }); Assert.ok(DevToolsServer.hasConnection()); info("Wait for server connection"); const conn = await onConnectionChange; // Register a custom actor to do echo requests const actor = new EchoTestActor(conn); actor.actorID = "echo-actor"; conn.addActor(actor); // Assert that connection settings are available on transport object const settings = transport.connectionSettings; Assert.equal(settings.host, "127.0.0.1"); Assert.equal(settings.port, gPort); const onDebuggerConnectionClosed = DevToolsServer.once("connectionchange"); const unicodeString = "(╯°□°)╯︵ ┻━┻"; await new Promise(resolve => { transport.hooks = { onPacket(packet) { this.onPacket = function ({ unicode }) { Assert.equal(unicode, unicodeString); transport.close(); }; // Verify that things work correctly when bigger than the output // transport buffers and when transporting unicode... transport.send({ to: "echo-actor", type: "echo", reallylong: really_long(), unicode: unicodeString, }); Assert.equal(packet.from, "root"); }, onTransportClosed(status) { resolve(); }, }; transport.ready(); }); const type = await onDebuggerConnectionClosed; Assert.equal(type, "closed"); Assert.ok(!DevToolsServer.hasConnection()); } async function test_socket_shutdown() { Assert.equal(DevToolsServer.listeningSockets, 2); gExtraListener.close(); Assert.equal(DevToolsServer.listeningSockets, 1); Assert.ok(DevToolsServer.closeAllSocketListeners()); Assert.equal(DevToolsServer.listeningSockets, 0); // Make sure closing the listener twice does nothing. Assert.ok(!DevToolsServer.closeAllSocketListeners()); Assert.equal(DevToolsServer.listeningSockets, 0); info("Connecting to a server socket at " + new Date().toTimeString()); try { await DevToolsClient.socketConnect({ host: "127.0.0.1", port: gPort, }); } catch (e) { if ( e.result == Cr.NS_ERROR_CONNECTION_REFUSED || e.result == Cr.NS_ERROR_NET_TIMEOUT ) { // The connection should be refused here, but on slow or overloaded // machines it may just time out. Assert.ok(true); return; } throw e; } // Shouldn't reach this, should never connect. Assert.ok(false); } function test_pipe_conn() { const transport = DevToolsServer.connectPipe(); transport.hooks = { onPacket(packet) { Assert.equal(packet.from, "root"); transport.close(); }, onTransportClosed(status) { run_next_test(); }, }; transport.ready(); }