mqtt-reqres-broker
Version:
mqtt request/response websocket broker
268 lines (212 loc) • 17.1 kB
HTML
<html lang="en"><head><title>brokerSpec</title></head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"><meta name="groc-relative-root" content=""><meta name="groc-document-path" content="brokerSpec"><meta name="groc-project-path" content="test/brokerSpec.js"><link rel="stylesheet" type="text/css" media="all" href="assets/style.css"><script type="text/javascript" src="assets/behavior.js"></script><body><div id="meta"><div class="file-path">test/brokerSpec.js</div></div><div id="document"><div class="segment"><div class="comments "><div class="wrapper"><h2 id="brokerspec">brokerSpec</h2>
<p>usage: $ DEBUG=brokerSpec mocha</p></div></div><div class="code"><div class="wrapper"><span class="hljs-keyword">const</span> debug = <span class="hljs-built_in">require</span>(<span class="hljs-string">'debug'</span>)(<span class="hljs-string">'mqtt-reqres-broker'</span>);
<span class="hljs-keyword">const</span> assert = <span class="hljs-built_in">require</span>(<span class="hljs-string">'assert'</span>);
<span class="hljs-keyword">const</span> MqttReqResBroker = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../lib/mqtt-reqres-broker.js'</span>);
<span class="hljs-keyword">const</span> mqtt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mqtt'</span>);
<span class="hljs-keyword">const</span> serverOptions = {
hostname: <span class="hljs-string">'localhost'</span>,
port: <span class="hljs-number">9999</span>
};
<span class="hljs-keyword">const</span> wsBroker = <span class="hljs-keyword">new</span> MqttReqResBroker();
<span class="hljs-keyword">var</span> mqttClientA, mqttClientB;
<span class="hljs-keyword">const</span> clientAId = <span class="hljs-string">'client-a'</span>,
clientBId = <span class="hljs-string">'client-b'</span>;
<span class="hljs-keyword">const</span> clientAChannelId = <span class="hljs-string">'client-a-channel-id'</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pcatch</span> (<span class="hljs-params">reason</span>) </span>{
debug(reason);
assert(!reason, reason);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">startServer</span> (<span class="hljs-params">callback</span>) </span>{
debug(<span class="hljs-string">'startServer()'</span>);
wsBroker.initialize(serverOptions, err => {
<span class="hljs-keyword">if</span> (err) {
<span class="hljs-built_in">console</span>.error(err.stack);
callback(err);
}
<span class="hljs-keyword">else</span> {
wsBroker.start(<span class="hljs-literal">null</span>, err => {
<span class="hljs-keyword">if</span> (err) {
<span class="hljs-built_in">console</span>.error(err.stack);
}
<span class="hljs-keyword">else</span> {
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`broker running at http://<span class="hljs-subst">${wsBroker.hostname}</span>:<span class="hljs-subst">${wsBroker.port}</span>/`</span>);
}
callback(err);
});
}
});
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">connectClient</span> (<span class="hljs-params">clientId</span>) </span>{
<span class="hljs-keyword">return</span> mqtt.connect({
protocol: <span class="hljs-string">'ws'</span>,
host: serverOptions.hostname,
port: serverOptions.port,
clientId: clientId || <span class="hljs-built_in">Math</span>.random().toString(<span class="hljs-number">36</span>).substr(<span class="hljs-number">2</span>, <span class="hljs-number">23</span>)
});
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">onClientConnect</span> (<span class="hljs-params">brokerClient</span>) </span>{
assert.strictEqual(brokerClient.clientId, onClientConnect.mqttClient.clientId);
setTimeout(() => {
assert(onClientConnect.mqttClient.connected, <span class="hljs-string">'mqtt client should be connected'</span>);
onClientConnect.callbackFn();
}, <span class="hljs-number">100</span>);
}
onClientConnect.configure = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">mqttClient, callbackFn</span>) </span>{
onClientConnect.mqttClient = mqttClient;
onClientConnect.callbackFn = callbackFn;
};
describe(<span class="hljs-string">'broker'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
before(done => {
startServer(err => {
wsBroker.mqtt.on(<span class="hljs-string">'client'</span>, onClientConnect);
done();
});
});
after(done => {
wsBroker.close(done);
});
describe(<span class="hljs-string">'connecting mqtt clients to broker via websockets'</span>, () => {
it(<span class="hljs-string">'should connect to mqtt client A'</span>, done => {
mqttClientA = connectClient(clientAId);
onClientConnect.configure(mqttClientA, done);
});
it(<span class="hljs-string">'should connect to mqtt client B'</span>, done => {
mqttClientB = connectClient(clientBId);
onClientConnect.configure(mqttClientB, done);
});
});
describe(<span class="hljs-string">'client subscriptions on topic "connect/&lt;device-id&gt;/+"'</span>, () => {
it(<span class="hljs-string">'should client A subscribe on topic "connect/'</span> + clientAId + <span class="hljs-string">'/+"'</span>, done => {
mqttClientA.subscribe(
<span class="hljs-string">`connect/<span class="hljs-subst">${clientAId}</span>/+`</span>,
{qos: <span class="hljs-number">0</span>},
<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, granted</span>) </span>{
assert(!err);
assert.strictEqual(granted[<span class="hljs-number">0</span>].qos, <span class="hljs-number">0</span>);
done();
}
);
});
it(<span class="hljs-string">'should client B subscribe on topic "connect/'</span> + clientBId + <span class="hljs-string">'/+"'</span>, done => {
mqttClientA.subscribe(
<span class="hljs-string">`connect/<span class="hljs-subst">${clientBId}</span>/+`</span>,
{qos: <span class="hljs-number">0</span>},
<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, granted</span>) </span>{
assert(!err);
assert.strictEqual(granted[<span class="hljs-number">0</span>].qos, <span class="hljs-number">0</span>);
done();
}
);
});
it(<span class="hljs-string">'should refuse to subscribe -t connect on invalid topics'</span>, done => {
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">promiseTest</span> (<span class="hljs-params">topic</span>) </span>{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">resolve</span>) </span>{
mqttClientA.subscribe(
topic,
{qos: <span class="hljs-number">0</span>},
<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, granted</span>) </span>{
assert(!err);
assert(granted[<span class="hljs-number">0</span>].qos > <span class="hljs-number">2</span>, <span class="hljs-string">'should not have subscribed -t connect on topic '</span> + topic);
resolve();
}
);
});
}
<span class="hljs-built_in">Promise</span>.all(
[</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p><code>connect/${clientBId}/+</code>, </p></div></div><div class="code"><div class="wrapper"> <span class="hljs-string">`invalid/<span class="hljs-subst">${clientBId}</span>/+`</span>,
<span class="hljs-string">`connect`</span>,
<span class="hljs-string">`connect/`</span>,
<span class="hljs-string">`connect//`</span>,
<span class="hljs-string">`connect/+`</span>,
<span class="hljs-string">`connect/#`</span>,
<span class="hljs-string">`connect/<span class="hljs-subst">${clientBId}</span>/#`</span>,
<span class="hljs-string">`connect/<span class="hljs-subst">${clientBId}</span>/`</span>,
<span class="hljs-string">`connect/<span class="hljs-subst">${clientBId}</span>`</span>,
<span class="hljs-string">`connect/<span class="hljs-subst">${clientBId}</span>/+/invalid`</span>,
<span class="hljs-string">`connect/<span class="hljs-subst">${clientBId}</span>/invalid/+`</span>
].map(promiseTest)
)
.then(() => done())
.catch(pcatch);
});
});
describe(<span class="hljs-string">'connecting client A to client B'</span>, () => {
it(<span class="hljs-string">'should subscribe -t message/'</span> + clientBId + <span class="hljs-string">'/'</span> + clientAChannelId + <span class="hljs-string">'/# '</span>, done => {</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>open a message channel to enable client-a to send messages:</p>
<p>subscribe -t message/<client-b-id>/<client-a-channel-id>/# </p></div></div><div class="code"><div class="wrapper"> mqttClientA.subscribe(
<span class="hljs-string">`message/<span class="hljs-subst">${clientBId}</span>/<span class="hljs-subst">${clientAChannelId}</span>/#`</span>,
{qos: <span class="hljs-number">0</span>},
<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, granted</span>) </span>{
assert(!err);
assert.strictEqual(granted[<span class="hljs-number">0</span>].qos, <span class="hljs-number">0</span>);
done();
}
);
});
it(<span class="hljs-string">'should refuse to subscribe -t message on invalid topics'</span>, done => {
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">promiseTest</span> (<span class="hljs-params">topic</span>) </span>{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">resolve</span>) </span>{
mqttClientA.subscribe(
topic,
{qos: <span class="hljs-number">0</span>},
<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, granted</span>) </span>{
assert(!err);
assert(granted[<span class="hljs-number">0</span>].qos > <span class="hljs-number">2</span>, <span class="hljs-string">'should not have subscribed -t message on topic '</span> + topic);
resolve();
}
);
});
}
<span class="hljs-built_in">Promise</span>.all(
[</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p><code>message/${clientBId}/${clientAChannelId}/#</code>, </p></div></div><div class="code"><div class="wrapper"> <span class="hljs-string">`invalid/<span class="hljs-subst">${clientBId}</span>/<span class="hljs-subst">${clientAChannelId}</span>/#`</span>,
<span class="hljs-string">`message`</span>,
<span class="hljs-string">`message/`</span>,
<span class="hljs-string">`message//`</span>,
<span class="hljs-string">`message//+`</span>,
<span class="hljs-string">`message/#`</span>,
<span class="hljs-string">`message/<span class="hljs-subst">${clientBId}</span>/#`</span>,
<span class="hljs-string">`message/<span class="hljs-subst">${clientBId}</span>/<span class="hljs-subst">${clientAChannelId}</span>/+`</span>,
<span class="hljs-string">`message/<span class="hljs-subst">${clientBId}</span>/<span class="hljs-subst">${clientAChannelId}</span>/+/bar`</span>,
<span class="hljs-string">`message/<span class="hljs-subst">${clientBId}</span>/<span class="hljs-subst">${clientAChannelId}</span>/foo/bar`</span>,
<span class="hljs-string">`message/from-client-id/`</span>,
<span class="hljs-string">`message/from-client-id`</span>,
<span class="hljs-string">`message/from-client-id/+`</span>,
<span class="hljs-string">`message/from-client-id/invalid/+`</span>
].map(promiseTest)
)
.then(() => done())
.catch(pcatch);
});
it(<span class="hljs-string">`should publish -t connect/<span class="hljs-subst">${clientBId}</span>/<span class="hljs-subst">${clientAId}</span> -m <span class="hljs-subst">${clientAChannelId}</span>`</span>, done => {</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>client-a publishes client-a-channel-id as message to client-b:</p>
<p>publish -t connect/<client-b-id>/<client-a-id> -m <client-a-channel-id> </p></div></div><div class="code"><div class="wrapper"> mqttClientA.publish(</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>topic</p></div></div><div class="code"><div class="wrapper"> <span class="hljs-string">`connect/<span class="hljs-subst">${clientBId}</span>/<span class="hljs-subst">${clientAId}</span>`</span>, </div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>message</p></div></div><div class="code"><div class="wrapper"> clientAChannelId,</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>options</p></div></div><div class="code"><div class="wrapper"> {qos: <span class="hljs-number">0</span>}, </div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>callback</p></div></div><div class="code"><div class="wrapper"> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
assert(!err);
done();
}
);
});
});
describe(<span class="hljs-string">'sending messages between clients'</span>, () => {</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>sending messages</p>
<p>publish -t message/<from>/<to></p>
<p>publish -t message/<from-device-id>/<to-channel-id></p>
<p>publish -t message/<client-b-id>/<client-a-channel-id>/foo -m '{packetId:123}' </p></div></div><div class="code"><div class="wrapper"> it(<span class="hljs-string">'should enable client B to send messages to client A'</span>, done => {
mqttClientA.on(<span class="hljs-string">'message'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">topic, payload</span>) </span>{
<span class="hljs-keyword">if</span> (topic === <span class="hljs-string">`message/<span class="hljs-subst">${clientBId}</span>/<span class="hljs-subst">${clientAChannelId}</span>/foo`</span>) {
assert.strictEqual(payload.toString(), <span class="hljs-string">'bar'</span>);
done();
}
});
mqttClientB.publish(</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>topic</p></div></div><div class="code"><div class="wrapper"> <span class="hljs-string">`message/<span class="hljs-subst">${clientBId}</span>/<span class="hljs-subst">${clientAChannelId}</span>/foo`</span>, </div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>message</p></div></div><div class="code"><div class="wrapper"> <span class="hljs-string">'bar'</span>,</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>options</p></div></div><div class="code"><div class="wrapper"> {qos: <span class="hljs-number">0</span>}
);
});
});
describe(<span class="hljs-string">'unsubscription of clients'</span>, () => {
it(<span class="hljs-string">'should unsubscribe client A'</span>, done => {
assert(mqttClientA.connected);
mqttClientA.end(<span class="hljs-literal">false</span>, () => {
assert(!mqttClientA.connected);
mqttClientB.end(<span class="hljs-literal">false</span>, () => {
done();
});
});
});
});
});</div></div></div></div></body></html>