diff --git a/src/server/_real_time_server_test.js b/src/server/_real_time_server_test.js index 0df87fab8..57d405a45 100644 --- a/src/server/_real_time_server_test.js +++ b/src/server/_real_time_server_test.js @@ -35,22 +35,10 @@ httpServer.start(PORT, done); }); - afterEach(function(done) { - waitForConnectionCount(0, "afterEach() requires all sockets to be closed", function() { - httpServer.stop(done); - }); - }); - - it("counts the number of connections", function(done) { - assert.equal(realTimeServer.numberOfActiveConnections(), 0, "before opening connection"); - - var socket = createSocket(); - waitForConnectionCount(1, "after opening connection", function() { - assert.equal(realTimeServer.numberOfActiveConnections(), 1, "after opening connection"); - closeSocket(socket, function() { - waitForConnectionCount(0, "after closing connection", done); - }); - }); + afterEach(function(done) { + realTimeServer.disconnectAll(function () { + httpServer.stop(done); + }); }); it("broadcasts pointer events from one client to all others", function(done) { @@ -89,8 +77,8 @@ realTimeServer.handleClientEvent(clientEvent, EMITTER_ID); - function end() { - async.each([ receiver1, receiver2 ], closeSocket, done); + function end() { + setTimeout(done, 0); } }); @@ -111,18 +99,16 @@ client.on(ServerDrawEvent.EVENT_NAME, function(event) { replayedEvents.push(ServerDrawEvent.fromSerializableObject(event)); if (replayedEvents.length === 3) { - try { - // if we don't get the events, the test will time out - assert.deepEqual(replayedEvents, [ - event1.toServerEvent(), - event2.toServerEvent(), - event3.toServerEvent() - ]); - } - finally { - closeSocket(client, done); - } - } + + // if we don't get the events, the test will time out + assert.deepEqual(replayedEvents, [ + event1.toServerEvent(), + event2.toServerEvent(), + event3.toServerEvent() + ]); + + setTimeout(done, 10); + } }); }); @@ -144,28 +130,10 @@ next(); } }); - }, end); + }, done); emitter.emit(clientEvent.name(), clientEvent.toSerializableObject()); - - function end() { - async.each([emitter, receiver1, receiver2], closeSocket, done); - } - } - - function waitForConnectionCount(expectedConnections, message, callback) { - var TIMEOUT = 1000; // milliseconds - var RETRY_PERIOD = 10; // milliseconds - - var retryOptions = { times: TIMEOUT / RETRY_PERIOD, interval: RETRY_PERIOD }; - async.retry(retryOptions, function(next) { - if (realTimeServer.numberOfActiveConnections() === expectedConnections) return next(); - else return next("fail"); - }, function(err) { - if (err) return assert.equal(realTimeServer.numberOfActiveConnections(), expectedConnections, message); - else setTimeout(callback, 0); - }); - } + } function createSocket() { return io("http://localhost:" + PORT); diff --git a/src/server/_server_test.js b/src/server/_server_test.js index f9bb7c40f..16e2ab1d0 100644 --- a/src/server/_server_test.js +++ b/src/server/_server_test.js @@ -65,14 +65,10 @@ receiver.on(ServerPointerEvent.EVENT_NAME, function(data) { assert.deepEqual(data, clientEvent.toServerEvent(emitter.id).toSerializableObject()); - end(); + setTimeout(done, 10); }); emitter.emit(clientEvent.name(), clientEvent.toSerializableObject()); - - function end() { - async.each([ emitter, receiver ], closeSocket, done); - } }); function createSocket() { diff --git a/src/server/real_time_server.js b/src/server/real_time_server.js index fb33068c8..a2be58777 100644 --- a/src/server/real_time_server.js +++ b/src/server/real_time_server.js @@ -3,6 +3,7 @@ "use strict"; var io = require('socket.io'); + var async = require("async"); var ClientPointerEvent = require("../shared/client_pointer_event.js"); var ClientRemovePointerEvent = require("../shared/client_remove_pointer_event.js"); var ClientDrawEvent = require("../shared/client_draw_event.js"); @@ -19,7 +20,7 @@ RealTimeServer.prototype.start = function(httpServer) { this._ioServer = io(httpServer); - trackSocketIoConnections(this._socketIoConnections, this._ioServer); + trackSocketIoConnections(this); handleSocketIoEvents(this, this._ioServer); }; @@ -30,15 +31,34 @@ RealTimeServer.prototype.numberOfActiveConnections = function() { return Object.keys(this._socketIoConnections).length; - }; + }; + + RealTimeServer.prototype.disconnectAll = function (callback) { + if (this._disconnectAllCallback) + throw "Only supporting one disconnectAll() call at a time."; + + if (this.numberOfActiveConnections() === 0) { + callback(); + } + else { + this._disconnectAllCallback = callback; + async.each(this._socketIoConnections, function (socket) { socket.disconnect(); }); + } + }; - function trackSocketIoConnections(connections, ioServer) { + function trackSocketIoConnections(self) { // Inspired by isaacs https://github.com/isaacs/server-destroy/commit/71f1a988e1b05c395e879b18b850713d1774fa92 - ioServer.on("connection", function(socket) { + self._ioServer.on("connection", function(socket) { var key = socket.id; - connections[key] = socket; - socket.on("disconnect", function() { - delete connections[key]; + self._socketIoConnections[key] = socket; + + socket.on("disconnect", function () { + delete self._socketIoConnections[key]; + + if (self._disconnectAllCallback && self.numberOfActiveConnections() === 0) { + self._disconnectAllCallback(); + self._disconnectAllCallback = null; + } }); }); } diff --git a/src/server/server.js b/src/server/server.js index d5dddca7e..cce35d8e3 100644 --- a/src/server/server.js +++ b/src/server/server.js @@ -13,14 +13,17 @@ this._httpServer = new HttpServer(contentDir, notFoundPageToServe); this._httpServer.start(portNumber, callback); - var realTimeServer = new RealTimeServer(); - realTimeServer.start(this._httpServer.getNodeServer()); + this._realTimeServer = new RealTimeServer(); + this._realTimeServer.start(this._httpServer.getNodeServer()); }; - Server.prototype.stop = function(callback) { - if (this._httpServer === undefined) return callback(new Error("stop() called before server started")); + Server.prototype.stop = function (callback) { + var self = this; + if (self._httpServer === undefined) return callback(new Error("stop() called before server started")); - this._httpServer.stop(callback); + self._realTimeServer.disconnectAll(function () { + self._httpServer.stop(callback); + }); }; }()); \ No newline at end of file