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.
527 lines
14 KiB
527 lines
14 KiB
var steed = require("steed"); |
|
var tmp = require('tmp'); |
|
var fs = require("fs"); |
|
var mqtt = require("mqtt"); |
|
var os = require("os"); |
|
|
|
var SECURE_KEY = __dirname + '/secure/tls-key.pem'; |
|
var SECURE_CERT = __dirname + '/secure/tls-cert.pem'; |
|
|
|
describe("mosca.cli", function() { |
|
|
|
var servers = null, |
|
oldDebug = null, |
|
args = null; |
|
|
|
beforeEach(function(done) { |
|
args = ["node", "mosca"]; |
|
servers = [new mosca.Server({ |
|
port: 3833 |
|
}, done)]; |
|
}); |
|
|
|
afterEach(function(done) { |
|
var count = 0; |
|
steed.each(servers, function(s, cb) { |
|
count++; |
|
s.close(cb); |
|
}, function() { |
|
done(); |
|
}); |
|
}); |
|
|
|
var startServer = function(done, callback) { |
|
return mosca.cli(args, function(err, server) { |
|
if (server) { |
|
servers.unshift(server); |
|
callback(server); |
|
} |
|
setImmediate(done.bind(null, err)); |
|
}); |
|
}; |
|
|
|
it("must be a function", function() { |
|
expect(mosca.cli).to.be.a("function"); |
|
}); |
|
|
|
it("should start a mosca.Server", function(done) { |
|
startServer(done, function(server) { |
|
expect(server).to.be.instanceOf(mosca.Server); |
|
}); |
|
}); |
|
|
|
it("should support a port flag", function(done) { |
|
args.push("-p"); |
|
args.push("2883"); |
|
startServer(done, function(server) { |
|
expect(server.opts.port).to.eql(2883); |
|
}); |
|
}); |
|
|
|
it("should support a port flag (bis)", function(done) { |
|
args.push("--port"); |
|
args.push("2883"); |
|
startServer(done, function(server) { |
|
expect(server.opts.port).to.eql(2883); |
|
}); |
|
}); |
|
|
|
it("should support a parent port", function(done) { |
|
args.push("--parent-port"); |
|
args.push("3833"); |
|
startServer(done, function(server) { |
|
expect(server.opts.backend.type).to.eql("mqtt"); |
|
expect(server.opts.backend.port).to.eql(3833); |
|
}); |
|
}); |
|
|
|
it("should support a parent host", function(done) { |
|
args.push("--parent-host"); |
|
args.push("localhost"); |
|
args.push("--parent-port"); |
|
args.push("3833"); |
|
startServer(done, function(server) { |
|
expect(server.opts.backend.type).to.eql("mqtt"); |
|
expect(server.opts.backend.host).to.eql("localhost"); |
|
}); |
|
}); |
|
|
|
it("should support a parent prefix", function(done) { |
|
args.push("--parent-port"); |
|
args.push("3833"); |
|
args.push("--parent-prefix"); |
|
args.push("/ahaha"); |
|
startServer(done, function(server) { |
|
expect(server.opts.backend.prefix).to.eql("/ahaha"); |
|
}); |
|
}); |
|
|
|
it("should support a config option", function(done) { |
|
args.push("--config"); |
|
args.push("test/sample_config.js"); |
|
startServer(done, function(server) { |
|
expect(server.opts).to.have.property("port", 2883); |
|
expect(server.opts).to.have.deep.property("backend.port", 3833); |
|
}); |
|
}); |
|
|
|
it("should support a config option with an absolute path", function(done) { |
|
args.push("-c"); |
|
args.push(process.cwd() + "/test/sample_config.js"); |
|
startServer(done, function(server) { |
|
expect(server.opts).to.have.property("port", 2883); |
|
expect(server.opts).to.have.deep.property("backend.port", 3833); |
|
}); |
|
}); |
|
|
|
it("should add an user to an authorization file", function(done) { |
|
args.push("adduser"); |
|
args.push("myuser"); |
|
args.push("mypass"); |
|
args.push("--credentials"); |
|
|
|
tmp.file(function (err, path, fd) { |
|
if (err) { |
|
done(err); |
|
return; |
|
} |
|
|
|
args.push(path); |
|
mosca.cli(args, function () { |
|
var content = JSON.parse(fs.readFileSync(path)); |
|
expect(content).to.have.property("myuser"); |
|
done(); |
|
}); |
|
}); |
|
}); |
|
|
|
it("should add an user specifying the authorizePublish pattern", function(done) { |
|
args.push("adduser"); |
|
args.push("myuser"); |
|
args.push("mypass"); |
|
args.push("--authorize-publish"); |
|
args.push("hello/**/*"); |
|
args.push("--credentials"); |
|
|
|
tmp.file(function (err, path, fd) { |
|
if (err) { |
|
done(err); |
|
return; |
|
} |
|
|
|
args.push(path); |
|
mosca.cli(args, function () { |
|
var content = JSON.parse(fs.readFileSync(path)); |
|
expect(content.myuser).to.have.property("authorizePublish", "hello/**/*"); |
|
done(); |
|
}); |
|
}); |
|
}); |
|
|
|
it("should add an user specifying the authorizeSubscribe pattern", function(done) { |
|
args.push("adduser"); |
|
args.push("myuser"); |
|
args.push("mypass"); |
|
args.push("--authorize-subscribe"); |
|
args.push("hello/**/*"); |
|
args.push("--credentials"); |
|
|
|
tmp.file(function (err, path, fd) { |
|
if (err) { |
|
done(err); |
|
return; |
|
} |
|
|
|
args.push(path); |
|
mosca.cli(args, function () { |
|
var content = JSON.parse(fs.readFileSync(path)); |
|
expect(content.myuser).to.have.property("authorizeSubscribe", "hello/**/*"); |
|
done(); |
|
}); |
|
}); |
|
}); |
|
|
|
it("should remove an user from an authorization file", function(done) { |
|
args.push("adduser"); |
|
args.push("myuser"); |
|
args.push("mypass"); |
|
args.push("--credentials"); |
|
|
|
tmp.file(function (err, path, fd) { |
|
if (err) { |
|
done(err); |
|
return; |
|
} |
|
|
|
args.push(path); |
|
var cloned = [].concat(args); |
|
cloned[2] = "rmuser"; |
|
|
|
mosca.cli(args, function () { |
|
mosca.cli(cloned, function () { |
|
var content = JSON.parse(fs.readFileSync(path)); |
|
expect(content).not.to.have.property("myuser"); |
|
done(); |
|
}); |
|
}); |
|
}); |
|
}); |
|
|
|
it("should support authorizing an authorized client", function(done) { |
|
args.push("--credentials"); |
|
args.push("test/credentials.json"); |
|
steed.waterfall([ |
|
function(cb) { |
|
mosca.cli(args, cb); |
|
}, |
|
function(server, cb) { |
|
servers.unshift(server); |
|
|
|
var options = { username: "test", password: "test", port: 1883 }; |
|
var client = mqtt.connect(options); |
|
client.on("error", cb); |
|
client.on("connect", function() { |
|
cb(null, client); |
|
}); |
|
}, |
|
function(client, cb) { |
|
client.once("close", cb); |
|
client.end(); |
|
} |
|
], function(err) { |
|
if(err instanceof Error) { |
|
done(err); |
|
return; |
|
} |
|
done(); |
|
}); |
|
}); |
|
|
|
it("should support negating an unauthorized client", function(done) { |
|
args.push("--credentials"); |
|
args.push("test/credentials.json"); |
|
steed.waterfall([ |
|
function(cb) { |
|
mosca.cli(args, cb); |
|
}, |
|
function(server, cb) { |
|
servers.unshift(server); |
|
var options = { port: 1883, username: "bad", password: "bad" }; |
|
var client = mqtt.connect(options); |
|
client.on("error", cb); |
|
client.on("connect", function() { |
|
cb(null, client); |
|
}); |
|
}, |
|
function(client, cb) { |
|
client.once("close", cb); |
|
client.end(); |
|
} |
|
], function(err) { |
|
if(err) { |
|
done(); |
|
return; |
|
} |
|
done(new Error("No error thrown")); |
|
}); |
|
}); |
|
|
|
it("should reload the current config if killed with SIGHUP on a Linux-based OS", function(done) { |
|
|
|
if(os.platform() === "win32") return done(); |
|
|
|
args.push("adduser"); |
|
args.push("myuser"); |
|
args.push("mypass"); |
|
args.push("--credentials"); |
|
|
|
var cloned = null; |
|
|
|
steed.waterfall([ |
|
function(cb) { |
|
tmp.file(cb); |
|
}, |
|
function(path, fd, ignore, cb) { |
|
args.push(path); |
|
cloned = [].concat(args); |
|
cloned[2] = "rmuser"; |
|
|
|
mosca.cli(args, cb); |
|
}, |
|
function(cb) { |
|
mosca.cli(["node", "mosca", "--credentials", cloned[cloned.length - 1]], cb); |
|
}, |
|
function(server, cb) { |
|
servers.unshift(server); |
|
|
|
setTimeout(function() { |
|
mosca.cli(cloned, cb); |
|
}, 300); |
|
}, |
|
function(cb) { |
|
process.kill(process.pid, 'SIGHUP'); |
|
setTimeout(cb, 50); |
|
}, |
|
function(cb) { |
|
var options = { port: 1883, username: "myuser", password: "mypass" }; |
|
var client = mqtt.connect(options); |
|
client.once("error", cb); |
|
client.once("connect", function() { |
|
client.once("close", cb); |
|
client.end(); |
|
}); |
|
} |
|
], function(err) { |
|
if(err) { |
|
done(); |
|
return; |
|
} |
|
done(new Error("should have errored")); |
|
}); |
|
}); |
|
|
|
it("should save the credentials.json as a formatted JSON when adding", function(done) { |
|
args.push("adduser"); |
|
args.push("myuser"); |
|
args.push("mypass"); |
|
args.push("--credentials"); |
|
|
|
tmp.file(function (err, path, fd) { |
|
if (err) { |
|
done(err); |
|
return; |
|
} |
|
|
|
args.push(path); |
|
mosca.cli(args, function () { |
|
var content = fs.readFileSync(path); |
|
expect(JSON.stringify(JSON.parse(content), null, 2)).to.equal(content.toString('utf8')); |
|
done(); |
|
}); |
|
}); |
|
}); |
|
|
|
it("should save the credentials.json as a formatted JSON when removing", function(done) { |
|
args.push("adduser"); |
|
args.push("myuser"); |
|
args.push("mypass"); |
|
args.push("--credentials"); |
|
|
|
tmp.file(function (err, path, fd) { |
|
if (err) { |
|
done(err); |
|
return; |
|
} |
|
|
|
args.push(path); |
|
var cloned = [].concat(args); |
|
cloned[2] = "rmuser"; |
|
cloned[3] = "anotheruser"; |
|
|
|
mosca.cli(args, function () { |
|
mosca.cli(cloned, function () { |
|
var content = fs.readFileSync(path); |
|
expect(JSON.stringify(JSON.parse(content), null, 2)).to.equal(content.toString('utf8')); |
|
done(); |
|
}); |
|
}); |
|
}); |
|
}); |
|
|
|
it("should create a memory persistence object", function(done) { |
|
var s = startServer(done, function(server) { |
|
expect(server.persistence).to.be.instanceOf(mosca.persistence.Memory); |
|
}); |
|
}); |
|
|
|
it("should create a leveldb with the --db flag", function(done) { |
|
|
|
tmp.dir(function (err, path, fd) { |
|
if (err) { |
|
done(err); |
|
return; |
|
} |
|
|
|
args.push("--db"); |
|
args.push(path); |
|
|
|
startServer(done, function(server) { |
|
expect(server.persistence).to.be.instanceOf(mosca.persistence.LevelUp); |
|
expect(server.persistence.options.path).to.eql(path); |
|
}); |
|
}); |
|
}); |
|
|
|
describe("with --key and --cert", function() { |
|
|
|
beforeEach(function() { |
|
args.push("--key"); |
|
args.push(SECURE_KEY); |
|
args.push("--cert"); |
|
args.push(SECURE_CERT); |
|
}); |
|
|
|
it("should pass key and cert to the server", function(done) { |
|
startServer(done, function(server) { |
|
expect(server.opts.secure.keyPath).to.eql(SECURE_KEY); |
|
expect(server.opts.secure.certPath).to.eql(SECURE_CERT); |
|
}); |
|
}); |
|
|
|
it("should support the --secure-port flag", function(done) { |
|
var port = nextPort(); |
|
args.push("--secure-port"); |
|
args.push(port); |
|
startServer(done, function(server) { |
|
expect(server.opts.secure.port).to.eql(port); |
|
}); |
|
}); |
|
|
|
it("should set the secure port by default at 8883", function(done) { |
|
startServer(done, function(server) { |
|
expect(server.opts.secure.port).to.eql(8883); |
|
}); |
|
}); |
|
|
|
it("should pass the --non-secure flag to the server", function(done) { |
|
args.push("--non-secure"); |
|
startServer(done, function(server) { |
|
expect(server.opts.allowNonSecure).to.eql(true); |
|
}); |
|
}); |
|
|
|
it("should allow to set the https port", function(done) { |
|
|
|
args.push("--https-port"); |
|
args.push("3000"); |
|
startServer(done, function(server) { |
|
expect(server.opts.https.port).to.eql(3000); |
|
}); |
|
}); |
|
|
|
it("should serve a HTTPS static directory", function(done) { |
|
args.push("--https-port"); |
|
args.push("3000"); |
|
args.push("--https-static"); |
|
args.push("/path/to/nowhere"); |
|
startServer(done, function(server) { |
|
expect(server.opts.https.static).to.eql("/path/to/nowhere"); |
|
}); |
|
}); |
|
|
|
it("should serve a HTTPS browserify bundle", function(done) { |
|
args.push("--https-port"); |
|
args.push("3000"); |
|
args.push("--https-bundle"); |
|
startServer(done, function(server) { |
|
expect(server.opts.https.bundle).to.eql(true); |
|
}); |
|
}); |
|
|
|
}); |
|
|
|
it("should allow to set the http port", function(done) { |
|
args.push("--http-port"); |
|
args.push("3000"); |
|
startServer(done, function(server) { |
|
expect(server.opts.http.port).to.eql(3000); |
|
}); |
|
}); |
|
|
|
it("should allow to limit the server only to http", function(done) { |
|
args.push("--http-port"); |
|
args.push("3000"); |
|
args.push("--only-http"); |
|
startServer(done, function(server) { |
|
expect(server.opts.http.port).to.eql(3000); |
|
}); |
|
}); |
|
|
|
it("should serve a HTTP static directory", function(done) { |
|
args.push("--http-port"); |
|
args.push("3000"); |
|
args.push("--http-static"); |
|
args.push("/path/to/nowhere"); |
|
startServer(done, function(server) { |
|
expect(server.opts.http.static).to.eql("/path/to/nowhere"); |
|
}); |
|
}); |
|
|
|
it("should serve a HTTP browserify bundle", function(done) { |
|
args.push("--http-port"); |
|
args.push("3000"); |
|
args.push("--http-bundle"); |
|
startServer(done, function(server) { |
|
expect(server.opts.http.bundle).to.eql(true); |
|
}); |
|
}); |
|
|
|
it("should have stats enabled by default", function(done) { |
|
var s = startServer(done, function(server) { |
|
expect(server.opts.stats).to.equal(true); |
|
}); |
|
}); |
|
|
|
it("should allow to disable stats", function(done) { |
|
args.push("--disable-stats"); |
|
var s = startServer(done, function(server) { |
|
expect(server.opts.stats).to.equal(false); |
|
}); |
|
}); |
|
|
|
it("should allow to specify a broker id", function(done) { |
|
args.push("--broker-id"); |
|
args.push("44cats"); |
|
var s = startServer(done, function(server) { |
|
expect(server.id).to.equal("44cats"); |
|
}); |
|
}); |
|
|
|
it("should specify an interface to bind to", function(done) { |
|
args.push("--host"); |
|
args.push("127.0.0.1"); |
|
startServer(done, function(server) { |
|
expect(server.opts.host).to.eql("127.0.0.1"); |
|
}); |
|
}); |
|
});
|
|
|