You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1105 lines
27 KiB

/**
* Testing requires
*/
var should = require('should')
, stream = require('./util').testStream;
/**
* Unit under test
*/
var Connection = require('../connection');
module.exports = function() {
beforeEach(function () {
this.stream.removeAllListeners();
});
describe('#connect', function() {
it('should send a connect packet (minimal)', function(done) {
var expected = new Buffer([
16, 18, // Header
0, 6, 77, 81, 73, 115, 100, 112, // Protocol Id
3, // Protocol version
0, // Connect flags
0, 30, // Keepalive
0, 4, // Client id length
116, 101, 115, 116 // Client Id
]);
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
clean: false
};
this.conn.connect(fixture);
var that = this;
this.stream.on('readable', function() {
var packet = that.stream.read();
packet.should.eql(expected);
done();
});
});
it('should send a connect packet (maximal)', function(done) {
var expected = new Buffer([
16, 54, // Header
0, 6, 77, 81, 73, 115, 100, 112, // Protocol Id
3, // Protocol version
246, // Connect flags (u=1,p=1,wr=1,wq=2,wf=1,c=1)
0, 30, // Keepalive (30)
0, 4, // Client id length
116, 101, 115, 116, // Client Id
0, 5, // Will topic length
116, 111, 112, 105, 99, // Will topic ('topic')
0, 7, // Will payload length
112, 97, 121, 108, 111, 97, 100, // ('payload')
0, 8, // Username length
117, 115, 101, 114, 110, 97, 109, 101, // ('username')
0, 8, // Password length
112, 97, 115, 115, 119, 111, 114, 100 // ('password')
]);
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
will: {
topic: 'topic',
payload: 'payload',
qos: 2,
retain: true
},
clean: true,
username: 'username',
password: 'password'
};
this.conn.connect(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should send a connect packet with binary username/password', function(done) {
var expected = new Buffer([
16, 28, // Header
0, 6, 77, 81, 73, 115, 100, 112, // Protocol Id
3, // Protocol version
0x40 | 0x80, // Connect flags
0, 30, // Keepalive
0, 4, // Client id length
116, 101, 115, 116, // Client Id
0, 3, // username length
12, 13, 14, // username
0, 3, // password length
15, 16, 17 //password
]);
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
clean: false,
username: new Buffer([12, 13, 14]),
password: new Buffer([15, 16, 17])
};
var s = stream()
var c = new Connection(s, { encoding: 'binary' });
s.removeAllListeners();
c.connect(fixture);
s.on('readable', function() {
var packet = s.read();
packet.should.eql(expected);
done();
});
});
it('should send a connect packet with binary will payload', function(done) {
var expected = new Buffer([
16, 50, // Header
0, 6, 77, 81, 73, 115, 100, 112, // Protocol Id
3, // Protocol version
246, // Connect flags
0, 30, // Keepalive
0, 4, // Client id length
116, 101, 115, 116, // Client Id
0, 5, // Will topic length
116, 111, 112, 105, 99, // Will topic ('topic')
0, 3, // Will payload length
18, 19, 20, // Will payload
0, 8, // Username length
117, 115, 101, 114, 110, 97, 109, 101, // ('username')
0, 8, // Password length
112, 97, 115, 115, 119, 111, 114, 100 // ('password')
]);
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
will: {
topic: 'topic',
payload: new Buffer([18, 19, 20]),
qos: 2,
retain: true
},
clean: true,
username: 'username',
password: 'password'
};
var s = stream()
var c = new Connection(s, { encoding: 'binary' });
s.removeAllListeners();
c.connect(fixture);
s.on('readable', function() {
var packet = s.read();
packet.should.eql(expected);
done();
});
});
it('should send a connect packet with unicode will payload', function(done) {
var expected = new Buffer([
16, 49, // Header
0, 6, 77, 81, 73, 115, 100, 112, // Protocol Id
3, // Protocol version
246, // Connect flags
0, 30, // Keepalive
0, 4, // Client id length
116, 101, 115, 116, // Client Id
0, 5, // Will topic length
116, 111, 112, 105, 99, // Will topic ('topic')
0, 2, // Will payload length
194, 167, // Will payload - '§'
0, 8, // Username length
117, 115, 101, 114, 110, 97, 109, 101, // ('username')
0, 8, // Password length
112, 97, 115, 115, 119, 111, 114, 100 // ('password')
]);
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
will: {
topic: 'topic',
payload: '§',
qos: 2,
retain: true
},
clean: true,
username: 'username',
password: 'password'
};
var s = stream()
var c = new Connection(s, { encoding: 'binary' });
s.removeAllListeners();
c.connect(fixture);
s.on('readable', function() {
var packet = s.read();
packet.should.eql(expected);
done();
});
});
describe('invalid options', function () {
describe('protocol id', function () {
it('should reject non-string', function(done) {
var fixture = {
protocolId: 42,
protocolVersion: 3,
clientId: 'test',
keepalive: 30
}
var expectedErr = 'Invalid protocol id';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
});
describe('protocol version', function() {
it('should reject non-number', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: [],
clientId: 'test',
keepalive: 30
};
var expectedErr = 'Invalid protocol version';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
it('should reject >255', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 300,
clientId: 'test',
keepalive: 30
};
var expectedErr = 'Invalid protocol version';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
it('should reject <0', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: -20,
clientId: 'test',
keepalive: 30
};
var expectedErr = 'Invalid protocol version';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
});
describe('client id', function() {
it('should reject non-present', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
keepalive: 30
};
var expectedErr = 'Invalid client id';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
it('should reject empty', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: '',
keepalive: 30
};
var expectedErr = 'Invalid client id';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
it('should reject non-string', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: {},
keepalive: 30
};
var expectedErr = 'Invalid client id';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
});
describe('keepalive', function() {
it('should reject non-number', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 'blah'
};
var expectedErr = 'Invalid keepalive';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
it('should reject < 0', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: -2
};
var expectedErr = 'Invalid keepalive';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
it('should reject > 65535', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 65536
};
var expectedErr = 'Invalid keepalive';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
});
describe('will', function() {
it('should reject non-object', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
will: 'test'
};
var expectedErr = 'Invalid will';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
it('should reject will without valid topic',
function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
will: {
topic: 0,
payload: 'test',
qos: 0,
retain: false
}
};
var expectedErr = 'Invalid will topic';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
it('should reject will without valid payload',
function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
will: {
topic: 'test',
payload: 42,
qos: 0,
retain: false
}
};
var expectedErr = 'Invalid will payload';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
it.skip('should reject will with invalid qos', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
will: {
topic: 'test',
payload: 'test',
qos: '',
retain: false
}
};
var expectedErr = 'Invalid will qos';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
});
describe('username', function() {
it('should reject invalid username', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
username: 30
};
var expectedErr = 'Invalid username';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
});
describe('password', function() {
it('should reject invalid password', function(done) {
var fixture = {
protocolId: 'MQIsdp',
protocolVersion: 3,
clientId: 'test',
keepalive: 30,
password: 30
};
var expectedErr = 'Invalid password';
this.conn.once('error', function(error) {
error.message.should.equal(expectedErr);
done();
});
this.conn.connect(fixture);
});
});
});
});
describe('#connack', function() {
it('should send a connack packet (rc = 0)', function(done) {
var expected = new Buffer([
32, 2, // Header
0, 0 // rc=0
]);
var fixture = {
returnCode: 0
};
this.conn.connack(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should send a connack packet (rc = 4)', function(done) {
var expected = new Buffer([
32, 2, // Header
0, 4 // rc=0
]);
var fixture = {
returnCode: 4
};
this.conn.connack(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should reject invalid rc', function (done) {
this.conn.once('error', function(error) {
error.message.should.equal('Invalid return code');
done();
});
this.conn.connack({returnCode: 'asdf'});
});
});
describe('#publish', function() {
it('should send a publish packet (minimal)', function(done) {
var expected = new Buffer([
48, 10, // Header
0, 4, // topic length
116, 101, 115, 116, // topic ('test')
116, 101, 115, 116, // payload ('test')
]);
var fixture = {
topic: 'test',
payload: 'test'
};
this.conn.publish(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should send a publish packet (maximal)', function (done) {
var expected = new Buffer([
61, 12, // Header
0, 4, // topic length
116, 101, 115, 116, // topic ('test')
0, 7, // message id (7)
116, 101, 115, 116, // payload ('test')
]);
var fixture = {
topic: 'test',
payload: 'test',
qos: 2,
retain: true,
dup: true,
messageId: 7
};
this.conn.publish(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should send a publish packet (empty)', function(done) {
var expected = new Buffer([
48, 6, // Header
0, 4, // topic length
116, 101, 115, 116 // topic ('test')
// empty payload
]);
var fixture = {
topic: 'test'
};
this.conn.publish(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should send a publish packet (buffer)', function(done) {
var expected = new Buffer([
48, 10, // Header
0, 4, // topic length
116, 101, 115, 116, // topic ('test')
0, 0, 0, 0 // payload
]);
var buf = new Buffer(4);
buf.fill(0);
var fixture = {
topic: 'test',
payload: buf
}
this.conn.publish(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should send a publish packet of 2 KB', function(done) {
var expected = new Buffer([
48, 134, 16, // Header
0, 4, // topic length
116, 101, 115, 116 // topic ('test')
]);
var payload = new Buffer(2048);
expected = Buffer.concat([expected, payload]);
var fixture = {
topic: 'test',
payload: payload
};
this.stream.on('readable', function() {
var data = this.read();
data.toString('hex').should.eql(expected.toString('hex'));
done();
});
this.conn.publish(fixture);
this.conn.end();
});
it('should send a publish packet of 2 MB', function(done) {
var expected = new Buffer([
48, 134, 128, 128, 1, // Header
0, 4, // topic length
116, 101, 115, 116 // topic ('test')
]);
var payload = new Buffer(2 * 1024 * 1024);
expected = Buffer.concat([expected, payload]);
var fixture = {
topic: 'test',
payload: payload
};
this.conn.publish(fixture);
this.conn.end();
this.stream.on('readable', function() {
var data = this.read();
data.toString('hex').should.eql(expected.toString('hex'));
done();
});
});
it('should reject invalid topic', function (done) {
var error = "Invalid topic";
this.conn.once('error', function(err) {
err.message.should.equal(error);
done();
});
this.conn.publish({topic: 0});
});
it('should reject invalid payloads, maybe');
it('should reject invalid mid', function(done) {
this.conn.once('error', function(err) {
err.message.should.equal('Invalid message id');
done();
});
this.conn.publish({topic: 'test', messageId: '', qos:1});
});
});
describe('#puback', function() {
it('should send a puback packet', function(done) {
var expected = new Buffer([
64, 2, // header
0, 30 // mid=30
]);
var fixture = {
messageId: 30
};
this.conn.puback(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should reject invalid mid', function (done) {
this.conn.once('error', function(error) {
error.message.should.equal('Invalid message id');
done();
});
this.conn.puback({messageId: ''});
});
});
describe('#pubrec', function() {
it('should send a pubrec packet', function(done) {
var expected = new Buffer([
80, 2, // header
0, 3 // mid=3
]);
var fixture = {
messageId: 3
};
this.conn.pubrec(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should reject invalid mid');
});
describe('#pubrel', function() {
it('should send a pubrel packet', function(done) {
var expected = new Buffer([
98, 2, // header
0, 6 // mid=6
]);
var fixture = {
messageId: 6
};
this.conn.pubrel(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should reject invalid mid');
});
describe('#pubcomp', function() {
it('should send a pubcomp packet', function(done) {
var expected = new Buffer([
116, 2, // header
0, 9 // mid=9
]);
var fixture = {
messageId: 9
};
this.conn.pubcomp(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should reject invalid mid');
});
describe('#subscribe', function() {
it('should send a subscribe packet (single)', function(done) {
var expected = new Buffer([
130, 9, // header
0, 7, // message id
0, 4, // topic length
116, 101, 115, 116, // topic
0 // qos=0
]);
var fixture = {
messageId: 7,
subscriptions: [
{
topic: 'test',
qos: 0
}
]
};
this.conn.subscribe(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should send subscribe packet (multiple)', function(done) {
var expected = new Buffer([
130, 23, // header
0, 8, // message id
0, 4, // topic length
116, 101, 115, 116, // topic ('test')
0, // qos=0
0, 4, //topic length
117, 101, 115, 116, // topic ('uest')
1, // qos=1
0, 4, //topic length
116, 101, 115, 115, // topic ('tess')
2 // qos=2
]);
var fixture = {
messageId: 8,
subscriptions: [
{
topic: 'test',
qos: 0
},{
topic: 'uest',
qos: 1
},{
topic: 'tess',
qos: 2
}
]
};
this.conn.subscribe(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should reject invalid subscriptions', function (done) {
this.conn.once('error', function(error) {
error.message.should.equal('Invalid subscriptions');
done();
});
this.conn.subscribe({
messageId: 1, subscriptions: ''
});
});
it('should reject invalid subscription objects');
it('should reject invalid mid', function (done) {
this.conn.once('error', function(error) {
error.message.should.equal('Invalid message id');
done();
});
this.conn.subscribe({
messageId: '', subscriptions:[{topic: 'test', qos: 1}]
});
});
});
describe('#suback', function() {
it('should send a suback packet', function(done) {
var expected = new Buffer([
144, 5, // length
0, 4, //mid=4
0, // qos=0
1, // qos=1
2, // qos=2
]);
var fixture = {
granted: [0, 1, 2],
messageId: 4
};
this.conn.suback(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should reject invalid mid');
it('should reject invalid qos vector', function (done) {
this.conn.on('error', function(error) {
error.message.should.equal('Invalid qos vector');
done();
});
this.conn.suback({granted: '', messageId: 1});
});
});
describe('#unsubscribe', function() {
it('should send an unsubscribe packet', function(done) {
var expected = new Buffer([
162, 14, // header
0, 6, // mid=6
0, 4, // topic length
116, 101, 115, 116, // topic ('test')
0, 4, // topic length
116, 115, 101, 116 // topic ('tset')
]);
var fixture = {
messageId: 6,
unsubscriptions: [
'test', 'tset'
]
};
this.conn.unsubscribe(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should reject invalid unsubs', function (done) {
this.conn.once('error', function(error) {
error.message.should.equal('Invalid unsubscriptions');
done();
});
this.conn.unsubscribe({
messageId: 1,
unsubscriptions: ''
});
});
it('should reject invalid mids');
});
describe('#unsuback', function() {
it('should send a unsuback packet', function(done) {
var expected = new Buffer([
176, 2, // header
0, 8 // mid=8
]);
var fixture = {
messageId: 8
};
this.conn.unsuback(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should reject invalid mid');
});
describe('#pingreq', function() {
it('should send a pingreq packet', function(done) {
var expected = new Buffer([
192, 0 // header
]);
var fixture = {
};
this.conn.pingreq(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
});
describe('#pingresp', function() {
it('should send a pingresp packet', function(done) {
var expected = new Buffer([
208, 0 // header
]);
var fixture = {
};
this.conn.pingresp(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
});
describe('#disconnect', function() {
it('should send a disconnect packet', function(done) {
var expected = new Buffer([
224, 0 // header
]);
var fixture = {
};
this.conn.disconnect(fixture);
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
it('should send a null disconnect packet', function(done) {
var expected = new Buffer([
224, 0 // header
]);
this.conn.disconnect();
var that = this;
this.stream.once('readable', function() {
that.stream.read(expected.length).should.eql(expected);
done();
});
});
});
};