首次提交

This commit is contained in:
2026-07-13 12:06:16 +08:00
commit e3c810b1a6
1690 changed files with 228324 additions and 0 deletions
+302
View File
@@ -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')
})
})
})