2014-07-17 09:34:26 +02:00
|
|
|
/**
|
2017-01-11 16:24:33 +01:00
|
|
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
2014-07-17 09:34:26 +02:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
**/
|
|
|
|
var should = require("should");
|
2014-11-04 18:05:29 +01:00
|
|
|
var when = require("when");
|
|
|
|
var sinon = require("sinon");
|
2015-11-12 08:56:23 +01:00
|
|
|
var path = require("path");
|
2014-11-04 18:05:29 +01:00
|
|
|
|
2015-11-12 08:56:23 +01:00
|
|
|
var api = require("../../../red/api");
|
|
|
|
var runtime = require("../../../red/runtime");
|
2014-07-17 09:34:26 +02:00
|
|
|
|
2015-11-12 08:56:23 +01:00
|
|
|
var redNodes = require("../../../red/runtime/nodes");
|
|
|
|
var storage = require("../../../red/runtime/storage");
|
|
|
|
var settings = require("../../../red/runtime/settings");
|
|
|
|
var log = require("../../../red/runtime/log");
|
|
|
|
|
|
|
|
describe("runtime", function() {
|
2015-11-11 23:11:02 +01:00
|
|
|
afterEach(function() {
|
|
|
|
if (console.log.restore) {
|
|
|
|
console.log.restore();
|
|
|
|
}
|
|
|
|
})
|
2015-10-11 21:37:11 +02:00
|
|
|
|
2014-11-04 18:05:29 +01:00
|
|
|
before(function() {
|
2015-11-12 08:56:23 +01:00
|
|
|
process.env.NODE_RED_HOME = path.resolve(path.join(__dirname,"..","..",".."))
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
|
|
|
after(function() {
|
2015-11-12 08:56:23 +01:00
|
|
|
delete process.env.NODE_RED_HOME;
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
2015-10-11 21:37:11 +02:00
|
|
|
|
2015-11-11 23:11:02 +01:00
|
|
|
describe("init", function() {
|
|
|
|
beforeEach(function() {
|
2015-11-12 08:56:23 +01:00
|
|
|
sinon.stub(log,"init",function() {});
|
|
|
|
sinon.stub(settings,"init",function() {});
|
2015-11-24 23:38:42 +01:00
|
|
|
sinon.stub(redNodes,"init",function() {})
|
2015-11-11 23:11:02 +01:00
|
|
|
});
|
|
|
|
afterEach(function() {
|
2015-11-12 08:56:23 +01:00
|
|
|
log.init.restore();
|
|
|
|
settings.init.restore();
|
2015-11-24 23:38:42 +01:00
|
|
|
redNodes.init.restore();
|
2015-11-11 23:11:02 +01:00
|
|
|
})
|
2015-10-11 21:37:11 +02:00
|
|
|
|
2015-11-11 23:11:02 +01:00
|
|
|
it("initialises components", function() {
|
2015-11-12 10:03:03 +01:00
|
|
|
runtime.init({testSettings: true, httpAdminRoot:"/"});
|
2016-10-10 14:27:43 +02:00
|
|
|
log.init.called.should.be.true();
|
|
|
|
settings.init.called.should.be.true();
|
|
|
|
redNodes.init.called.should.be.true();
|
2015-11-11 23:11:02 +01:00
|
|
|
});
|
2015-10-11 21:37:11 +02:00
|
|
|
|
2015-11-12 08:56:23 +01:00
|
|
|
it("returns version", function() {
|
2015-11-12 10:03:03 +01:00
|
|
|
runtime.init({testSettings: true, httpAdminRoot:"/"});
|
2016-10-10 14:27:43 +02:00
|
|
|
/^\d+\.\d+\.\d+(-git)?$/.test(runtime.version()).should.be.true();
|
2015-11-11 23:11:02 +01:00
|
|
|
|
2015-11-12 08:56:23 +01:00
|
|
|
})
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
2015-10-11 21:37:11 +02:00
|
|
|
|
2015-03-21 18:42:06 +01:00
|
|
|
describe("start",function() {
|
|
|
|
var storageInit;
|
|
|
|
var settingsLoad;
|
|
|
|
var logMetric;
|
|
|
|
var logWarn;
|
|
|
|
var logInfo;
|
|
|
|
var logLog;
|
|
|
|
var redNodesInit;
|
|
|
|
var redNodesLoad;
|
|
|
|
var redNodesCleanModuleList;
|
|
|
|
var redNodesGetNodeList;
|
|
|
|
var redNodesLoadFlows;
|
2015-10-11 21:37:11 +02:00
|
|
|
var redNodesStartFlows;
|
|
|
|
|
2015-03-21 18:42:06 +01:00
|
|
|
beforeEach(function() {
|
|
|
|
storageInit = sinon.stub(storage,"init",function(settings) {return when.resolve();});
|
|
|
|
logMetric = sinon.stub(log,"metric",function() { return false; });
|
|
|
|
logWarn = sinon.stub(log,"warn",function() { });
|
|
|
|
logInfo = sinon.stub(log,"info",function() { });
|
|
|
|
logLog = sinon.stub(log,"log",function(m) {});
|
|
|
|
redNodesInit = sinon.stub(redNodes,"init", function() {});
|
|
|
|
redNodesLoad = sinon.stub(redNodes,"load", function() {return when.resolve()});
|
|
|
|
redNodesCleanModuleList = sinon.stub(redNodes,"cleanModuleList",function(){});
|
2015-10-11 21:37:11 +02:00
|
|
|
redNodesLoadFlows = sinon.stub(redNodes,"loadFlows",function() {return when.resolve()});
|
|
|
|
redNodesStartFlows = sinon.stub(redNodes,"startFlows",function() {});
|
2015-03-21 18:42:06 +01:00
|
|
|
});
|
|
|
|
afterEach(function() {
|
|
|
|
storageInit.restore();
|
|
|
|
logMetric.restore();
|
|
|
|
logWarn.restore();
|
|
|
|
logInfo.restore();
|
|
|
|
logLog.restore();
|
|
|
|
redNodesInit.restore();
|
|
|
|
redNodesLoad.restore();
|
2015-10-11 21:37:11 +02:00
|
|
|
redNodesGetNodeList.restore();
|
2015-03-21 18:42:06 +01:00
|
|
|
redNodesCleanModuleList.restore();
|
|
|
|
redNodesLoadFlows.restore();
|
2015-10-11 21:37:11 +02:00
|
|
|
redNodesStartFlows.restore();
|
2015-03-21 18:42:06 +01:00
|
|
|
});
|
|
|
|
it("reports errored/missing modules",function(done) {
|
2015-03-30 22:49:20 +02:00
|
|
|
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) {
|
2015-03-21 18:42:06 +01:00
|
|
|
return [
|
|
|
|
{ err:"errored",name:"errName" }, // error
|
|
|
|
{ module:"module",enabled:true,loaded:false,types:["typeA","typeB"]} // missing
|
2015-03-30 22:49:20 +02:00
|
|
|
].filter(cb);
|
2015-03-21 18:42:06 +01:00
|
|
|
});
|
2015-11-12 10:03:03 +01:00
|
|
|
runtime.init({testSettings: true, httpAdminRoot:"/", load:function() { return when.resolve();}});
|
2015-11-11 23:11:02 +01:00
|
|
|
sinon.stub(console,"log");
|
|
|
|
runtime.start().then(function() {
|
|
|
|
console.log.restore();
|
2015-03-21 18:42:06 +01:00
|
|
|
try {
|
2016-10-10 14:27:43 +02:00
|
|
|
storageInit.calledOnce.should.be.true();
|
|
|
|
redNodesInit.calledOnce.should.be.true();
|
|
|
|
redNodesLoad.calledOnce.should.be.true();
|
|
|
|
redNodesLoadFlows.calledOnce.should.be.true();
|
2015-10-11 21:37:11 +02:00
|
|
|
|
2015-03-21 18:42:06 +01:00
|
|
|
logWarn.calledWithMatch("Failed to register 1 node type");
|
|
|
|
logWarn.calledWithMatch("Missing node modules");
|
|
|
|
logWarn.calledWithMatch(" - module: typeA, typeB");
|
2016-10-10 14:27:43 +02:00
|
|
|
redNodesCleanModuleList.calledOnce.should.be.true();
|
2015-03-21 18:42:06 +01:00
|
|
|
done();
|
|
|
|
} catch(err) {
|
|
|
|
done(err);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
it("initiates load of missing modules",function(done) {
|
2015-03-30 22:49:20 +02:00
|
|
|
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) {
|
2015-03-21 18:42:06 +01:00
|
|
|
return [
|
|
|
|
{ err:"errored",name:"errName" }, // error
|
|
|
|
{ err:"errored",name:"errName" }, // error
|
|
|
|
{ module:"module",enabled:true,loaded:false,types:["typeA","typeB"]}, // missing
|
|
|
|
{ module:"node-red",enabled:true,loaded:false,types:["typeC","typeD"]} // missing
|
2015-03-30 22:49:20 +02:00
|
|
|
].filter(cb);
|
2015-03-21 18:42:06 +01:00
|
|
|
});
|
2015-11-08 15:06:36 +01:00
|
|
|
var serverInstallModule = sinon.stub(redNodes,"installModule",function(name) { return when.resolve();});
|
2015-11-12 10:03:03 +01:00
|
|
|
runtime.init({testSettings: true, autoInstallModules:true, httpAdminRoot:"/", load:function() { return when.resolve();}});
|
2015-11-11 23:11:02 +01:00
|
|
|
sinon.stub(console,"log");
|
|
|
|
runtime.start().then(function() {
|
|
|
|
console.log.restore();
|
2015-03-21 18:42:06 +01:00
|
|
|
try {
|
|
|
|
logWarn.calledWithMatch("Failed to register 2 node types");
|
|
|
|
logWarn.calledWithMatch("Missing node modules");
|
|
|
|
logWarn.calledWithMatch(" - module: typeA, typeB");
|
|
|
|
logWarn.calledWithMatch(" - node-red: typeC, typeD");
|
2016-10-10 14:27:43 +02:00
|
|
|
redNodesCleanModuleList.calledOnce.should.be.false();
|
|
|
|
serverInstallModule.calledOnce.should.be.true();
|
2015-03-21 18:42:06 +01:00
|
|
|
serverInstallModule.calledWithMatch("module");
|
|
|
|
done();
|
|
|
|
} catch(err) {
|
|
|
|
done(err);
|
|
|
|
} finally {
|
|
|
|
serverInstallModule.restore();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
it("reports errored modules when verbose is enabled",function(done) {
|
2015-03-30 22:49:20 +02:00
|
|
|
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) {
|
2015-03-21 18:42:06 +01:00
|
|
|
return [
|
|
|
|
{ err:"errored",name:"errName" } // error
|
2015-03-30 22:49:20 +02:00
|
|
|
].filter(cb);
|
2015-03-21 18:42:06 +01:00
|
|
|
});
|
2015-11-12 10:03:03 +01:00
|
|
|
runtime.init({testSettings: true, verbose:true, httpAdminRoot:"/", load:function() { return when.resolve();}});
|
2015-11-11 23:11:02 +01:00
|
|
|
sinon.stub(console,"log");
|
|
|
|
runtime.start().then(function() {
|
|
|
|
console.log.restore();
|
2015-03-21 18:42:06 +01:00
|
|
|
try {
|
|
|
|
logWarn.neverCalledWithMatch("Failed to register 1 node type");
|
|
|
|
logWarn.calledWithMatch("[errName] errored");
|
|
|
|
done();
|
|
|
|
} catch(err) {
|
|
|
|
done(err);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2015-10-11 21:37:11 +02:00
|
|
|
|
2015-03-21 18:42:06 +01:00
|
|
|
it("reports runtime metrics",function(done) {
|
|
|
|
var stopFlows = sinon.stub(redNodes,"stopFlows",function() {} );
|
|
|
|
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []});
|
|
|
|
logMetric.restore();
|
|
|
|
logMetric = sinon.stub(log,"metric",function() { return true; });
|
2015-11-12 10:03:03 +01:00
|
|
|
runtime.init({testSettings: true, runtimeMetricInterval:200, httpAdminRoot:"/", load:function() { return when.resolve();}});
|
2015-11-11 23:11:02 +01:00
|
|
|
sinon.stub(console,"log");
|
|
|
|
runtime.start().then(function() {
|
|
|
|
console.log.restore();
|
2015-03-21 18:42:06 +01:00
|
|
|
setTimeout(function() {
|
|
|
|
try {
|
|
|
|
logLog.args.should.have.lengthOf(3);
|
|
|
|
logLog.args[0][0].should.have.property("level",log.METRIC);
|
|
|
|
logLog.args[0][0].should.have.property("event","runtime.memory.rss");
|
|
|
|
logLog.args[1][0].should.have.property("level",log.METRIC);
|
|
|
|
logLog.args[1][0].should.have.property("event","runtime.memory.heapTotal");
|
|
|
|
logLog.args[2][0].should.have.property("level",log.METRIC);
|
|
|
|
logLog.args[2][0].should.have.property("event","runtime.memory.heapUsed");
|
|
|
|
done();
|
|
|
|
} catch(err) {
|
|
|
|
done(err);
|
|
|
|
} finally {
|
2015-11-11 23:11:02 +01:00
|
|
|
runtime.stop();
|
2015-03-21 18:42:06 +01:00
|
|
|
stopFlows.restore();
|
|
|
|
}
|
2015-11-11 23:11:02 +01:00
|
|
|
},300);
|
2015-03-21 18:42:06 +01:00
|
|
|
});
|
2015-10-11 21:37:11 +02:00
|
|
|
});
|
|
|
|
|
2015-11-11 23:11:02 +01:00
|
|
|
|
2015-03-21 18:42:06 +01:00
|
|
|
});
|
2015-10-11 21:37:11 +02:00
|
|
|
|
2014-11-04 18:05:29 +01:00
|
|
|
it("stops components", function() {
|
|
|
|
var stopFlows = sinon.stub(redNodes,"stopFlows",function() {} );
|
2015-11-11 23:11:02 +01:00
|
|
|
runtime.stop();
|
2016-10-10 14:27:43 +02:00
|
|
|
stopFlows.called.should.be.true();
|
2014-11-04 18:05:29 +01:00
|
|
|
stopFlows.restore();
|
|
|
|
});
|
2014-07-17 09:34:26 +02:00
|
|
|
});
|