msgflo
Version:
Polyglot FBP runtime based on message queues
264 lines (214 loc) • 9.32 kB
text/coffeescript
chai = require 'chai' unless chai
path = require 'path'
async = require 'async'
Coordinator = require('../src/coordinator').Coordinator
transport = require '../src/transport'
common = require '../src/common'
participants = require './fixtures/participants'
# Note: most require running an external broker service
transports =
'direct': 'direct://broker2'
'MQTT': 'mqtt://localhost'
'AMQP': 'amqp://localhost'
connectAll = (clients, callback) ->
connect = (c, cb) ->
c.connect cb
async.map clients, connect, callback
zip = () ->
lengthArray = (arr.length for arr in arguments)
length = Math.min(lengthArray...)
for i in [0...length]
arr[i] for arr in arguments
#
createConnectClients = (address, names, callback) ->
createConnect = (name, cb) ->
client = transport.getClient address
client.connect (err) ->
cb err, client
async.map names, createConnect, (err, clients) ->
return callback err if err
ret = {}
for nc in zip names, clients
ret[nc[0]] = nc[1]
return callback null, ret
createBindQueues = (broker, queueMapping, callback) ->
createBindQueue = (det, cb) ->
[client, type, srcQ, tgtQ] = det
createQ = if type == 'outqueue' then srcQ else tgtQ
client.createQueue type, createQ, (err) ->
return cb err if err
broker.bindQueue srcQ, tgtQ, cb
async.map queueMapping, createBindQueue, callback
sendPackets = (packets, callback) ->
send = (p, cb) ->
[client, queue, data] = p
client.sendToQueue queue, data, cb
async.map packets, send, callback
subscribeData = (handlers, callback) ->
sub = (h, cb) ->
[client, queue, handler] = h
ackHandler = (msg) ->
client.ackMessage msg
return handler msg
client.subscribeToQueue queue, ackHandler, cb
async.map handlers, sub, callback
describe 'Transport', ->
Object.keys(transports).forEach (type) =>
address = transports[type]
broker = null
describe "#{type}", () ->
beforeEach (done) ->
broker = transport.getBroker address
broker.connect (err) ->
err = null if not err?
chai.expect(err).to.be.a 'null'
done()
afterEach (done) ->
broker.disconnect () ->
broker = null
done()
describe 'starting client', ->
it 'should not error', (done) ->
clientA = transport.getClient address
clientA.connect (err) ->
done err
describe 'inqueue==outqueue without binding', ->
it 'sending should be received on other end', (done) ->
sender = transport.getClient address
receiver = transport.getClient address
payload = { foo: 'bar91' }
sharedQueue = 'myqueue33'
onReceive = (msg) ->
chai.expect(msg).to.include.keys 'data'
chai.expect(msg.data).to.eql payload
done()
connectAll [sender, receiver], (err) ->
receiver.createQueue 'inqueue', sharedQueue, (err) ->
chai.expect(err).to.be.a 'null'
sender.createQueue 'outqueue', sharedQueue, (err) ->
chai.expect(err).to.be.a 'null'
receiver.subscribeToQueue sharedQueue, onReceive, (err) ->
chai.expect(err).to.be.a 'null'
sender.sendToQueue sharedQueue, payload, (err) ->
chai.expect(err).to.be.a 'null'
describe 'inqueue==outqueue with binding', ->
it 'sending should be received on other end', (done) ->
sender = transport.getClient address
receiver = transport.getClient address
payload = { foo: 'bar92' }
sharedQueue = 'myqueue35'
onReceive = (msg) ->
chai.expect(msg).to.include.keys 'data'
chai.expect(msg.data).to.eql payload
done()
connectAll [sender, receiver], (err) ->
receiver.createQueue 'inqueue', sharedQueue, (err) ->
chai.expect(err).to.be.a 'null'
sender.createQueue 'outqueue', sharedQueue, (err) ->
chai.expect(err).to.be.a 'null'
broker.bindQueue sharedQueue, sharedQueue, (err) ->
chai.expect(err).to.be.a 'null'
receiver.subscribeToQueue sharedQueue, onReceive, (err) ->
chai.expect(err).to.be.a 'null'
sender.sendToQueue sharedQueue, payload, (err) ->
chai.expect(err).to.be.a 'null'
describe 'outqueue bound to inqueue', ->
it 'sending to inqueue, show up on outqueue', (done) ->
sender = transport.getClient address
receiver = transport.getClient address
payload = { foo: 'bar99' }
inQueue = 'inqueue232'
outQueue = 'outqueue353'
onReceive = (msg) ->
receiver.ackMessage msg
chai.expect(msg).to.include.keys 'data'
chai.expect(msg.data).to.eql payload
done()
connectAll [sender, receiver], (err) ->
receiver.createQueue 'inqueue', inQueue, (err) ->
chai.expect(err).to.be.a 'null'
sender.createQueue 'outqueue', outQueue, (err) ->
chai.expect(err).to.be.a 'null'
broker.bindQueue outQueue, inQueue, (err) ->
chai.expect(err).to.be.a 'null'
receiver.subscribeToQueue inQueue, onReceive, (err) ->
chai.expect(err).to.be.a 'null'
sender.sendToQueue outQueue, payload, (err) ->
chai.expect(err).to.be.a 'null'
describe 'multiple outqueues bound to one inqueue', ->
it 'all sent on outqueues shows up on inqueue', (done) ->
3000
senders = [ 'sendA', 'sendB', 'sendC' ]
clientNames = ['receive']
clientNames.push.apply clientNames, senders
createConnectClients address, clientNames, (err, clients) ->
chai.expect(err).to.be.a 'null'
expect = [ {name:'sendA'}, {name:'sendB'}, {name:'sendC'} ]
received = []
onReceive = (msg) ->
clients.receive.ackMessage msg
chai.expect(msg).to.include.keys 'data'
received.push msg.data
if received.length == expect.length
received.sort (a,b) ->
return -1 if a.name < b.name
return 1 if a.name > b.name
return 0
chai.expect(received).to.eql expect
done()
inQueue = 'inqueue27'
clients.receive.createQueue 'inqueue', inQueue, (err) ->
chai.expect(err).to.not.exist
clients.receive.subscribeToQueue inQueue, onReceive, (err) ->
chai.expect(err).to.not.exist
# Bind all outqueues to same inqueue
queueMapping = []
for name in senders
queueMapping.push [ clients[name], 'outqueue', name, inQueue ]
createBindQueues broker, queueMapping, (err) ->
chai.expect(err).to.not.exist
packets = []
for name in senders
packets.push [ clients[name], name, { name: name } ]
sendPackets packets, (err) ->
chai.expect(err).to.not.exist
describe 'multiple inqueues bound to one outqueue', ->
it 'data sent on outqueue shows up on all inqueues', (done) ->
3000
senders = [ 'sender' ]
receivers = ['r1', 'r2', 'r3']
clientNames = common.clone receivers
clientNames.push.apply clientNames, senders
createConnectClients address, clientNames, (err, clients) ->
chai.expect(err).to.not.exist
expect = [ {q:'r1',d:'ident'}, {q:'r2',d:'ident'}, {q:'r3',d:'ident'} ]
received = []
checkExpected = (q, msg) ->
received.push { q: q, d: msg.data.data }
if received.length == expect.length
received.sort (a,b) ->
return -1 if a.q < b.q
return 1 if a.q > b.q
return 0
chai.expect(received).to.eql expect
done()
onReceives =
r1: (msg) -> checkExpected 'r1', msg
r2: (msg) -> checkExpected 'r2', msg
r3: (msg) -> checkExpected 'r3', msg
outQueue2 = 'outqueue39'
clients.sender.createQueue 'outqueue', outQueue2, (err) ->
chai.expect(err).to.not.exist
# Bind same outqueue to all inqueues
queueMapping = []
for name in receivers
queueMapping.push [ clients[name], 'inqueue', outQueue2, name ]
createBindQueues broker, queueMapping, (err) ->
chai.expect(err).to.not.exist
handlers = []
for name in receivers
handlers.push [ clients[name], name, onReceives[name] ]
subscribeData handlers, (err) ->
chai.expect(err).to.not.exist
clients.sender.sendToQueue outQueue2, {data: 'ident'}, (err) ->
chai.expect(err).to.not.exist