Fix tests

This commit is contained in:
lmb 2014-10-20 09:44:09 +01:00
parent 9b9c6f168a
commit d1a24d5711
5 changed files with 140 additions and 201 deletions

View File

@ -1,21 +1,15 @@
var express = require('express'); var express = require('express');
var mixin = require('utils-merge');
var proto = require('./server'); var proto = require('./server');
var util = require('./util'); var util = require('./util');
var http = require('http'); var http = require('http');
var https = require('https'); var https = require('https');
function ExpressPeerServer(server, options) { function ExpressPeerServer(server, options) {
if (!server) {
throw new Error('Server is not passed to constructor - '+
'can\'t start PeerServer');
}
var app = express(); var app = express();
mixin(app, proto); util.extend(app, proto);
options = app.options = mixin({ options = app._options = util.extend({
debug: false, debug: false,
timeout: 5000, timeout: 5000,
key: 'peerjs', key: 'peerjs',
@ -34,6 +28,11 @@ function ExpressPeerServer(server, options) {
app._ips = {}; app._ips = {};
app.on('mount', function() { app.on('mount', function() {
if (!server) {
throw new Error('Server is not passed to constructor - '+
'can\'t start PeerServer');
}
// Initialize HTTP routes. This is only used for the first few milliseconds // Initialize HTTP routes. This is only used for the first few milliseconds
// before a socket is opened for a Peer. // before a socket is opened for a Peer.
app._initializeHTTP(); app._initializeHTTP();
@ -47,11 +46,11 @@ function ExpressPeerServer(server, options) {
function PeerServer(options, callback) { function PeerServer(options, callback) {
var app = express(); var app = express();
options = options || {};
var path = options.path || '/'; var path = options.path || '/';
var port = options.port; var port = options.port || 80;
delete options.path; delete options.path;
delete options.port;
if (path[0] !== '/') { if (path[0] !== '/') {
path = '/' + path; path = '/' + path;

View File

@ -74,7 +74,7 @@ app._configureWS = function(socket, key, id, token) {
// Cleanup after a socket closes. // Cleanup after a socket closes.
socket.on('close', function() { socket.on('close', function() {
util.log('Socket closed:', id); self._log('Socket closed:', id);
if (client.socket == socket) { if (client.socket == socket) {
self._removePeer(key, id); self._removePeer(key, id);
} }
@ -96,7 +96,7 @@ app._configureWS = function(socket, key, id, token) {
util.prettyError('Message unrecognized'); util.prettyError('Message unrecognized');
} }
} catch(e) { } catch(e) {
util.log('Invalid message', data); self._log('Invalid message', data);
throw e; throw e;
} }
}); });
@ -107,11 +107,11 @@ app._configureWS = function(socket, key, id, token) {
}; };
app._checkAllowsDiscovery = function(key, cb) { app._checkAllowsDiscovery = function(key, cb) {
cb(this.options.allow_discovery); cb(this._options.allow_discovery);
}; };
app._checkKey = function(key, ip, cb) { app._checkKey = function(key, ip, cb) {
if (key == this.options.key) { if (key == this._options.key) {
if (!this._clients[key]) { if (!this._clients[key]) {
this._clients[key] = {}; this._clients[key] = {};
} }
@ -122,11 +122,11 @@ app._checkKey = function(key, ip, cb) {
this._ips[ip] = 0; this._ips[ip] = 0;
} }
// Check concurrent limit // Check concurrent limit
if (Object.keys(this._clients[key]).length >= this.options.concurrent_limit) { if (Object.keys(this._clients[key]).length >= this._options.concurrent_limit) {
cb('Server has reached its concurrent user limit'); cb('Server has reached its concurrent user limit');
return; return;
} }
if (this._ips[ip] >= this.options.ip_limit) { if (this._ips[ip] >= this._options.ip_limit) {
cb(ip + ' has reached its concurrent user limit'); cb(ip + ' has reached its concurrent user limit');
return; return;
} }
@ -339,7 +339,7 @@ app._handleTransmission = function(key, message) {
// User is connected! // User is connected!
if (destination) { if (destination) {
try { try {
util.log(type, 'from', src, 'to', dst); this._log(type, 'from', src, 'to', dst);
if (destination.socket) { if (destination.socket) {
destination.socket.send(data); destination.socket.send(data);
} else if (destination.res) { } else if (destination.res) {
@ -389,3 +389,9 @@ app._generateClientId = function(key) {
} }
return clientId; return clientId;
}; };
app._log = function() {
if (this._options.debug) {
console.log.apply(console, arguments);
}
};

View File

@ -1,4 +1,3 @@
var util = { var util = {
debug: false, debug: false,
inherits: function(ctor, superCtor) { inherits: function(ctor, superCtor) {
@ -27,15 +26,6 @@ var util = {
prettyError: function (msg) { prettyError: function (msg) {
console.log('ERROR PeerServer: ', msg); console.log('ERROR PeerServer: ', msg);
}, },
log: function() {
if (util.debug) {
var copy = [];
for (var i = 0; i < arguments.length; i += 1) {
copy[i] = arguments[i];
}
console.log.apply(console, copy);
}
},
allowCrossDomain: function(req, res, next) { allowCrossDomain: function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
@ -45,6 +35,4 @@ var util = {
} }
}; };
// if node
module.exports = util; module.exports = util;
// end node

View File

@ -16,7 +16,6 @@
"body-parser": "^1.9.0", "body-parser": "^1.9.0",
"express": "^4.9.8", "express": "^4.9.8",
"optimist": "~0.6.1", "optimist": "~0.6.1",
"utils-merge": "~1.0.0",
"ws": "~0.4.25" "ws": "~0.4.25"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,205 +1,152 @@
var PeerServer = require('../').PeerServer; var ExpressPeerServer = require('../').ExpressPeerServer;
var expect = require('expect.js'); var expect = require('expect.js');
var sinon = require('sinon'); var sinon = require('sinon');
describe('PeerServer', function() { describe('ExpressPeerServer', function() {
describe('#_initializeWSS', function() { describe('method', function() {
WebSocketServer = sinon.stub(); var p;
});
describe('#_configureWS', function() {
before(function() {
p = ExpressPeerServer(undefined, {port: 8000});
}); });
describe('#_checkKey', function() { describe('#_checkKey', function() {
var p; it('should reject keys that are not the default', function(done) {
before(function(done) { p._checkKey('bad key', null, function(response) {
PeerServer.prototype._initializeHTTP = sinon.stub(); expect(response).to.be('Invalid key provided');
p = PeerServer({ port: 8000 }, done); done();
p._checkKey('peerjs', 'myip', function() {});
}); });
});
after(function(done) { it('should accept valid key/ip pairs', function(done) {
p._server.close(done); p._checkKey('peerjs', 'myip', function(response) {
expect(response).to.be(null);
done();
}); });
});
it('should reject ips that are at their limit', function(done) {
it('should reject keys that are not the default', function(done) { p._options.ip_limit = 0;
p._checkKey('bad key', null, function(response) { p._checkKey('peerjs', 'myip', function(response) {
expect(response).to.be('Invalid key provided'); expect(response).to.be('myip has reached its concurrent user limit');
done(); done();
});
}); });
});
it('should accept valid key/ip pairs', function(done) { it('should reject when the server is at its limit', function(done) {
p._checkKey('peerjs', 'myip', function(response) { p._options.concurrent_limit = 0;
expect(response).to.be(null); p._checkKey('peerjs', 'myip', function(response) {
done(); expect(response).to.be('Server has reached its concurrent user limit');
}); done();
}); });
});
it('should reject ips that are at their limit', function(done) {
p.options.ip_limit = 0;
p._checkKey('peerjs', 'myip', function(response) {
expect(response).to.be('myip has reached its concurrent user limit');
done();
});
});
it('should reject when the server is at its limit', function(done) {
p.options.concurrent_limit = 0;
p._checkKey('peerjs', 'myip', function(response) {
expect(response).to.be('Server has reached its concurrent user limit');
done();
});
});
});
describe('#_initializeHTTP', function() {
});
describe('#_startStreaming', function() {
});
describe('#_pruneOutstanding', function() {
});
describe('#_processOutstanding', function() {
}); });
describe('#_removePeer', function() { describe('#_removePeer', function() {
var p; before(function() {
before(function(done) { var fake = {ip: '0.0.0.0'};
PeerServer.prototype._initializeHTTP = sinon.stub(); p._ips[fake.ip] = 1;
p = new PeerServer({ port: 8000 }, done); p._clients['peerjs'] = {};
p._clients['peerjs']['test'] = fake;
});
var fake = {ip: '0.0.0.0'}; it('should decrement the number of ips being used and remove the connection', function() {
p._ips[fake.ip] = 1; expect(p._ips['0.0.0.0']).to.be(1);
p._clients['peerjs'] = {}; p._removePeer('peerjs', 'test');
p._clients['peerjs']['test'] = fake; expect(p._ips['0.0.0.0']).to.be(0);
}); expect(p._clients['peerjs']['test']).to.be(undefined);
});
after(function(done) {
p._server.close(done);
});
it('should decrement the number of ips being used and remove the connection', function() {
expect(p._ips['0.0.0.0']).to.be(1);
p._removePeer('peerjs', 'test');
expect(p._ips['0.0.0.0']).to.be(0);
expect(p._clients['peerjs']['test']).to.be(undefined);
});
}); });
describe('#_handleTransmission', function() { describe('#_handleTransmission', function() {
var p; var KEY = 'peerjs';
var KEY = 'peerjs'; var ID = 'test';
var ID = 'test';
before(function(done) {
PeerServer.prototype._initializeHTTP = sinon.stub();
p = PeerServer({ port: 8000 }, done);
p._clients[KEY] = {};
});
after(function(done) { before(function() {
p._server.close(done); p._clients[KEY] = {};
}); });
it('should send to the socket when appropriate', function() { it('should send to the socket when appropriate', function() {
var send = sinon.spy(); var send = sinon.spy();
var write = sinon.spy(); var write = sinon.spy();
var message = {dst: ID}; var message = {dst: ID};
p._clients[KEY][ID] = { p._clients[KEY][ID] = {
socket: { socket: {
send: send send: send
}, },
res: { res: {
write: write write: write
} }
} }
p._handleTransmission(KEY, message); p._handleTransmission(KEY, message);
expect(send.calledWith(JSON.stringify(message))).to.be(true); expect(send.calledWith(JSON.stringify(message))).to.be(true);
expect(write.calledWith(JSON.stringify(message))).to.be(false); expect(write.calledWith(JSON.stringify(message))).to.be(false);
}); });
it('should write to the response with a newline when appropriate', function() { it('should write to the response with a newline when appropriate', function() {
var write = sinon.spy(); var write = sinon.spy();
var message = {dst: ID}; var message = {dst: ID};
p._clients[KEY][ID] = { p._clients[KEY][ID] = {
res: { res: {
write: write write: write
} }
} }
p._handleTransmission(KEY, message); p._handleTransmission(KEY, message);
expect(write.calledWith(JSON.stringify(message) + '\n')).to.be(true); expect(write.calledWith(JSON.stringify(message) + '\n')).to.be(true);
}); });
// no destination. // no destination.
it('should push to outstanding messages if the destination is not found', function() { it('should push to outstanding messages if the destination is not found', function() {
var message = {dst: ID}; var message = {dst: ID};
p._outstanding[KEY] = {}; p._outstanding[KEY] = {};
p._clients[KEY] = {}; p._clients[KEY] = {};
p._handleTransmission(KEY, message); p._handleTransmission(KEY, message);
expect(p._outstanding[KEY][ID][0]).to.be(message); expect(p._outstanding[KEY][ID][0]).to.be(message);
}); });
it('should not push to outstanding messages if the message is a LEAVE or EXPIRE', function() { it('should not push to outstanding messages if the message is a LEAVE or EXPIRE', function() {
var message = {dst: ID, type: 'LEAVE'}; var message = {dst: ID, type: 'LEAVE'};
p._outstanding[KEY] = {}; p._outstanding[KEY] = {};
p._clients[KEY] = {}; p._clients[KEY] = {};
p._handleTransmission(KEY, message); p._handleTransmission(KEY, message);
expect(p._outstanding[KEY][ID]).to.be(undefined); expect(p._outstanding[KEY][ID]).to.be(undefined);
message = {dst: ID, type: 'EXPIRE'}; message = {dst: ID, type: 'EXPIRE'};
p._handleTransmission(KEY, message); p._handleTransmission(KEY, message);
expect(p._outstanding[KEY][ID]).to.be(undefined); expect(p._outstanding[KEY][ID]).to.be(undefined);
}); });
it('should remove the peer if there is no dst in the message', function() { it('should remove the peer if there is no dst in the message', function() {
var message = {type: 'LEAVE'}; var message = {type: 'LEAVE'};
p._removePeer = sinon.spy(); p._removePeer = sinon.spy();
p._outstanding[KEY] = {}; p._outstanding[KEY] = {};
p._handleTransmission(KEY, message); p._handleTransmission(KEY, message);
expect(p._removePeer.calledWith(KEY, undefined)).to.be(true); expect(p._removePeer.calledWith(KEY, undefined)).to.be(true);
}); });
it('should remove the peer and send a LEAVE message if the socket appears to be closed', function() { it('should remove the peer and send a LEAVE message if the socket appears to be closed', function() {
var send = sinon.stub().throws(); var send = sinon.stub().throws();
var message = {dst: ID}; var message = {dst: ID};
var leaveMessage = {type: 'LEAVE', dst: undefined, src: ID}; var leaveMessage = {type: 'LEAVE', dst: undefined, src: ID};
var oldHandleTransmission = p._handleTransmission; var oldHandleTransmission = p._handleTransmission;
p._removePeer = function() { p._removePeer = function() {
// Hacks! // Hacks!
p._handleTransmission = sinon.spy(); p._handleTransmission = sinon.spy();
}; };
p._clients[KEY][ID] = { p._clients[KEY][ID] = {
socket: { socket: {
send: send send: send
} }
} }
p._handleTransmission(KEY, message); p._handleTransmission(KEY, message);
expect(p._handleTransmission.calledWith(KEY, leaveMessage)).to.be(true); expect(p._handleTransmission.calledWith(KEY, leaveMessage)).to.be(true);
}); });
}); });
describe('#_generateClientId', function() { describe('#_generateClientId', function() {
var p; it('should generate a 16-character ID', function() {
before(function(done) { expect(p._generateClientId('anykey').length).to.be(16);
p = new PeerServer({ port: 8000 }, done); });
});
after(function(done) {
p._server.close(done);
});
it('should generate a 16-character ID', function() {
expect(p._generateClientId('anykey').length).to.be.within(15, 16);
});
}); });
});
}); });