Live texturing

This commit is contained in:
maqu14
2016-03-18 10:14:02 +01:00
parent 65e5729118
commit 7fc83d1471
155 changed files with 18378 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver')
describe('context', function() {
it('should support setting max io threads', function(done) {
// 3.2 and above.
if (!semver.gte(zmq.version, '3.2.0')) {
done();
return console.warn('Test requires libzmq >= 3.2.0');
}
zmq.Context.setMaxThreads(3);
zmq.Context.getMaxThreads().should.equal(3);
zmq.Context.setMaxThreads(1);
done();
});
it('should support setting max number of sockets', function(done) {
// 3.2 and above.
if (!semver.gte(zmq.version, '3.2.0')) {
done();
return console.warn('Test requires libzmq >= 3.2.0');
}
var currMaxSockets = zmq.Context.getMaxSockets();
zmq.Context.setMaxSockets(256);
zmq.Context.getMaxSockets().should.equal(256);
zmq.Context.setMaxSockets(currMaxSockets);
done();
});
});
+132
View File
@@ -0,0 +1,132 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('exports', function(){
it('should export a valid version', function(){
semver.valid(zmq.version).should.be.ok;
});
it('should generate valid curve keypair', function(done) {
if (!semver.gte(zmq.version,'4.0.0') || require('os').platform() == 'win32'){
done();
return console.warn('Test requires libzmq >= 4 compiled with libsodium');
}
var curve = zmq.curveKeypair();
should.exist(curve);
should.exist(curve.public);
should.exist(curve.secret);
curve.public.length.should.equal(40);
curve.secret.length.should.equal(40);
done();
});
it('should export socket types and options', function(){
// All versions.
var constants = [
'PUB',
'SUB',
'REQ',
'XREQ',
'REP',
'XREP',
'DEALER',
'ROUTER',
'PUSH',
'PULL',
'PAIR',
'AFFINITY',
'IDENTITY',
'SUBSCRIBE',
'UNSUBSCRIBE',
'RCVTIMEO',
'SNDTIMEO',
'RATE',
'RECOVERY_IVL',
'SNDBUF',
'RCVBUF',
'RCVMORE',
'FD',
'EVENTS',
'TYPE',
'LINGER',
'RECONNECT_IVL',
'RECONNECT_IVL_MAX',
'BACKLOG',
'POLLIN',
'POLLOUT',
'POLLERR',
'SNDMORE'
];
// 2.x only.
if (semver.satisfies(zmq.version, '2.x')) {
constants.concat([
'HWM',
'SWAP',
'MCAST_LOOP',
'ZMQ_RECOVERY_IVL_MSEC',
'NOBLOCK'
]);
}
// 3.0 and above.
if (semver.gte(zmq.version, '3.0.0')) {
constants.concat([
'XPUB',
'XSUB',
'SNDHWM',
'RCVHWM',
'MAXMSGSIZE',
'ZMQ_MULTICAST_HOPS',
'TCP_KEEPALIVE',
'TCP_KEEPALIVE_CNT',
'TCP_KEEPALIVE_IDLE',
'TCP_KEEPALIVE_INTVL'
]);
}
// 3.2 and above.
if (semver.gte(zmq.version, '3.2.0')) {
constants.concat([
'IPV4ONLY',
'DELAY_ATTACH_ON_CONNECT',
'ROUTER_MANDATORY',
'XPUB_VERBOSE',
'TCP_KEEPALIVE',
'TCP_KEEPALIVE_IDLE',
'TCP_KEEPALIVE_CNT',
'TCP_KEEPALIVE_INTVL',
'TCP_ACCEPT_FILTER',
'LAST_ENDPOINT'
]);
}
// 3.3 and above.
if (semver.gte(zmq.version, '3.3.0')) {
constants.concat([
'ROUTER_RAW'
]);
}
constants.forEach(function(typeOrProp){
zmq['ZMQ_' + typeOrProp].should.be.a.Number;
});
});
it('should export states', function(){
['STATE_READY', 'STATE_BUSY', 'STATE_CLOSED'].forEach(function(state){
zmq[state].should.be.a.Number;
});
});
it('should export constructors', function(){
zmq.Context.should.be.a.Function;
zmq.Socket.should.be.a.Function;
});
it('should export methods', function(){
zmq.socket.should.be.a.Function;
});
});
+52
View File
@@ -0,0 +1,52 @@
var zmq = require('..')
, should = require('should');
it('should cooperate with gc', function(done){
var a = zmq.socket('dealer')
, b = zmq.socket('dealer');
/**
* We create 2 dealer sockets.
* One of them (`a`) is not referenced explicitly after the main loop
* finishes so it's a pretender for garbage collection.
* This test performs gc() explicitly and then tries to send a message
* to a dealer socket that could be destroyed and collected.
* If a message is delivered, than everything is ok. Otherwise the guard
* timeout will make the test fail.
*/
a.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('hello');
this.close();
b.close();
clearTimeout(timeout);
done();
});
var bound = false;
a.bind('tcp://127.0.0.1:5555', function(e){
if (e) {
clearInterval(interval);
done(e);
} else {
bound = true;
}
});
var interval = setInterval(function(){
gc();
if (bound) {
clearInterval(interval);
b.connect('tcp://127.0.0.1:5555');
b.send('hello');
}
}, 100);
// guard against hanging
var timeout = setTimeout(function(){
clearInterval(interval);
done(new Error('timeout of 5000ms exceeded (bound: ' + bound + ')'));
}, 15000);
});
+1
View File
@@ -0,0 +1 @@
--reporter spec
+31
View File
@@ -0,0 +1,31 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.events', function(){
it('should support events', function(done){
var rep = zmq.socket('rep')
, req = zmq.socket('req');
rep.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('hello');
rep.send('world');
});
rep.bind('inproc://stuff');
rep.on('bind', function(){
req.connect('inproc://stuff');
req.send('hello');
req.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('world');
req.close();
rep.close();
done();
});
});
});
});
+60
View File
@@ -0,0 +1,60 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket', function(){
var sock;
it('should alias socket', function(){
zmq.createSocket.should.equal(zmq.socket);
});
it('should include type and close', function(){
sock = zmq.socket('req');
sock.type.should.equal('req');
sock.close.should.be.a.Function;
});
it('should use socketopt', function(){
sock.getsockopt(zmq.ZMQ_BACKLOG).should.not.equal(75);
sock.setsockopt(zmq.ZMQ_BACKLOG, 75).should.equal(sock);
sock.getsockopt(zmq.ZMQ_BACKLOG).should.equal(75);
sock.setsockopt(zmq.ZMQ_BACKLOG, 100);
});
it('should use socketopt with sugar', function(){
sock.getsockopt('backlog').should.not.equal(75);
sock.setsockopt('backlog', 75).should.equal(sock);
sock.getsockopt('backlog').should.equal(75);
sock.backlog.should.be.a.Number;
sock.backlog.should.not.equal(50);
sock.backlog = 50;
sock.backlog.should.equal(50);
});
it('should close', function(){
sock.close();
});
it('should support options', function(){
sock = zmq.socket('req', { backlog: 30 });
sock.backlog.should.equal(30);
sock.close();
});
it('should throw a javascript error if it hits the system file descriptor limit', function() {
var i, socks = [], numSocks = 10000;
function hitlimit() {
for (i = 0; i < numSocks; i++) {
socks.push(zmq.socket('router'));
}
}
hitlimit.should['throw'];
for (i = 0; i < socks.length; i++) {
socks[i].close();
}
});
});
+141
View File
@@ -0,0 +1,141 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.messages', function(){
var push, pull;
beforeEach(function(){
push = zmq.socket('push');
pull = zmq.socket('pull');
});
it('should support messages', function(done){
var n = 0;
pull.on('message', function(msg){
msg = msg.toString();
switch (n++) {
case 0:
msg.should.equal('string');
break;
case 1:
msg.should.equal('15.99');
break;
case 2:
msg.should.equal('buffer');
push.close();
pull.close();
done();
break;
}
});
pull.bind('inproc://stuff_ssm', function(){
push.connect('inproc://stuff_ssm');
push.send('string');
push.send(15.99);
push.send(new Buffer('buffer'));
});
});
it('should support multipart messages', function(done){
pull.on('message', function(msg1, msg2, msg3){
msg1.toString().should.equal('string');
msg2.toString().should.equal('15.99');
msg3.toString().should.equal('buffer');
push.close();
pull.close();
done();
});
pull.bind('inproc://stuff_ssmm', function(){
push.connect('inproc://stuff_ssmm');
push.send(['string', 15.99, new Buffer('buffer')]);
});
});
it('should support sndmore', function(done){
pull.on('message', function(a, b, c, d, e){
a.toString().should.equal('tobi');
b.toString().should.equal('loki');
c.toString().should.equal('jane');
d.toString().should.equal('luna');
e.toString().should.equal('manny');
push.close();
pull.close();
done();
});
pull.bind('inproc://stuff_sss', function(){
push.connect('inproc://stuff_sss');
push.send(['tobi', 'loki'], zmq.ZMQ_SNDMORE);
push.send(['jane', 'luna'], zmq.ZMQ_SNDMORE);
push.send('manny');
});
});
it('should handle late connect', function(done){
var n = 0;
pull.on('message', function(msg){
msg = msg.toString();
switch (n++) {
case 0:
msg.should.equal('string');
break;
case 1:
msg.should.equal('15.99');
break;
case 2:
msg.should.equal('buffer');
push.close();
pull.close();
done();
break;
}
});
if (semver.satisfies(zmq.version, '>=3.x')) {
push.setsockopt(zmq.ZMQ_SNDHWM, 1);
pull.setsockopt(zmq.ZMQ_RCVHWM, 1);
} else if (semver.satisfies(zmq.version, '2.x')) {
push.setsockopt(zmq.ZMQ_HWM, 1);
pull.setsockopt(zmq.ZMQ_HWM, 1);
}
push.bind('tcp://127.0.0.1:12345', function () {
push.send('string');
push.send(15.99);
push.send(new Buffer('buffer'));
pull.connect('tcp://127.0.0.1:12345');
});
});
it('should call send() callbacks', function(done){
var received = 0;
var callbacks = 0;
function cb() {
callbacks += 1;
}
pull.on('message', function () {
received += 1;
if (received === 4) {
callbacks.should.equal(received);
done();
}
});
pull.bind('inproc://stuff_ssmm', function(){
push.connect('inproc://stuff_ssmm');
push.send('hello', null, cb);
push.send('hello', null, cb);
push.send('hello', null, cb);
push.send(['hello', 'world'], null, cb);
});
});
});
+104
View File
@@ -0,0 +1,104 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.monitor', function() {
if (!zmq.ZMQ_CAN_MONITOR) {
console.log("monitoring not enabled skipping test");
return;
}
it('should be able to monitor the socket', function(done) {
var rep = zmq.socket('rep')
, req = zmq.socket('req')
, events = [];
rep.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('hello');
rep.send('world');
});
var testedEvents = ['listen', 'accept', 'disconnect', 'close'];
testedEvents.forEach(function(e) {
rep.on(e, function(event_value, event_endpoint_addr) {
// Test the endpoint addr arg
event_endpoint_addr.toString().should.equal('tcp://127.0.0.1:5423');
// If this is a disconnect event we can now close the rep socket
if (e === 'disconnect') {
rep.close();
}
testedEvents.pop();
if (testedEvents.length === 0) {
rep.unmonitor();
done();
}
});
});
// enable monitoring for this socket
rep.monitor();
rep.bind('tcp://127.0.0.1:5423');
rep.on('bind', function(){
req.connect('tcp://127.0.0.1:5423');
req.send('hello');
req.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('world');
req.close();
});
});
});
it('should use default interval and numOfEvents', function(done) {
var req = zmq.socket('req');
req.setsockopt(zmq.ZMQ_RECONNECT_IVL, 5); // We want a quick connect retry from zmq
// We will try to connect to a non-existing server, zmq will issue events: "connect_retry", "close", "connect_retry"
// The connect_retry will be issued immediately after the close event, so we will measure the time between the close
// event and connect_retry event, those should >= 10 (this will tell us that we are reading 1 event at a time from
// the monitor socket).
var closeTime;
req.on('close', function() {
closeTime = Date.now();
});
req.on('connect_retry', function() {
var diff = Date.now() - closeTime;
req.unmonitor();
req.close();
diff.should.be.within(10, 20);
done();
});
req.monitor();
req.connect('tcp://127.0.0.1:5423');
});
it('should read multiple events on monitor interval', function(done) {
var req = zmq.socket('req');
req.setsockopt(zmq.ZMQ_RECONNECT_IVL, 5);
var closeTime;
req.on('close', function() {
closeTime = Date.now();
});
req.on('connect_retry', function() {
var diff = Date.now() - closeTime;
req.unmonitor();
req.close();
diff.should.be.within(0, 5);
done();
});
// This should read all available messages from the queue, and we expect that "close" and "connect_retry" will be
// read on the same interval (for further details see the comment in the previous test)
req.monitor(10, 0);
req.connect('tcp://127.0.0.1:5423');
});
});
+46
View File
@@ -0,0 +1,46 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.pair', function(){
it('should support pair-pair', function (done){
var pairB = zmq.socket('pair')
, pairC = zmq.socket('pair');
var n = 0;
pairB.on('message', function (msg){
msg.should.be.an.instanceof(Buffer);
switch (n++) {
case 0:
msg.toString().should.equal('foo');
break;
case 1:
msg.toString().should.equal('bar');
break;
case 2:
msg.toString().should.equal('baz');
pairB.close();
pairC.close();
done();
break;
}
});
pairC.on('message', function (msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('barnacle');
})
var addr = "inproc://stuff";
pairB.bind(addr, function(){
pairC.connect(addr);
pairB.send('barnacle');
pairC.send('foo');
pairC.send('bar');
pairC.send('baz');
});
});
});
+92
View File
@@ -0,0 +1,92 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.pub-sub', function(){
var pub, sub;
beforeEach(function() {
pub = zmq.socket('pub');
sub = zmq.socket('sub');
});
it('should support pub-sub', function(done){
var n = 0;
sub.subscribe('');
sub.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
switch (n++) {
case 0:
msg.toString().should.equal('foo');
break;
case 1:
msg.toString().should.equal('bar');
break;
case 2:
msg.toString().should.equal('baz');
sub.close();
pub.close();
done();
break;
}
});
var addr = "inproc://stuff_ssps";
sub.bind(addr, function(){
pub.connect(addr);
// The connect is asynchronous, and messages published to a non-
// connected socket are silently dropped. That means that there is
// a race between connecting and sending the first message which
// causes this test to hang, especially when running on Linux. Even an
// inproc:// socket seems to be asynchronous. So instead of
// sending straight away, we wait 100ms for the connection to be
// established before we start the send. This fixes the observed
// hang.
setTimeout(function() {
pub.send('foo');
pub.send('bar');
pub.send('baz');
}, 100.0);
});
});
it('should support pub-sub filter', function(done){
var n = 0;
sub.subscribe('js');
sub.subscribe('luna');
sub.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
switch (n++) {
case 0:
msg.toString().should.equal('js is cool');
break;
case 1:
msg.toString().should.equal('luna is cool too');
sub.close();
pub.close();
done();
break;
}
});
sub.bind('inproc://stuff_sspsf', function(){
pub.connect('inproc://stuff_sspsf');
// See comments on pub-sub test.
setTimeout(function() {
pub.send('js is cool');
pub.send('ruby is meh');
pub.send('py is pretty cool');
pub.send('luna is cool too');
}, 100.0);
});
});
});
+152
View File
@@ -0,0 +1,152 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.push-pull', function(){
it('should support push-pull', function(done){
var push = zmq.socket('push')
, pull = zmq.socket('pull');
var n = 0;
pull.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
switch (n++) {
case 0:
msg.toString().should.equal('foo');
break;
case 1:
msg.toString().should.equal('bar');
break;
case 2:
msg.toString().should.equal('baz');
pull.close();
push.close();
done();
break;
}
});
var addr = "inproc://stuff";
pull.bind(addr, function(){
push.connect(addr);
push.send('foo');
push.send('bar');
push.send('baz');
});
});
it('should not emit messages after pause()', function(done){
var push = zmq.socket('push')
, pull = zmq.socket('pull');
var n = 0;
pull.on('message', function(msg){
if(n++ === 0) {
msg.toString().should.equal('foo');
}
else{
should.not.exist(msg);
}
});
var addr = "inproc://pause_stuff";
pull.bind(addr, function(){
push.connect(addr);
push.send('foo');
pull.pause()
push.send('bar');
push.send('baz');
});
setTimeout(function (){
pull.close();
push.close();
done();
}, 100);
});
it('should be able to read messages after pause()', function(done){
var push = zmq.socket('push')
, pull = zmq.socket('pull');
var addr = "inproc://pause_stuff";
var messages = ['bar', 'foo'];
pull.bind(addr, function(){
push.connect(addr);
pull.pause()
messages.forEach(function(message){
push.send(message);
});
messages.forEach(function(message){
pull.read().toString().should.eql(message);
});
});
setTimeout(function (){
pull.close();
push.close();
done();
}, 100);
});
it('should emit messages after resume()', function(done){
var push = zmq.socket('push')
, pull = zmq.socket('pull');
var n = 0;
function checkNoMessages(msg){
should.not.exist(msg);
}
function checkMessages(msg){
msg.should.be.an.instanceof(Buffer);
switch (n++) {
case 0:
msg.toString().should.equal('foo');
break;
case 1:
msg.toString().should.equal('bar');
break;
case 2:
msg.toString().should.equal('baz');
pull.close();
push.close();
done();
break;
}
}
pull.on('message', checkNoMessages)
var addr = "inproc://resume_stuff";
pull.bind(addr, function(){
push.connect(addr);
pull.pause()
push.send('foo');
push.send('bar');
push.send('baz');
setTimeout(function (){
pull.removeListener('message', checkNoMessages)
pull.on('message', checkMessages)
pull.resume()
}, 100)
});
});
});
+58
View File
@@ -0,0 +1,58 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.req-rep', function(){
it('should support req-rep', function(done){
var rep = zmq.socket('rep')
, req = zmq.socket('req');
rep.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('hello');
rep.send('world');
});
rep.bind('inproc://stuff', function(){
req.connect('inproc://stuff');
req.send('hello');
req.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('world');
rep.close();
req.close();
done();
});
});
});
it('should support multiple', function(done){
var n = 5;
for (var i = 0; i < n; i++) {
(function(n){
var rep = zmq.socket('rep')
, req = zmq.socket('req');
rep.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('hello');
rep.send('world');
});
rep.bind('inproc://' + n, function(){
req.connect('inproc://' + n);
req.send('hello');
req.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('world');
req.close();
rep.close();
if (!--n) done();
});
});
})(i);
}
});
});
+73
View File
@@ -0,0 +1,73 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.router', function(){
it('should handle the unroutable', function(done){
var complete = 0;
if (!semver.gte(zmq.version, '3.2.0')) {
done();
return console.warn('Test requires libzmq >= 3.2.0');
}
if (semver.eq(zmq.version, '3.2.1')) {
done();
return console.warn('ZMQ_ROUTER_MANDATORY is broken in libzmq = 3.2.1');
}
var envelope = '12384982398293';
var errMsg = 'No route to host';
if (require('os').platform() == 'win32') errMsg = 'Unknown error';
// should emit an error event on unroutable msgs if mandatory = 1 and error handler is set
(function(){
var sock = zmq.socket('router');
sock.on('error', function(err){
err.message.should.equal(errMsg);
sock.close();
if (++complete === 2) done();
});
sock.setsockopt(zmq.ZMQ_ROUTER_MANDATORY, 1);
sock.send([envelope, '']);
})();
// should throw an error on unroutable msgs if mandatory = 1 and no error handler is set
(function(){
var sock = zmq.socket('router');
sock.setsockopt(zmq.ZMQ_ROUTER_MANDATORY, 1);
(function(){
sock.send([envelope, '']);
}).should.throw(errMsg);
(function(){
sock.send([envelope, '']);
}).should.throw(errMsg);
(function(){
sock.send([envelope, '']);
}).should.throw(errMsg);
sock.close();
})();
// should silently ignore unroutable msgs if mandatory = 0
(function(){
var sock = zmq.socket('router');
(function(){
sock.send([envelope, '']);
sock.close();
}).should.not.throw(errMsg);
})();
if (++complete === 2) done();
});
});
+73
View File
@@ -0,0 +1,73 @@
var zmq = require('..')
, http = require('http')
, should = require('should')
, semver = require('semver');
describe('socket.stream', function(){
it('should support a streaming socket', function (done){
//socket stream type API after libzmq4+, target > 4.0.0
if (semver.gte(zmq.version, '4.0.0')) {
var stream = zmq.socket('stream');
stream.on('message', function (id,msg){
msg.should.be.an.instanceof(Buffer);
var raw_header = String(msg).split('\r\n');
var method = raw_header[0].split(' ')[0];
method.should.equal('GET');
//finding an HTTP GET method, prepare HTTP response for TCP socket
var httpProtocolString = 'HTTP/1.0 200 OK\r\n' //status code
+ 'Content-Type: text/html\r\n' //headers
+ '\r\n'
+ '<!DOCTYPE html>' //response body
+ '<head>' //make it xml, json, html or something else
+ '<meta charset="UTF-8">'
+ '</head>'
+ '<body>'
+'<p>derpin over protocols</p>'
+ '</body>'
+'</html>'
//zmq streaming prefixed by envelope's routing identifier
stream.send([id,httpProtocolString]);
});
var addr = '127.0.0.1:5513';
stream.bind('tcp://'+addr, function(){
//send non-peer request to zmq, like an http GET method with URI path
http.get('http://'+addr+'/aRandomRequestPath', function (httpMsg){
//msg should now be a node readable stream as the good lord intended
if (semver.gte(process.versions.node, '0.11.0')){
httpMsg.socket._readableState.reading.should.be.false
} else {
if(semver.gte(process.versions.node, '0.10.0')){
httpMsg.socket._readableState.reading.should.be.true
}
}
//conventional node streams emit data events to process zmq stream response
httpMsg.on('data',function (msg){
msg.should.be.an.instanceof(Buffer);
String(msg).should.equal('<!DOCTYPE html><head><meta charset="UTF-8"></head>'
+'<body>'
+'<p>derpin over protocols</p>'
+'</body>'
+'</html>');
done();
});
});
});
} else {
done();
return console.warn('stream socket type in libzmq v4+');
}
});
});
+53
View File
@@ -0,0 +1,53 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.unbind', function(){
it('should be able to unbind', function(done){
if (!zmq.ZMQ_CAN_UNBIND) {
done();
return;
}
var a = zmq.socket('dealer')
, b = zmq.socket('dealer')
, c = zmq.socket('dealer');
var message_count = 0;
a.bind('tcp://127.0.0.1:5420', function (err) {
if (err) throw err;
a.bind('tcp://127.0.0.1:5421', function (err) {
if (err) throw err;
b.connect('tcp://127.0.0.1:5420');
b.send('Hello from b.');
c.connect('tcp://127.0.0.1:5421');
c.send('Hello from c.');
});
});
a.on('unbind', function(addr) {
if (addr === 'tcp://127.0.0.1:5420') {
b.send('Error from b.');
c.send('Messsage from c.');
setTimeout(function () {
c.send('Final message from c.');
}, 100);
}
});
a.on('message', function(msg) {
message_count++;
if (msg.toString() === 'Hello from b.') {
a.unbind('tcp://127.0.0.1:5420');
} else if (msg.toString() === 'Final message from c.') {
message_count.should.equal(4);
a.close();
b.close();
c.close();
done();
} else if (msg.toString() === 'Error from b.') {
throw Error('b should have been unbound');
}
});
});
});
+88
View File
@@ -0,0 +1,88 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.xpub-xsub', function () {
it('should support pub-sub tracing and filtering', function (done) {
if (!semver.gte(zmq.version, '3.1.0')) {
done();
return console.warn('Test requires libzmq >= 3.1.0');
}
var n = 0;
var m = 0;
var pub = zmq.socket('pub');
var sub = zmq.socket('sub');
var xpub = zmq.socket('xpub');
var xsub = zmq.socket('xsub');
pub.bindSync('tcp://*:5556');
xsub.connect('tcp://127.0.0.1:5556');
xpub.bindSync('tcp://*:5555');
sub.connect('tcp://127.0.0.1:5555');
xsub.on('message', function (msg) {
xpub.send(msg); // Forward message using the xpub so subscribers can receive it
});
xpub.on('message', function (msg) {
msg.should.be.an.instanceof(Buffer);
var type = msg[0] === 0 ? 'unsubscribe' : 'subscribe';
var channel = msg.slice(1).toString();
switch (type) {
case 'subscribe':
switch (m++) {
case 0:
channel.should.equal('js');
break;
case 1:
channel.should.equal('luna');
break;
}
break;
case 'unsubscribe':
switch (m++) {
case 2:
channel.should.equal('luna');
sub.close();
pub.close();
xsub.close();
xpub.close();
done();
break;
}
break;
}
xsub.send(msg); // Forward message using the xsub so the publisher knows it has a subscriber
});
sub.on('message', function (msg) {
msg.should.be.an.instanceof(Buffer);
switch (n++) {
case 0:
msg.toString().should.equal('js is cool');
break;
case 1:
msg.toString().should.equal('luna is cool too');
break;
}
});
sub.subscribe('js');
sub.subscribe('luna');
setTimeout(function () {
pub.send('js is cool');
pub.send('ruby is meh');
pub.send('py is pretty cool');
pub.send('luna is cool too');
}, 100.0);
setTimeout(function () {
sub.unsubscribe('luna');
}, 300);
});
});
+132
View File
@@ -0,0 +1,132 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
describe('socket.zap', function(){
var zap = require('./zap')
, zapSocket, rep, req, count = 0;
beforeEach(function(){
count++;
zapSocket = zap.start(count);
rep = zmq.socket('rep');
req = zmq.socket('req');
});
afterEach(function(){
req.close();
rep.close();
zapSocket.close();
});
it('should support curve', function(done){
var port = 'tcp://127.0.0.1:12347';
if (!semver.gte(zmq.version, '4.0.0')) {
done();
return;
}
try {
rep.curve_server = 0;
} catch(e) {
console.log("libsodium seems to be missing; skipping curve test");
done();
return;
}
var serverPublicKey = new Buffer('7f188e5244b02bf497b86de417515cf4d4053ce4eb977aee91a55354655ec33a', 'hex')
, serverPrivateKey = new Buffer('1f5d3873472f95e11f4723d858aaf0919ab1fb402cb3097742c606e61dd0d7d8', 'hex')
, clientPublicKey = new Buffer('ea1cc8bd7c8af65497d43fc21dbec6560c5e7b61bcfdcbd2b0dfacf0b4c38d45', 'hex')
, clientPrivateKey = new Buffer('83f99afacfab052406e5f421612568034e85f4c8182a1c92671e83dca669d31d', 'hex');
rep.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('hello');
rep.send('world');
});
rep.zap_domain = "test";
rep.curve_server = 1;
rep.curve_secretkey = serverPrivateKey;
rep.mechanism.should.eql(2);
rep.bind(port, function(){
req.curve_serverkey = serverPublicKey;
req.curve_publickey = clientPublicKey;
req.curve_secretkey = clientPrivateKey;
req.mechanism.should.eql(2);
req.connect(port);
req.send('hello');
req.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('world');
done();
});
});
});
it('should supoort null', function(done){
var port = 'tcp://127.0.0.1:12345';
if (!semver.gte(zmq.version, '4.0.0')) {
done();
return;
}
rep.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('hello');
rep.send('world');
});
rep.zap_domain = "test";
rep.mechanism.should.eql(0);
rep.bind(port, function(){
req.mechanism.should.eql(0);
req.connect(port);
req.send('hello');
req.on('message', function(msg){
console.log('here')
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('world');
done();
});
});
});
it('should supoort plain', function(done){
var port = 'tcp://127.0.0.1:12346';
if (!semver.gte(zmq.version, '4.0.0')) {
done();
return;
}
rep.on('message', function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('hello');
rep.send('world');
});
rep.zap_domain = "test";
rep.plain_server = 1;
rep.mechanism.should.eql(1);
rep.bind(port, function(){
req.plain_username = "user";
req.plain_password = "pass";
req.mechanism.should.eql(1);
req.connect(port);
req.send('hello');
req.on('message', function(msg){
console.log('here')
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('world');
done();
});
});
});
});
+46
View File
@@ -0,0 +1,46 @@
// This is mainly for testing that the security mechanisms themselves are working
// not the ZAP protocol itself. As long as the request is valid, this will
// authenticate it.
var zmq = require('../');
module.exports.start = function(count) {
var zap = zmq.socket('router');
zap.on('message', function() {
var data = Array.prototype.slice.call(arguments);
if (!data || !data.length) throw new Error("Invalid ZAP request");
var returnPath = [],
frame = data.shift();
while (frame && (frame.length != 0)) {
returnPath.push(frame);
frame = data.shift();
}
returnPath.push(frame);
if (data.length < 6) throw new Error("Invalid ZAP request");
var zapReq = {
version: data.shift(),
requestId: data.shift(),
domain: new Buffer(data.shift()).toString('utf8'),
address: new Buffer(data.shift()).toString('utf8'),
identity: new Buffer(data.shift()).toString('utf8'),
mechanism: new Buffer(data.shift()).toString('utf8'),
credentials: data.slice(0)
};
zap.send(returnPath.concat([
zapReq.version,
zapReq.requestId,
new Buffer("200", "utf8"),
new Buffer("OK", "utf8"),
new Buffer(0),
new Buffer(0)
]));
});
zap.bindSync("inproc://zeromq.zap.01."+count);
return zap;
}
+10
View File
@@ -0,0 +1,10 @@
var zmq = require('..')
, should = require('should');
describe('proxy', function() {
it('should be a function off the module namespace', function (done) {
zmq.proxy.should.be.a.Function;
done();
});
});
+95
View File
@@ -0,0 +1,95 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
var addr = 'tcp://127.0.0.1'
, frontendAddr = addr+':5501'
, backendAddr = addr+':5502'
, captureAddr = addr+':5503';
describe('proxy.push-pull', function() {
it('should proxy push-pull connected to pull-push',function (done) {
var frontend = zmq.socket('pull');
var backend = zmq.socket('push');
var pull = zmq.socket('pull');
var push = zmq.socket('push');
frontend.bindSync(frontendAddr);
backend.bindSync(backendAddr);
push.connect(frontendAddr);
pull.connect(backendAddr);
pull.on('message',function (msg) {
frontend.close();
backend.close();
push.close();
pull.close();
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('foo');
done();
});
setTimeout(function() {
push.send('foo');
}, 100.0);
zmq.proxy(frontend,backend);
});
it('should proxy pull-push connected to push-pull with capture',function (done) {
var frontend = zmq.socket('push');
var backend = zmq.socket('pull');
var capture = zmq.socket('pub');
var capSub = zmq.socket('sub');
var pull = zmq.socket('pull');
var push = zmq.socket('push');
frontend.bindSync(frontendAddr);
backend.bindSync(backendAddr);
capture.bindSync(captureAddr);
pull.connect(frontendAddr);
push.connect(backendAddr);
capSub.connect(captureAddr);
pull.on('message',function (msg) {
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('foo');
console.log(msg.toString());
});
capSub.subscribe('');
capSub.on('message',function (msg) {
capture.close();
capSub.close();
setTimeout(function() {
frontend.close();
backend.close();
push.close();
pull.close();
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('foo');
done();
},100.0);
});
setTimeout(function() {
push.send('foo');
}, 100.0);
zmq.proxy(frontend,backend,capture);
});
});
+97
View File
@@ -0,0 +1,97 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
var addr = 'tcp://127.0.0.1'
, frontendAddr = addr+':5504'
, backendAddr = addr+':5505'
, captureAddr = addr+':5506';
describe('proxy.router-dealer', function() {
it('should proxy req-rep connected over router-dealer', function (done){
var frontend = zmq.socket('router');
var backend = zmq.socket('dealer');
var rep = zmq.socket('rep');
var req = zmq.socket('req');
frontend.bindSync(frontendAddr);
backend.bindSync(backendAddr);
req.connect(frontendAddr);
rep.connect(backendAddr);
req.on('message',function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('foo bar');
frontend.close();
backend.close();
req.close();
rep.close();
done();
});
rep.on('message', function (msg) {
rep.send(msg+' bar');
});
setTimeout(function() {
req.send('foo');
}, 100.0);
zmq.proxy(frontend,backend);
});
it('should proxy rep-req connections with capture', function (done){
var frontend = zmq.socket('router');
var backend = zmq.socket('dealer');
var rep = zmq.socket('rep');
var req = zmq.socket('req');
var capture = zmq.socket('pub');
var capSub = zmq.socket('sub');
frontend.bindSync(frontendAddr);
backend.bindSync(backendAddr);
capture.bindSync(captureAddr);
req.connect(frontendAddr);
rep.connect(backendAddr);
capSub.connect(captureAddr);
capSub.subscribe('');
req.on('message',function (msg) {
req.close();
rep.close();
console.log(msg.toString());
});
rep.on('message', function (msg) {
rep.send(msg+' bar');
});
capSub.on('message',function (msg) {
backend.close();
frontend.close();
capture.close();
capSub.close();
setTimeout(function() {
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('foo bar');
done();
},100.0)
});
setTimeout(function() {
req.send('foo');
},200.0)
zmq.proxy(frontend,backend,capture);
});
});
+155
View File
@@ -0,0 +1,155 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
var addr = 'tcp://127.0.0.1'
, frontendAddr = addr+':5507'
, backendAddr = addr+':5508'
, captureAddr = addr+':5509';
var version = semver.gte(zmq.version, '3.1.0');
describe('proxy.xpub-xsub', function() {
it('should proxy pub-sub connected to xpub-xsub', function (done) {
if (!version) {
done();
return console.warn('Test requires libzmq >= 3.1.0');
}
var frontend = zmq.socket('xpub');
var backend = zmq.socket('xsub');
var sub = zmq.socket('sub');
var pub = zmq.socket('pub');
sub.subscribe('');
sub.on('message',function (msg) {
frontend.close();
backend.close();
sub.close();
pub.close();
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('foo');
done();
});
frontend.bind(frontendAddr,function() {
backend.bind(backendAddr,function() {
sub.connect(frontendAddr);
pub.connect(backendAddr);
setTimeout(function() {
pub.send('foo');
}, 200.0);
zmq.proxy(frontend,backend);
});
});
});
it('should proxy connections with capture', function (done) {
if (!version) {
done();
return console.warn('Test requires libzmq >= 3.1.0');
}
var frontend = zmq.socket('xpub');
var backend = zmq.socket('xsub');
var capture = zmq.socket('pub');
var capSub = zmq.socket('sub');
var sub = zmq.socket('sub');
var pub = zmq.socket('pub');
sub.subscribe('');
sub.on('message', function (msg) {
sub.close();
pub.close();
backend.close();
frontend.close();
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('foo');
console.log(msg.toString());
});
capSub.subscribe('');
capSub.on('message',function (msg) {
capture.close();
capSub.close();
setTimeout(function(){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('foo');
done();
},100.0);
});
capture.bind(captureAddr,function() {
frontend.bind(frontendAddr,function() {
backend.bind(backendAddr,function() {
pub.connect(backendAddr);
sub.connect(frontendAddr);
capSub.connect(captureAddr);
setTimeout(function () {
pub.send('foo');
}, 200.0);
zmq.proxy(frontend,backend,capture);
});
});
});
});
it('should throw an error if the order is wrong', function (done) {
if (!version) {
done();
return console.warn('Test requires libzmq >= 3.1.0');
}
var frontend = zmq.socket('xpub');
var backend = zmq.socket('xsub');
var sub = zmq.socket('sub');
var pub = zmq.socket('pub');
frontend.bindSync(frontendAddr);
backend.bindSync(backendAddr);
sub.connect(frontendAddr);
pub.connect(backendAddr);
try{
zmq.proxy(backend,frontend);
} catch(e){
e.message.should.equal('wrong socket order to proxy');
} finally{
frontend.close();
backend.close();
pub.close();
sub.close();
//allow time for TCP sockets to close
setTimeout(function(){
done();
},200)
}
})
});
+52
View File
@@ -0,0 +1,52 @@
var zmq = require('..')
, should = require('should')
, semver = require('semver');
var addr = 'tcp://127.0.0.1'
, frontendAddr = addr+':5510'
, backendAddr = addr+':5511'
, captureAddr = addr+':5512';
//since its for libzmq2, we target versions < 3.0.0
var version = semver.lte(zmq.version, '3.0.0');
describe('proxy.xrep-xreq', function() {
it('should proxy req-rep connected to xrep-xreq', function (done) {
if (!version) {
done();
return console.warn('Test requires libzmq v2');
}
var frontend = zmq.socket('xrep');
var backend = zmq.socket('xreq');
var req = zmq.socket('req');
var rep = zmq.socket('rep');
frontend.bindSync(frontendAddr);
backend.bindSync(backendAddr);
req.connect(frontendAddr);
rep.connect(backendAddr);
req.on('message',function(msg){
msg.should.be.an.instanceof(Buffer);
msg.toString().should.equal('foo bar');
frontend.close();
backend.close();
req.close();
rep.close();
done();
});
rep.on('message', function (msg) {
rep.send(msg+' bar');
});
setTimeout(function() {
req.send('foo');
}, 100.0);
zmq.proxy(frontend,backend);
});
});