首次提交
This commit is contained in:
+302
@@ -0,0 +1,302 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { setup, connect, subscribe } = require('./helper')
|
||||
const aedes = require('../')
|
||||
const { validateTopic } = require('../lib/utils')
|
||||
|
||||
test('validation of `null` topic', function (t) {
|
||||
// issue #780
|
||||
t.plan(1)
|
||||
const err = validateTopic(null, 'SUBSCRIBE')
|
||||
t.equal(err.message, 'impossible to SUBSCRIBE to an empty topic')
|
||||
})
|
||||
|
||||
// [MQTT-4.7.1-3]
|
||||
test('Single-level wildcard should match empty level', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
const s = connect(setup())
|
||||
t.teardown(s.broker.close.bind(s.broker))
|
||||
|
||||
subscribe(t, s, 'a/+/b', 0, function () {
|
||||
s.outStream.once('data', function (packet) {
|
||||
t.pass('ok')
|
||||
})
|
||||
|
||||
s.inStream.write({
|
||||
cmd: 'publish',
|
||||
topic: 'a//b',
|
||||
payload: 'world'
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// [MQTT-4.7.3-1]
|
||||
test('publish empty topic', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
const s = connect(setup())
|
||||
|
||||
subscribe(t, s, '#', 0, function () {
|
||||
s.outStream.once('data', function (packet) {
|
||||
t.fail('no packet')
|
||||
})
|
||||
|
||||
s.inStream.write({
|
||||
cmd: 'publish',
|
||||
topic: '',
|
||||
payload: 'world'
|
||||
})
|
||||
|
||||
s.broker.close(function () {
|
||||
t.equal(s.broker.connectedClients, 0, 'no connected clients')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('publish invalid topic with #', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
const s = connect(setup())
|
||||
t.teardown(s.broker.close.bind(s.broker))
|
||||
|
||||
subscribe(t, s, '#', 0, function () {
|
||||
s.outStream.once('data', function (packet) {
|
||||
t.fail('no packet')
|
||||
})
|
||||
|
||||
s.inStream.write({
|
||||
cmd: 'publish',
|
||||
topic: 'hello/#',
|
||||
payload: 'world'
|
||||
})
|
||||
})
|
||||
|
||||
s.broker.on('clientError', function () {
|
||||
t.pass('raise an error')
|
||||
})
|
||||
})
|
||||
|
||||
test('publish invalid topic with +', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
const s = connect(setup())
|
||||
t.teardown(s.broker.close.bind(s.broker))
|
||||
|
||||
subscribe(t, s, '#', 0, function () {
|
||||
s.outStream.once('data', function (packet) {
|
||||
t.fail('no packet')
|
||||
})
|
||||
|
||||
s.inStream.write({
|
||||
cmd: 'publish',
|
||||
topic: 'hello/+/eee',
|
||||
payload: 'world'
|
||||
})
|
||||
})
|
||||
|
||||
s.broker.on('clientError', function () {
|
||||
t.pass('raise an error')
|
||||
})
|
||||
})
|
||||
|
||||
;['base/#/sub', 'base/#sub', 'base/sub#', 'base/xyz+/sub', 'base/+xyz/sub', ''].forEach(function (topic) {
|
||||
test('subscribe to invalid topic with "' + topic + '"', function (t) {
|
||||
t.plan(1)
|
||||
|
||||
const s = connect(setup())
|
||||
t.teardown(s.broker.close.bind(s.broker))
|
||||
|
||||
s.broker.on('clientError', function () {
|
||||
t.pass('raise an error')
|
||||
})
|
||||
|
||||
s.inStream.write({
|
||||
cmd: 'subscribe',
|
||||
messageId: 24,
|
||||
subscriptions: [{
|
||||
topic,
|
||||
qos: 0
|
||||
}]
|
||||
})
|
||||
})
|
||||
|
||||
test('unsubscribe to invalid topic with "' + topic + '"', function (t) {
|
||||
t.plan(1)
|
||||
|
||||
const s = connect(setup())
|
||||
t.teardown(s.broker.close.bind(s.broker))
|
||||
|
||||
s.broker.on('clientError', function () {
|
||||
t.pass('raise an error')
|
||||
})
|
||||
|
||||
s.inStream.write({
|
||||
cmd: 'unsubscribe',
|
||||
messageId: 24,
|
||||
unsubscriptions: [topic]
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('topics are case-sensitive', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
const broker = aedes()
|
||||
t.teardown(broker.close.bind(broker))
|
||||
|
||||
const publisher = connect(setup(broker), { clean: true })
|
||||
const subscriber = connect(setup(broker), { clean: true })
|
||||
const expected = {
|
||||
cmd: 'publish',
|
||||
topic: 'hello',
|
||||
payload: Buffer.from('world'),
|
||||
qos: 0,
|
||||
dup: false,
|
||||
length: 12,
|
||||
retain: false
|
||||
}
|
||||
|
||||
subscribe(t, subscriber, 'hello', 0, function () {
|
||||
subscriber.outStream.on('data', function (packet) {
|
||||
t.same(packet, expected, 'packet mush match')
|
||||
})
|
||||
;['hello', 'HELLO', 'heLLo', 'HELLO/#', 'hello/+'].forEach(function (topic) {
|
||||
publisher.inStream.write({
|
||||
cmd: 'publish',
|
||||
topic,
|
||||
payload: 'world',
|
||||
qos: 0,
|
||||
retain: false
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function subscribeMultipleTopics (t, broker, qos, subscriber, subscriptions, done) {
|
||||
const publisher = connect(setup(broker))
|
||||
subscriber.inStream.write({
|
||||
cmd: 'subscribe',
|
||||
messageId: 24,
|
||||
subscriptions
|
||||
})
|
||||
|
||||
subscriber.outStream.once('data', function (packet) {
|
||||
t.equal(packet.cmd, 'suback')
|
||||
t.same(packet.granted, subscriptions.map(obj => obj.qos))
|
||||
t.equal(packet.messageId, 24)
|
||||
|
||||
publisher.inStream.write({
|
||||
cmd: 'publish',
|
||||
topic: 'hello/world',
|
||||
payload: 'world',
|
||||
qos,
|
||||
messageId: 42
|
||||
})
|
||||
|
||||
if (done) {
|
||||
done(null, packet)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
test('Overlapped topics with same QoS', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
const broker = aedes()
|
||||
t.teardown(broker.close.bind(broker))
|
||||
|
||||
const subscriber = connect(setup(broker))
|
||||
const expected = {
|
||||
cmd: 'publish',
|
||||
topic: 'hello/world',
|
||||
payload: Buffer.from('world'),
|
||||
qos: 1,
|
||||
dup: false,
|
||||
length: 20,
|
||||
retain: false
|
||||
}
|
||||
const sub = [
|
||||
{ topic: 'hello/world', qos: 1 },
|
||||
{ topic: 'hello/#', qos: 1 }]
|
||||
subscribeMultipleTopics(t, broker, 1, subscriber, sub, function () {
|
||||
subscriber.outStream.on('data', function (packet) {
|
||||
delete packet.messageId
|
||||
t.same(packet, expected, 'packet must match')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// [MQTT-3.3.5-1]
|
||||
test('deliver overlapped topics respecting the maximum QoS of all the matching subscriptions - QoS 0 publish', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
const broker = aedes()
|
||||
t.teardown(broker.close.bind(broker))
|
||||
|
||||
const subscriber = connect(setup(broker))
|
||||
const expected = {
|
||||
cmd: 'publish',
|
||||
topic: 'hello/world',
|
||||
payload: Buffer.from('world'),
|
||||
qos: 0,
|
||||
dup: false,
|
||||
length: 18,
|
||||
retain: false
|
||||
}
|
||||
const sub = [
|
||||
{ topic: 'hello/world', qos: 0 },
|
||||
{ topic: 'hello/#', qos: 2 }]
|
||||
subscribeMultipleTopics(t, broker, 0, subscriber, sub, function () {
|
||||
subscriber.outStream.on('data', function (packet) {
|
||||
delete packet.messageId
|
||||
t.same(packet, expected, 'packet must match')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// [MQTT-3.3.5-1]
|
||||
test('deliver overlapped topics respecting the maximum QoS of all the matching subscriptions - QoS 2 publish', function (t) {
|
||||
t.plan(3)
|
||||
|
||||
const broker = aedes()
|
||||
t.teardown(broker.close.bind(broker))
|
||||
|
||||
const subscriber = connect(setup(broker))
|
||||
|
||||
const sub = [
|
||||
{ topic: 'hello/world', qos: 0 },
|
||||
{ topic: 'hello/#', qos: 2 }]
|
||||
subscribeMultipleTopics(t, broker, 2, subscriber, sub, function () {
|
||||
subscriber.outStream.on('data', function () {
|
||||
t.fail('should receive messages with the maximum QoS')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('Overlapped topics with QoS downgrade', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
const broker = aedes()
|
||||
t.teardown(broker.close.bind(broker))
|
||||
|
||||
const subscriber = connect(setup(broker))
|
||||
const expected = {
|
||||
cmd: 'publish',
|
||||
topic: 'hello/world',
|
||||
payload: Buffer.from('world'),
|
||||
qos: 0,
|
||||
dup: false,
|
||||
length: 18,
|
||||
retain: false
|
||||
}
|
||||
const sub = [
|
||||
{ topic: 'hello/world', qos: 1 },
|
||||
{ topic: 'hello/#', qos: 1 }]
|
||||
subscribeMultipleTopics(t, broker, 0, subscriber, sub, function () {
|
||||
subscriber.outStream.on('data', function (packet) {
|
||||
t.same(packet, expected, 'packet must match')
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user