1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Add open/close API for context

This commit is contained in:
HirokiUchikawa 2018-05-30 10:24:27 +09:00
parent 28d05e2449
commit 7185bcd51f
8 changed files with 318 additions and 260 deletions

View File

@ -90,6 +90,7 @@ function start() {
}) })
.then(function() { return storage.init(runtime)}) .then(function() { return storage.init(runtime)})
.then(function() { return settings.load(storage)}) .then(function() { return settings.load(storage)})
.then(function() { return redNodes.loadContextsPlugin()})
.then(function() { .then(function() {
if (log.metric()) { if (log.metric()) {
@ -109,8 +110,6 @@ function start() {
events.emit("runtime-event",{id:"runtime-unsupported-version",payload:{type:"error",text:"notification.errors.unsupportedVersion"},retain:true}); events.emit("runtime-event",{id:"runtime-unsupported-version",payload:{type:"error",text:"notification.errors.unsupportedVersion"},retain:true});
} }
log.info(os.type()+" "+os.release()+" "+os.arch()+" "+os.endianness()); log.info(os.type()+" "+os.release()+" "+os.arch()+" "+os.endianness());
log.info("Loading external context plugins");
redNodes.loadContextsPlugin();
return redNodes.load().then(function() { return redNodes.load().then(function() {
var i; var i;
@ -231,7 +230,9 @@ function stop() {
clearTimeout(reinstallTimeout); clearTimeout(reinstallTimeout);
} }
started = false; started = false;
return redNodes.stopFlows(); return redNodes.stopFlows().then(function(){
return redNodes.closeContextsPlugin();
});
} }
var runtime = module.exports = { var runtime = module.exports = {

View File

@ -17,6 +17,7 @@
var clone = require("clone"); var clone = require("clone");
var util = require("../../util"); var util = require("../../util");
var log = require("../../log"); var log = require("../../log");
var when = require("when");
var settings; var settings;
var contexts = {}; var contexts = {};
@ -30,8 +31,10 @@ function init(_settings) {
// init memory plugin // init memory plugin
var memory = require("./memory"); var memory = require("./memory");
var seed = settings.functionGlobalContext || {};
externalContexts["_"] = memory(); externalContexts["_"] = memory();
globalContext = createContext("global",settings.functionGlobalContext || {}); externalContexts["_"].setGlobalContext(seed);
globalContext = createContext("global",seed);
} }
function load() { function load() {
@ -39,6 +42,7 @@ function load() {
var plugins = settings.contextStorage; var plugins = settings.contextStorage;
var isAlias = false; var isAlias = false;
if (plugins) { if (plugins) {
var promises = [];
noContextStorage = false; noContextStorage = false;
for(var pluginName in plugins){ for(var pluginName in plugins){
if(pluginName === "_"){ if(pluginName === "_"){
@ -56,25 +60,32 @@ function load() {
try{ try{
plugin = require("./"+plugins[pluginName].module); plugin = require("./"+plugins[pluginName].module);
}catch(err){ }catch(err){
throw new Error(log._("context.error-module-not-loaded", {module:plugins[pluginName].module})); return when.reject(new Error(log._("context.error-module-not-loaded", {module:plugins[pluginName].module})));
} }
} else { } else {
plugin = plugins[pluginName].module; plugin = plugins[pluginName].module;
} }
externalContexts[pluginName] = plugin(config); externalContexts[pluginName] = plugin(config);
}else{ }else{
throw new Error(log._("context.error-module-not-defined", {storage:pluginName})); return when.reject(new Error(log._("context.error-module-not-defined", {storage:pluginName})));
} }
} }
if(isAlias){ if(isAlias){
if(externalContexts.hasOwnProperty(plugins["default"])){ if(externalContexts.hasOwnProperty(plugins["default"])){
externalContexts["default"] = externalContexts[plugins["default"]]; externalContexts["default"] = externalContexts[plugins["default"]];
}else{ }else{
throw new Error(log._("context.error-invalid-default-module", {storage:plugins["default"]})); return when.reject(new Error(log._("context.error-invalid-default-module", {storage:plugins["default"]})));
} }
} }
for(var plugin in externalContexts){
if(externalContexts.hasOwnProperty(plugin)){
promises.push(externalContexts[plugin].open());
}
}
return when.all(promises);
} else { } else {
noContextStorage = true; noContextStorage = true;
return externalContexts["_"].open();
} }
} }
@ -157,9 +168,6 @@ function createContext(id,seed) {
var context = getContextStorage(storageName); var context = getContextStorage(storageName);
return context.keys(scope); return context.keys(scope);
}; };
if(id === "global"){
externalContexts["_"].setGlobalContext(seed);
}
return obj; return obj;
} }
@ -210,10 +218,21 @@ function clean(flowConfig) {
} }
} }
function close() {
var promises = [];
for(var plugin in externalContexts){
if(externalContexts.hasOwnProperty(plugin)){
promises.push(externalContexts[plugin].close());
}
}
return when.all(promises);
}
module.exports = { module.exports = {
init: init, init: init,
load: load, load: load,
get: getContext, get: getContext,
delete: deleteContext, delete: deleteContext,
clean:clean clean: clean,
close: close
}; };

View File

@ -17,11 +17,10 @@
var JsonDB = require('node-json-db'); var JsonDB = require('node-json-db');
var fs = require('fs-extra'); var fs = require('fs-extra');
var path = require("path"); var path = require("path");
var when = require("when");
function createStorage(storageBaseDir, scope) { function createStorage(storageBaseDir, scope) {
var i = scope.indexOf(":") if(scope.indexOf(":") === -1){
if(i === -1){
if(scope === "global"){ if(scope === "global"){
return new JsonDB(path.join(storageBaseDir,"global",scope), true, true); return new JsonDB(path.join(storageBaseDir,"global",scope), true, true);
}else{ // scope:flow }else{ // scope:flow
@ -69,6 +68,14 @@ function LocalFileSystem(config){
this.storages = {}; this.storages = {};
} }
LocalFileSystem.prototype.open = function(){
return when.resolve();
}
LocalFileSystem.prototype.close = function(){
return when.resolve();
}
LocalFileSystem.prototype.get = function (scope, key) { LocalFileSystem.prototype.get = function (scope, key) {
if(!this.storages[scope]){ if(!this.storages[scope]){
return undefined; return undefined;

View File

@ -15,11 +15,20 @@
**/ **/
var util = require("../../util"); var util = require("../../util");
var when = require("when");
function Memory(config){ function Memory(config){
this.data = {}; this.data = {};
} }
Memory.prototype.open = function(){
return when.resolve();
};
Memory.prototype.close = function(){
return when.resolve();
};
Memory.prototype.get = function(scope, key) { Memory.prototype.get = function(scope, key) {
if(!this.data[scope]){ if(!this.data[scope]){
return undefined; return undefined;
@ -49,14 +58,7 @@ Memory.prototype.keys = function(scope){
Memory.prototype.delete = function(scope){ Memory.prototype.delete = function(scope){
delete this.data[scope]; delete this.data[scope];
};
Memory.prototype.open = function(){
return true;
};
Memory.prototype.close = function(){
delete this.data;
}; };
Memory.prototype.setGlobalContext= function(seed){ Memory.prototype.setGlobalContext= function(seed){

View File

@ -219,5 +219,6 @@ module.exports = {
getCredentialKeyType: credentials.getKeyType, getCredentialKeyType: credentials.getKeyType,
// Contexts // Contexts
loadContextsPlugin: context.load loadContextsPlugin: context.load,
closeContextsPlugin: context.close
}; };

View File

@ -92,7 +92,7 @@ describe("runtime", function() {
redNodesCleanModuleList = sinon.stub(redNodes,"cleanModuleList",function(){}); redNodesCleanModuleList = sinon.stub(redNodes,"cleanModuleList",function(){});
redNodesLoadFlows = sinon.stub(redNodes,"loadFlows",function() {return when.resolve()}); redNodesLoadFlows = sinon.stub(redNodes,"loadFlows",function() {return when.resolve()});
redNodesStartFlows = sinon.stub(redNodes,"startFlows",function() {}); redNodesStartFlows = sinon.stub(redNodes,"startFlows",function() {});
redNodesLoadContextsPlugin = sinon.stub(redNodes,"loadContextsPlugin",function() {}); redNodesLoadContextsPlugin = sinon.stub(redNodes,"loadContextsPlugin",function() {return when.resolve()});
}); });
afterEach(function() { afterEach(function() {
storageInit.restore(); storageInit.restore();
@ -186,7 +186,7 @@ describe("runtime", function() {
}); });
it("reports runtime metrics",function(done) { it("reports runtime metrics",function(done) {
var stopFlows = sinon.stub(redNodes,"stopFlows",function() {} ); var stopFlows = sinon.stub(redNodes,"stopFlows",function() { return when.resolve();} );
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []}); redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []});
logMetric.restore(); logMetric.restore();
logMetric = sinon.stub(log,"metric",function() { return true; }); logMetric = sinon.stub(log,"metric",function() { return true; });
@ -217,10 +217,18 @@ describe("runtime", function() {
}); });
it("stops components", function() { it("stops components", function(done) {
var stopFlows = sinon.stub(redNodes,"stopFlows",function() {} ); var stopFlows = sinon.stub(redNodes,"stopFlows",function() { return when.resolve();} );
runtime.stop(); var closeContextsPlugin = sinon.stub(redNodes,"closeContextsPlugin",function() { return when.resolve();} );
runtime.stop().then(function(){
stopFlows.called.should.be.true(); stopFlows.called.should.be.true();
closeContextsPlugin.called.should.be.true();
done();
}).catch(function(err){
return done(err)
}).finally(function(){
stopFlows.restore(); stopFlows.restore();
closeContextsPlugin.restore();
});
}); });
}); });

View File

@ -16,8 +16,6 @@
var should = require("should"); var should = require("should");
var sinon = require('sinon'); var sinon = require('sinon');
var path = require('path');
var fs = require('fs-extra');
var rewire = require("rewire"); var rewire = require("rewire");
var Context = require("../../../../../red/runtime/nodes/context/index"); var Context = require("../../../../../red/runtime/nodes/context/index");
@ -25,9 +23,11 @@ describe('context', function() {
describe('local memory',function() { describe('local memory',function() {
beforeEach(function() { beforeEach(function() {
Context.init({}); Context.init({});
return Context.load();
}); });
afterEach(function() { afterEach(function() {
Context.clean({allNodes:{}}); Context.clean({allNodes:{}});
return Context.close();
}); });
it('stores local property',function() { it('stores local property',function() {
var context1 = Context.get("1","flowA"); var context1 = Context.get("1","flowA");
@ -140,57 +140,261 @@ describe('context', function() {
keys.should.have.length(2); keys.should.have.length(2);
keys[1].should.eql("abc"); keys[1].should.eql("abc");
}); });
it('should store data on memory when contextStorage is not defined', function() {
var context = Context.get("1","flow");
context.set("#nonexist.key1", "val1");
context.get("#nonexist.key1").should.eql("val1");
context.flow.set("#nonexist.key2", "val2");
context.flow.get("#nonexist.key2").should.eql("val2");
context.global.set("#nonexist.key1", "val3");
context.global.get("#nonexist.key1").should.eql("val3");
});
}); });
describe('external context storage',function() { describe('external context storage',function() {
var testDir = path.join(__dirname,".testUserHome"); describe('load modules',function(){
var context; afterEach(function() {
var stubGet = sinon.stub(); Context.clean({allNodes:{}});
var stubSet = sinon.stub(); return Context.close();
var stubKeys = sinon.stub(); });
var stubDelete = sinon.stub();
var contextStorage={ it('should load memory module', function() {
test:{ Context.init({contextStorage:{memory:{module:"memory"}}});
module: function(config){ return Context.load();
});
it('should load localfilesystem module', function() {
Context.init({contextStorage:{file:{module:"localfilesystem"}}});
return Context.load();
});
it('should accept special storage name', function() {
Context.init({
contextStorage:{
"#%&":{module:"memory"},
\u3042:{module:"memory"},
1:{module:"memory"},
}
});
return Context.load().then(function(){
var context = Context.get("1","flow");
context.set("##%&.sign","sign1");
context.get("##%&.sign").should.eql("sign1");
context.set("#\u3042.file2","file2");
context.get("#\u3042.file2").should.eql("file2");
context.set("#1.num","num3");
context.get("#1.num").should.eql("num3");
});
});
it('should fail when using invalid default context', function(done) {
Context.init({contextStorage:{default:"noexist"}});
Context.load().then(function(){
done("An error was not thrown");
}).catch(function(){
done();
});
});
it('should fail for the storage with no module', function(done) {
Context.init({ contextStorage: { test: {}}});
Context.load().then(function(){
done("An error was not thrown");
}).catch(function(){
done();
});
});
it('should fail to load non-existent module', function(done) {
Context.init({contextStorage:{ file:{module:"nonexistent"} }});
Context.load().then(function(){
done("An error was not thrown");
}).catch(function(){
done();
});
});
});
describe('store data',function() {
var sandbox = sinon.sandbox.create();
var stubGet = sandbox.stub();
var stubSet = sandbox.stub();
var stubKeys = sandbox.stub();
var stubDelete = sandbox.stub();
var stubOpen = sandbox.stub().returns(Promise.resolve());
var stubClose = sandbox.stub().returns(Promise.resolve());
var stubGet2 = sandbox.stub();
var stubSet2 = sandbox.stub();
var stubKeys2 = sandbox.stub();
var stubDelete2 = sandbox.stub();
var stubOpen2 = sandbox.stub().returns(Promise.resolve());
var stubClose2 = sandbox.stub().returns(Promise.resolve());
var testPlugin = function(config){
function Test(){} function Test(){}
Test.prototype.get = stubGet; Test.prototype.get = stubGet;
Test.prototype.set = stubSet; Test.prototype.set = stubSet;
Test.prototype.keys = stubKeys; Test.prototype.keys = stubKeys;
Test.prototype.delete = stubDelete; Test.prototype.delete = stubDelete;
Test.prototype.open = stubOpen;
Test.prototype.close = stubClose;
return new Test(config); return new Test(config);
};
var testPlugin2 = function(config){
function Test2(){}
Test2.prototype.get = stubGet2;
Test2.prototype.set = stubSet2;
Test2.prototype.keys = stubKeys2;
Test2.prototype.delete = stubDelete2;
Test2.prototype.open = stubOpen2;
Test2.prototype.close = stubClose2;
return new Test2(config);
};
var contextStorage={
test:{
module: testPlugin,
config:{}
}
};
var contextDefaultStorage={
default: {
module: testPlugin2,
config:{}
}, },
test:{
module: testPlugin,
config:{} config:{}
} }
}; };
afterEach(function(done) { afterEach(function() {
stubGet.reset(); sandbox.reset();
stubSet.reset();
stubKeys.reset();
stubDelete.reset();
Context.clean({allNodes:{}}); Context.clean({allNodes:{}});
fs.remove(testDir,done); return Context.close();
}); });
function initializeContext() { it('should store local property to external context storage',function() {
Context.init({contextStorage:contextStorage}); Context.init({contextStorage:contextStorage});
Context.load(); return Context.load().then(function(){
context = Context.get("1","flow"); var context = Context.get("1","flow");
should.not.exist(context.get("#test.foo"));
context.set("#test.foo","test");
context.get("#test.foo");
context.keys("#test");
stubSet.calledWithExactly("1:flow","foo","test").should.be.true();
stubGet.calledWithExactly("1:flow","foo").should.be.true();
stubKeys.calledWithExactly("1:flow").should.be.true();
});
});
it('should store flow property to external context storage',function() {
Context.init({contextStorage:contextStorage});
return Context.load().then(function(){
var context = Context.get("1","flow");
should.not.exist(context.flow.get("#test.foo"));
context.flow.set("#test.foo","test");
context.flow.get("#test.foo");
context.flow.keys("#test");
stubSet.calledWithExactly("flow","foo","test").should.be.true();
stubGet.calledWithExactly("flow","foo").should.be.true();
stubKeys.calledWithExactly("flow").should.be.true();
});
});
it('should store global property to external context storage',function() {
Context.init({contextStorage:contextStorage});
return Context.load().then(function(){
var context = Context.get("1","flow");
should.not.exist(context.global.get("#test.foo"));
context.global.set("#test.foo","test");
context.global.get("#test.foo");
context.global.keys("#test");
stubSet.calledWithExactly("global","foo","test").should.be.true();
stubGet.calledWithExactly("global","foo").should.be.true();
stubKeys.calledWithExactly("global").should.be.true();
});
});
it('should store data to the default context when non-existent context storage was specified', function() {
Context.init({contextStorage:contextDefaultStorage});
return Context.load().then(function(){
var context = Context.get("1","flow");
should.not.exist(context.get("#nonexist.foo"));
context.set("#nonexist.foo","test");
context.get("#nonexist.foo");
context.keys("#nonexist");
stubGet.called.should.be.false();
stubSet.called.should.be.false();
stubKeys.called.should.be.false();
stubSet2.calledWithExactly("1:flow","foo","test").should.be.true();
stubGet2.calledWithExactly("1:flow","foo").should.be.true();
stubKeys2.calledWithExactly("1:flow").should.be.true();
});
});
it('should use the default context', function() {
Context.init({contextStorage:contextDefaultStorage});
return Context.load().then(function(){
var context = Context.get("1","flow");
should.not.exist(context.get("#default.foo"));
context.set("#default.foo","default");
context.get("#default.foo");
context.keys("#default");
stubGet.called.should.be.false();
stubSet.called.should.be.false();
stubKeys.called.should.be.false();
stubSet2.calledWithExactly("1:flow","foo","default").should.be.true();
stubGet2.calledWithExactly("1:flow","foo").should.be.true();
stubKeys2.calledWithExactly("1:flow").should.be.true();
});
});
it('should use the alias of default context', function() {
Context.init({contextStorage:contextDefaultStorage});
return Context.load().then(function(){
var context = Context.get("1","flow");
should.not.exist(context.get("#.foo"));
context.set("#.foo","alias");
context.get("#.foo");
context.keys("#");
stubGet.called.should.be.false();
stubSet.called.should.be.false();
stubKeys.called.should.be.false();
stubSet2.calledWithExactly("1:flow","foo","alias").should.be.true();
stubGet2.calledWithExactly("1:flow","foo").should.be.true();
stubKeys2.calledWithExactly("1:flow").should.be.true();
});
});
it('should throw an error using undefined storage for local context', function(done) {
Context.init({contextStorage:contextStorage});
Context.load().then(function(){
var context = Context.get("1","flow");
context.get("#nonexist.local");
should.fail(null, null, "An error was not thrown using undefined storage for local context");
}).catch(function(err) {
if (err.name === "ContextError") {
done();
} else {
done(err);
} }
});
});
it('should throw an error using undefined storage for flow context', function(done) {
Context.init({contextStorage:contextStorage});
Context.load().then(function(){
var context = Context.get("1","flow");
context.flow.set("#nonexist.flow");
should.fail(null, null, "An error was not thrown using undefined storage for flow context");
}).catch(function(err) {
if (err.name === "ContextError") {
done();
} else {
done(err);
}
});
});
});
describe('key name',function() { describe('key name',function() {
var memoryStorage = {
memory: {
module: "memory"
}
};
beforeEach(function() { beforeEach(function() {
Context.init({contextStorage:memoryStorage}); Context.init({contextStorage:{memory:{module:"memory"}}});
Context.load(); return Context.load().then(function(){
context = Context.get("1","flow"); context = Context.get("1","flow");
}); });
});
afterEach(function() { afterEach(function() {
Context.clean({allNodes:{}}); Context.clean({allNodes:{}});
return Context.close();
}); });
it('should work correctly with the valid key name',function() { it('should work correctly with the valid key name',function() {
context.set("#memory.azAZ09#_","valid"); context.set("#memory.azAZ09#_","valid");
@ -222,192 +426,6 @@ describe('context', function() {
}).should.throw(); }).should.throw();
}); });
}); });
describe('if external context storage exists',function() {
var contextDefaultStorage={
default: "test",
test:{
module: function(config){
function Test(){}
Test.prototype.get = stubGet;
Test.prototype.set = stubSet;
Test.prototype.keys = stubKeys;
Test.prototype.delete = stubDelete;
return new Test(config);
},
config:{}
}
};
it('should store local property to external context storage',function() {
initializeContext();
should.not.exist(context.get("#test.foo"));
context.set("#test.foo","test");
context.get("#test.foo");
context.keys("#test");
stubGet.called.should.be.true();
stubSet.called.should.be.true();
stubKeys.called.should.be.true();
});
it('should store flow property to external context storage',function() {
initializeContext();
should.not.exist(context.flow.get("#test.foo"));
context.flow.set("#test.foo","test");
context.flow.get("#test.foo");
context.flow.keys("#test");
stubGet.called.should.be.true();
stubSet.called.should.be.true();
stubKeys.called.should.be.true();
});
it('should store global property to external context storage',function() {
initializeContext();
should.not.exist(context.global.get("#test.foo"));
context.global.set("#test.foo","test");
context.global.get("#test.foo");
context.global.keys("#test");
stubGet.called.should.be.true();
stubSet.called.should.be.true();
stubKeys.called.should.be.true();
});
it('should store data when non-existent context storage was specified', function() {
Context.init({contextStorage:contextDefaultStorage});
Context.load();
context = Context.get("1","flow");
should.not.exist(context.get("#nonexist.foo"));
context.set("#nonexist.foo","test");
context.get("#nonexist.foo");
context.keys("#nonexist");
stubGet.called.should.be.true();
stubSet.called.should.be.true();
stubKeys.called.should.be.true();
});
it('should use the default context', function() {
Context.init({contextStorage:contextDefaultStorage});
Context.load();
context = Context.get("1","flow");
should.not.exist(context.get("#default.foo"));
context.set("#default.foo","default");
context.get("#default.foo");
context.keys("#default");
stubGet.called.should.be.true();
stubSet.called.should.be.true();
stubKeys.called.should.be.true();
});
it('should use the alias of default context', function() {
Context.init({contextStorage:contextDefaultStorage});
Context.load();
context = Context.get("1","flow");
should.not.exist(context.get("#.foo"));
context.set("#.foo","alias");
context.get("#.foo");
context.keys("#");
stubGet.called.should.be.true();
stubSet.called.should.be.true();
stubKeys.called.should.be.true();
});
it('should load memory module', function(done) {
Context.init({ contextStorage: { _: {}}});
try {
Context.load();
context.set("#_.foo","mem1");
context.get("#_.foo").should.eql("mem1");
var keys = context.keys("#_");
keys.should.have.length(1);
keys[0].should.eql("foo");
done();
} catch (err) {
done(err);
}
});
it('should load localfilesystem module', function(done) {
Context.init({contextStorage:{ file:{module:"localfilesystem"} }});
try {
Context.load();
done();
} catch (err) {
done(err);
}
});
it('should accept special storage name', function(done) {
Context.init({
contextStorage:{
"#%&":{module:"memory"},
\u3042:{module:"memory"},
1:{module:"memory"},
}
});
try {
Context.load();
context.set("##%&.sign","sign1");
context.get("##%&.sign").should.eql("sign1");
context.set("#\u3042.file2","file2");
context.get("#\u3042.file2").should.eql("file2");
context.set("#1.num","num3");
context.get("#1.num").should.eql("num3");
done();
} catch (err) {
done(err);
}
});
});
describe('if external context storage does not exist',function() {
it('should throw an error using undefined storage for local context', function(done) {
initializeContext();
try {
context.get("#nonexist.local");
should.fail(null, null, "An error was not thrown using undefined storage for local context");
} catch (err) {
if (err.name === "ContextError") {
done();
} else {
done(err);
}
}
});
it('should throw an error using undefined storage for flow context', function(done) {
initializeContext();
try {
context.flow.set("#nonexist.flow");
should.fail(null, null, "An error was not thrown using undefined storage for flow context");
} catch (err) {
if (err.name === "ContextError") {
done();
} else {
done(err);
}
}
});
it('should fail when using invalid default context', function() {
Context.init({contextStorage:{default:"noexist"}});
(function() {
Context.load();
}).should.throw();
});
it('should store data on memory when contextStorage is not defined', function() {
Context.init({});
Context.load();
context = Context.get("1","flow");
context.set("#nonexist.key1", "val1");
context.get("#nonexist.key1").should.eql("val1");
context.flow.set("#nonexist.key2", "val2");
context.flow.get("#nonexist.key2").should.eql("val2");
context.global.set("#nonexist.key1", "val3");
context.global.get("#nonexist.key1").should.eql("val3");
});
it('should fail for the storage with no module', function() {
Context.init({ contextStorage: { test: {}}});
(function() {
Context.load();
}).should.throw();
});
it('should fail to load non-existent module', function() {
Context.init({contextStorage:{ file:{module:"nonexistent"} }});
(function() {
Context.load();
}).should.throw();
});
});
}); });
describe('#parseKey()', function() { describe('#parseKey()', function() {

View File

@ -17,6 +17,7 @@
var should = require('should'); var should = require('should');
var fs = require('fs-extra'); var fs = require('fs-extra');
var path = require("path"); var path = require("path");
var when = require("when");
var LocalFileSystem = require('../../../../../red/runtime/nodes/context/localfilesystem'); var LocalFileSystem = require('../../../../../red/runtime/nodes/context/localfilesystem');
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context")); var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
@ -26,11 +27,12 @@ describe('localfilesystem',function() {
beforeEach(function() { beforeEach(function() {
context = LocalFileSystem({dir: resourcesDir}); context = LocalFileSystem({dir: resourcesDir});
return context.open();
}); });
afterEach(function(done) { afterEach(function() {
fs.remove(resourcesDir).then(function(result){ return context.close().then(function(){
return done(result); return fs.remove(resourcesDir);
}); });
}); });