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:
parent
28d05e2449
commit
7185bcd51f
@ -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 = {
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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){
|
||||||
|
@ -219,5 +219,6 @@ module.exports = {
|
|||||||
getCredentialKeyType: credentials.getKeyType,
|
getCredentialKeyType: credentials.getKeyType,
|
||||||
|
|
||||||
// Contexts
|
// Contexts
|
||||||
loadContextsPlugin: context.load
|
loadContextsPlugin: context.load,
|
||||||
|
closeContextsPlugin: context.close
|
||||||
};
|
};
|
||||||
|
@ -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();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -16,18 +16,18 @@
|
|||||||
|
|
||||||
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");
|
||||||
|
|
||||||
describe('context', function() {
|
describe('context', function() {
|
||||||
describe('localmemory',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() {
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user