mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge branch '0.19' into context-tab
This commit is contained in:
commit
c0870c5694
@ -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()) {
|
||||||
@ -229,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 = {
|
||||||
|
@ -155,5 +155,13 @@
|
|||||||
"readme": "### About\n\nThis is your project's README.md file. It helps users understand what your\nproject does, how to use it and anything else they may need to know."
|
"readme": "### About\n\nThis is your project's README.md file. It helps users understand what your\nproject does, how to use it and anything else they may need to know."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"context": {
|
||||||
|
"error-module-not-loaded": "'__module__' could not be loaded",
|
||||||
|
"error-module-not-defined": "'module' is not defined in '__storage__' of settings.contextStorage",
|
||||||
|
"error-invalid-default-module": "Invalid storage '__storage__' is specified as a default storage",
|
||||||
|
"error-use-undefined-storage": "Undefined storage '__storage__' is specified"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -105,12 +105,12 @@ Node.prototype.close = function(removed) {
|
|||||||
if (promises.length > 0) {
|
if (promises.length > 0) {
|
||||||
return when.settle(promises).then(function() {
|
return when.settle(promises).then(function() {
|
||||||
if (this._context) {
|
if (this._context) {
|
||||||
context.delete(this._alias||this.id,this.z);
|
return context.delete(this._alias||this.id,this.z);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (this._context) {
|
if (this._context) {
|
||||||
context.delete(this._alias||this.id,this.z);
|
return context.delete(this._alias||this.id,this.z);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
|
||||||
*
|
|
||||||
* 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 clone = require("clone");
|
|
||||||
var when = require("when");
|
|
||||||
var util = require("../util");
|
|
||||||
|
|
||||||
function createContext(id,seed) {
|
|
||||||
var data = seed || {};
|
|
||||||
var obj = seed || {};
|
|
||||||
obj.get = function get(key) {
|
|
||||||
return util.getMessageProperty(data,key);
|
|
||||||
};
|
|
||||||
obj.set = function set(key, value) {
|
|
||||||
util.setMessageProperty(data,key,value);
|
|
||||||
}
|
|
||||||
obj.keys = function() {
|
|
||||||
var keysData = Object.keys(data);
|
|
||||||
if (seed == null) {
|
|
||||||
return keysData;
|
|
||||||
} else {
|
|
||||||
return keysData.filter(function (key) {
|
|
||||||
return key !== "set" && key !== "get" && key !== "keys";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
var contexts = {};
|
|
||||||
var globalContext = null;
|
|
||||||
|
|
||||||
function getContext(localId,flowId) {
|
|
||||||
var contextId = localId;
|
|
||||||
if (flowId) {
|
|
||||||
contextId = localId+":"+flowId;
|
|
||||||
}
|
|
||||||
if (contexts.hasOwnProperty(contextId)) {
|
|
||||||
return contexts[contextId];
|
|
||||||
}
|
|
||||||
var newContext = createContext(contextId);
|
|
||||||
if (flowId) {
|
|
||||||
newContext.flow = getContext(flowId);
|
|
||||||
}
|
|
||||||
if (globalContext) {
|
|
||||||
newContext.global = globalContext;
|
|
||||||
}
|
|
||||||
contexts[contextId] = newContext;
|
|
||||||
return newContext;
|
|
||||||
}
|
|
||||||
function deleteContext(id,flowId) {
|
|
||||||
var contextId = id;
|
|
||||||
if (flowId) {
|
|
||||||
contextId = id+":"+flowId;
|
|
||||||
}
|
|
||||||
delete contexts[contextId];
|
|
||||||
}
|
|
||||||
function clean(flowConfig) {
|
|
||||||
var activeIds = {};
|
|
||||||
var contextId;
|
|
||||||
var node;
|
|
||||||
for (var id in contexts) {
|
|
||||||
if (contexts.hasOwnProperty(id) && id !== "global") {
|
|
||||||
var idParts = id.split(":");
|
|
||||||
if (!flowConfig.allNodes.hasOwnProperty(idParts[0])) {
|
|
||||||
delete contexts[id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = {
|
|
||||||
init: function(settings) {
|
|
||||||
globalContext = createContext("global",settings.functionGlobalContext || {});
|
|
||||||
contexts['global'] = globalContext;
|
|
||||||
},
|
|
||||||
get: getContext,
|
|
||||||
delete: deleteContext,
|
|
||||||
clean:clean
|
|
||||||
};
|
|
233
red/runtime/nodes/context/index.js
Normal file
233
red/runtime/nodes/context/index.js
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* 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 clone = require("clone");
|
||||||
|
var log = require("../../log");
|
||||||
|
var memory = require("./memory");
|
||||||
|
|
||||||
|
var settings;
|
||||||
|
var contexts = {};
|
||||||
|
var globalContext = null;
|
||||||
|
var externalContexts = {};
|
||||||
|
var noContextStorage = true;
|
||||||
|
|
||||||
|
function init(_settings) {
|
||||||
|
settings = _settings;
|
||||||
|
externalContexts = {};
|
||||||
|
|
||||||
|
// init memory plugin
|
||||||
|
var seed = settings.functionGlobalContext || {};
|
||||||
|
externalContexts["_"] = memory();
|
||||||
|
externalContexts["_"].setGlobalContext(seed);
|
||||||
|
globalContext = createContext("global",seed);
|
||||||
|
contexts['global'] = globalContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
function load() {
|
||||||
|
// load & init plugins in settings.contextStorage
|
||||||
|
var plugins = settings.contextStorage;
|
||||||
|
var isAlias = false;
|
||||||
|
if (plugins) {
|
||||||
|
var promises = [];
|
||||||
|
noContextStorage = false;
|
||||||
|
for(var pluginName in plugins){
|
||||||
|
if(pluginName === "_"){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(pluginName === "default" && typeof plugins[pluginName] === "string"){
|
||||||
|
isAlias = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var plugin;
|
||||||
|
if(plugins[pluginName].hasOwnProperty("module")){
|
||||||
|
var config = plugins[pluginName].config || {};
|
||||||
|
copySettings(config, settings);
|
||||||
|
if(typeof plugins[pluginName].module === "string") {
|
||||||
|
try{
|
||||||
|
plugin = require("./"+plugins[pluginName].module);
|
||||||
|
}catch(err){
|
||||||
|
return Promise.reject(new Error(log._("context.error-module-not-loaded", {module:plugins[pluginName].module})));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
plugin = plugins[pluginName].module;
|
||||||
|
}
|
||||||
|
externalContexts[pluginName] = plugin(config);
|
||||||
|
}else{
|
||||||
|
return Promise.reject(new Error(log._("context.error-module-not-defined", {storage:pluginName})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(var plugin in externalContexts){
|
||||||
|
if(externalContexts.hasOwnProperty(plugin)){
|
||||||
|
promises.push(externalContexts[plugin].open());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(isAlias){
|
||||||
|
if(externalContexts.hasOwnProperty(plugins["default"])){
|
||||||
|
externalContexts["default"] = externalContexts[plugins["default"]];
|
||||||
|
}else{
|
||||||
|
return Promise.reject(new Error(log._("context.error-invalid-default-module", {storage:plugins["default"]})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
} else {
|
||||||
|
noContextStorage = true;
|
||||||
|
return externalContexts["_"].open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copySettings(config, settings){
|
||||||
|
var copy = ["userDir"]
|
||||||
|
config.settings = {};
|
||||||
|
copy.forEach(function(setting){
|
||||||
|
config.settings[setting] = clone(settings[setting]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContextStorage(storage) {
|
||||||
|
if (externalContexts.hasOwnProperty(storage)) {
|
||||||
|
return externalContexts[storage];
|
||||||
|
} else if (externalContexts.hasOwnProperty("default")) {
|
||||||
|
return externalContexts["default"];
|
||||||
|
} else {
|
||||||
|
var contextError = new Error(log._("context.error-use-undefined-storage", {storage:storage}));
|
||||||
|
contextError.name = "ContextError";
|
||||||
|
throw contextError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createContext(id,seed) {
|
||||||
|
var scope = id;
|
||||||
|
var obj = seed || {};
|
||||||
|
|
||||||
|
obj.get = function(key, storage, callback) {
|
||||||
|
var context;
|
||||||
|
if (!storage && !callback) {
|
||||||
|
context = externalContexts["_"];
|
||||||
|
} else {
|
||||||
|
if (typeof storage === 'function') {
|
||||||
|
callback = storage;
|
||||||
|
storage = "default";
|
||||||
|
}
|
||||||
|
if (typeof callback !== 'function'){
|
||||||
|
throw new Error("Callback must be a function");
|
||||||
|
}
|
||||||
|
context = getContextStorage(storage);
|
||||||
|
}
|
||||||
|
return context.get(scope, key, callback);
|
||||||
|
};
|
||||||
|
obj.set = function(key, value, storage, callback) {
|
||||||
|
var context;
|
||||||
|
if (!storage && !callback) {
|
||||||
|
context = externalContexts["_"];
|
||||||
|
} else {
|
||||||
|
if (typeof storage === 'function') {
|
||||||
|
callback = storage;
|
||||||
|
storage = "default";
|
||||||
|
}
|
||||||
|
if (callback && typeof callback !== 'function') {
|
||||||
|
throw new Error("Callback must be a function");
|
||||||
|
}
|
||||||
|
context = getContextStorage(storage);
|
||||||
|
}
|
||||||
|
context.set(scope, key, value, callback);
|
||||||
|
};
|
||||||
|
obj.keys = function(storage, callback) {
|
||||||
|
var context;
|
||||||
|
if (!storage && !callback) {
|
||||||
|
context = externalContexts["_"];
|
||||||
|
} else {
|
||||||
|
if (typeof storage === 'function') {
|
||||||
|
callback = storage;
|
||||||
|
storage = "default";
|
||||||
|
}
|
||||||
|
if (typeof callback !== 'function') {
|
||||||
|
throw new Error("Callback must be a function");
|
||||||
|
}
|
||||||
|
context = getContextStorage(storage);
|
||||||
|
}
|
||||||
|
return context.keys(scope, callback);
|
||||||
|
};
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContext(localId,flowId) {
|
||||||
|
var contextId = localId;
|
||||||
|
if (flowId) {
|
||||||
|
contextId = localId+":"+flowId;
|
||||||
|
}
|
||||||
|
if (contexts.hasOwnProperty(contextId)) {
|
||||||
|
return contexts[contextId];
|
||||||
|
}
|
||||||
|
var newContext = createContext(contextId);
|
||||||
|
if (flowId) {
|
||||||
|
newContext.flow = getContext(flowId);
|
||||||
|
}
|
||||||
|
if (globalContext) {
|
||||||
|
newContext.global = globalContext;
|
||||||
|
}
|
||||||
|
contexts[contextId] = newContext;
|
||||||
|
return newContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteContext(id,flowId) {
|
||||||
|
if(noContextStorage){
|
||||||
|
var contextId = id;
|
||||||
|
if (flowId) {
|
||||||
|
contextId = id+":"+flowId;
|
||||||
|
}
|
||||||
|
delete contexts[contextId];
|
||||||
|
return externalContexts["_"].delete(contextId);
|
||||||
|
}else{
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clean(flowConfig) {
|
||||||
|
var promises = [];
|
||||||
|
for(var plugin in externalContexts){
|
||||||
|
if(externalContexts.hasOwnProperty(plugin)){
|
||||||
|
promises.push(externalContexts[plugin].clean(Object.keys(flowConfig.allNodes)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var id in contexts) {
|
||||||
|
if (contexts.hasOwnProperty(id) && id !== "global") {
|
||||||
|
var idParts = id.split(":");
|
||||||
|
if (!flowConfig.allNodes.hasOwnProperty(idParts[0])) {
|
||||||
|
delete contexts[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
var promises = [];
|
||||||
|
for(var plugin in externalContexts){
|
||||||
|
if(externalContexts.hasOwnProperty(plugin)){
|
||||||
|
promises.push(externalContexts[plugin].close());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init: init,
|
||||||
|
load: load,
|
||||||
|
get: getContext,
|
||||||
|
delete: deleteContext,
|
||||||
|
clean: clean,
|
||||||
|
close: close
|
||||||
|
};
|
164
red/runtime/nodes/context/localfilesystem.js
Normal file
164
red/runtime/nodes/context/localfilesystem.js
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* 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 fs = require('fs-extra');
|
||||||
|
var path = require("path");
|
||||||
|
var util = require("../../util");
|
||||||
|
|
||||||
|
function getStoragePath(storageBaseDir, scope) {
|
||||||
|
if(scope.indexOf(":") === -1){
|
||||||
|
if(scope === "global"){
|
||||||
|
return path.join(storageBaseDir,"global",scope);
|
||||||
|
}else{ // scope:flow
|
||||||
|
return path.join(storageBaseDir,scope,"flow");
|
||||||
|
}
|
||||||
|
}else{ // scope:local
|
||||||
|
var ids = scope.split(":")
|
||||||
|
return path.join(storageBaseDir,ids[1],ids[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBasePath(config) {
|
||||||
|
var base = config.base || "contexts";
|
||||||
|
var storageBaseDir;
|
||||||
|
if (!config.dir) {
|
||||||
|
if(config.settings && config.settings.userDir){
|
||||||
|
storageBaseDir = path.join(config.settings.userDir, base);
|
||||||
|
}else{
|
||||||
|
try {
|
||||||
|
fs.statSync(path.join(process.env.NODE_RED_HOME,".config.json"));
|
||||||
|
storageBaseDir = path.join(process.env.NODE_RED_HOME, base);
|
||||||
|
} catch(err) {
|
||||||
|
try {
|
||||||
|
// Consider compatibility for older versions
|
||||||
|
if (process.env.HOMEPATH) {
|
||||||
|
fs.statSync(path.join(process.env.HOMEPATH,".node-red",".config.json"));
|
||||||
|
storageBaseDir = path.join(process.env.HOMEPATH, ".node-red", base);
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
}
|
||||||
|
if (!storageBaseDir) {
|
||||||
|
storageBaseDir = path.join(process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH || process.env.NODE_RED_HOME,".node-red", base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
storageBaseDir = path.join(config.dir, base);
|
||||||
|
}
|
||||||
|
return storageBaseDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadFile(storagePath){
|
||||||
|
return fs.pathExists(storagePath).then(function(exists){
|
||||||
|
if(exists === true){
|
||||||
|
return fs.readFile(storagePath, "utf8");
|
||||||
|
}else{
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
}).catch(function(err){
|
||||||
|
throw Promise.reject(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function LocalFileSystem(config){
|
||||||
|
this.config = config;
|
||||||
|
this.storageBaseDir = getBasePath(this.config);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFileSystem.prototype.open = function(){
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFileSystem.prototype.close = function(){
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFileSystem.prototype.get = function(scope, key, callback) {
|
||||||
|
if(typeof callback !== "function"){
|
||||||
|
throw new Error("Callback must be a function");
|
||||||
|
}
|
||||||
|
var storagePath = getStoragePath(this.storageBaseDir ,scope);
|
||||||
|
loadFile(storagePath + ".json").then(function(data){
|
||||||
|
if(data){
|
||||||
|
callback(null, util.getMessageProperty(JSON.parse(data),key));
|
||||||
|
}else{
|
||||||
|
callback(null, undefined);
|
||||||
|
}
|
||||||
|
}).catch(function(err){
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
LocalFileSystem.prototype.set =function(scope, key, value, callback) {
|
||||||
|
var storagePath = getStoragePath(this.storageBaseDir ,scope);
|
||||||
|
loadFile(storagePath + ".json").then(function(data){
|
||||||
|
var obj = data ? JSON.parse(data) : {}
|
||||||
|
util.setMessageProperty(obj,key,value);
|
||||||
|
return fs.outputFile(storagePath + ".json", JSON.stringify(obj, undefined, 4), "utf8");
|
||||||
|
}).then(function(){
|
||||||
|
if(typeof callback === "function"){
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
|
}).catch(function(err){
|
||||||
|
if(typeof callback === "function"){
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
LocalFileSystem.prototype.keys = function(scope, callback){
|
||||||
|
if(typeof callback !== "function"){
|
||||||
|
throw new Error("Callback must be a function");
|
||||||
|
}
|
||||||
|
var storagePath = getStoragePath(this.storageBaseDir ,scope);
|
||||||
|
loadFile(storagePath + ".json").then(function(data){
|
||||||
|
if(data){
|
||||||
|
callback(null, Object.keys(JSON.parse(data)));
|
||||||
|
}else{
|
||||||
|
callback(null, []);
|
||||||
|
}
|
||||||
|
}).catch(function(err){
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
LocalFileSystem.prototype.delete = function(scope){
|
||||||
|
var storagePath = getStoragePath(this.storageBaseDir ,scope);
|
||||||
|
return fs.remove(storagePath + ".json");
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFileSystem.prototype.clean = function(activeNodes){
|
||||||
|
var self = this;
|
||||||
|
return fs.readdir(self.storageBaseDir).then(function(dirs){
|
||||||
|
return Promise.all(dirs.reduce(function(result, item){
|
||||||
|
if(item !== "global" && activeNodes.indexOf(item) === -1){
|
||||||
|
result.push(fs.remove(path.join(self.storageBaseDir,item)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},[]));
|
||||||
|
}).catch(function(err){
|
||||||
|
if(err.code == 'ENOENT') {
|
||||||
|
return Promise.resolve();
|
||||||
|
}else{
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function(config){
|
||||||
|
return new LocalFileSystem(config);
|
||||||
|
};
|
||||||
|
|
118
red/runtime/nodes/context/memory.js
Normal file
118
red/runtime/nodes/context/memory.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* 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 util = require("../../util");
|
||||||
|
|
||||||
|
function Memory(config){
|
||||||
|
this.data = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Memory.prototype.open = function(){
|
||||||
|
return Promise.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
Memory.prototype.close = function(){
|
||||||
|
return Promise.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
Memory.prototype.get = function(scope, key, callback) {
|
||||||
|
var value;
|
||||||
|
try{
|
||||||
|
if(this.data[scope]){
|
||||||
|
value = util.getMessageProperty(this.data[scope], key);
|
||||||
|
}
|
||||||
|
}catch(err){
|
||||||
|
if(callback){
|
||||||
|
callback(err);
|
||||||
|
}else{
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(callback){
|
||||||
|
callback(null, value);
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Memory.prototype.set =function(scope, key, value, callback) {
|
||||||
|
if(!this.data[scope]){
|
||||||
|
this.data[scope] = {};
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
util.setMessageProperty(this.data[scope],key,value);
|
||||||
|
}catch(err){
|
||||||
|
if(callback){
|
||||||
|
callback(err);
|
||||||
|
}else{
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(callback){
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Memory.prototype.keys = function(scope, callback){
|
||||||
|
var values = [];
|
||||||
|
try{
|
||||||
|
if(this.data[scope]){
|
||||||
|
if (scope !== "global") {
|
||||||
|
values = Object.keys(this.data[scope]);
|
||||||
|
} else {
|
||||||
|
values = Object.keys(this.data[scope]).filter(function (key) {
|
||||||
|
return key !== "set" && key !== "get" && key !== "keys";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(err){
|
||||||
|
if(callback){
|
||||||
|
callback(err);
|
||||||
|
}else{
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(callback){
|
||||||
|
callback(null, values);
|
||||||
|
} else {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Memory.prototype.delete = function(scope){
|
||||||
|
delete this.data[scope];
|
||||||
|
return Promise.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
Memory.prototype.clean = function(activeNodes){
|
||||||
|
for(var id in this.data){
|
||||||
|
if(this.data.hasOwnProperty(id) && id !== "global"){
|
||||||
|
var idParts = id.split(":");
|
||||||
|
if(activeNodes.indexOf(idParts[0]) === -1){
|
||||||
|
delete this.data[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
Memory.prototype.setGlobalContext= function(seed){
|
||||||
|
this.data["global"] = seed;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = function(config){
|
||||||
|
return new Memory(config);
|
||||||
|
};
|
@ -160,11 +160,12 @@ function setFlows(_config,type,muteLog,forceStart) {
|
|||||||
activeFlowConfig = newFlowConfig;
|
activeFlowConfig = newFlowConfig;
|
||||||
if (forceStart || started) {
|
if (forceStart || started) {
|
||||||
return stop(type,diff,muteLog).then(function() {
|
return stop(type,diff,muteLog).then(function() {
|
||||||
context.clean(activeFlowConfig);
|
return context.clean(activeFlowConfig).then(function() {
|
||||||
start(type,diff,muteLog).then(function() {
|
start(type,diff,muteLog).then(function() {
|
||||||
events.emit("runtime-event",{id:"runtime-deploy",payload:{revision:flowRevision},retain: true});
|
events.emit("runtime-event",{id:"runtime-deploy",payload:{revision:flowRevision},retain: true});
|
||||||
});
|
});
|
||||||
return flowRevision;
|
return flowRevision;
|
||||||
|
});
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,5 +218,9 @@ module.exports = {
|
|||||||
setCredentialSecret: credentials.setKey,
|
setCredentialSecret: credentials.setKey,
|
||||||
clearCredentials: credentials.clear,
|
clearCredentials: credentials.clear,
|
||||||
exportCredentials: credentials.export,
|
exportCredentials: credentials.export,
|
||||||
getCredentialKeyType: credentials.getKeyType
|
getCredentialKeyType: credentials.getKeyType,
|
||||||
|
|
||||||
|
// Contexts
|
||||||
|
loadContextsPlugin: context.load,
|
||||||
|
closeContextsPlugin: context.close
|
||||||
};
|
};
|
||||||
|
@ -79,6 +79,7 @@ describe("runtime", function() {
|
|||||||
var redNodesGetNodeList;
|
var redNodesGetNodeList;
|
||||||
var redNodesLoadFlows;
|
var redNodesLoadFlows;
|
||||||
var redNodesStartFlows;
|
var redNodesStartFlows;
|
||||||
|
var redNodesLoadContextsPlugin;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
storageInit = sinon.stub(storage,"init",function(settings) {return when.resolve();});
|
storageInit = sinon.stub(storage,"init",function(settings) {return when.resolve();});
|
||||||
@ -91,6 +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() {return when.resolve()});
|
||||||
});
|
});
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
storageInit.restore();
|
storageInit.restore();
|
||||||
@ -104,6 +106,7 @@ describe("runtime", function() {
|
|||||||
redNodesCleanModuleList.restore();
|
redNodesCleanModuleList.restore();
|
||||||
redNodesLoadFlows.restore();
|
redNodesLoadFlows.restore();
|
||||||
redNodesStartFlows.restore();
|
redNodesStartFlows.restore();
|
||||||
|
redNodesLoadContextsPlugin.restore();
|
||||||
});
|
});
|
||||||
it("reports errored/missing modules",function(done) {
|
it("reports errored/missing modules",function(done) {
|
||||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) {
|
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) {
|
||||||
@ -183,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; });
|
||||||
@ -214,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();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
479
test/red/runtime/nodes/context/index_spec.js
Normal file
479
test/red/runtime/nodes/context/index_spec.js
Normal file
@ -0,0 +1,479 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* 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");
|
||||||
|
var sinon = require('sinon');
|
||||||
|
var path = require("path");
|
||||||
|
var Context = require("../../../../../red/runtime/nodes/context/index");
|
||||||
|
|
||||||
|
describe('context', function() {
|
||||||
|
describe('local memory',function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
Context.init({});
|
||||||
|
return Context.load();
|
||||||
|
});
|
||||||
|
afterEach(function() {
|
||||||
|
Context.clean({allNodes:{}});
|
||||||
|
return Context.close();
|
||||||
|
});
|
||||||
|
it('stores local property',function() {
|
||||||
|
var context1 = Context.get("1","flowA");
|
||||||
|
should.not.exist(context1.get("foo"));
|
||||||
|
context1.set("foo","test");
|
||||||
|
context1.get("foo").should.equal("test");
|
||||||
|
});
|
||||||
|
it('stores local property - creates parent properties',function() {
|
||||||
|
var context1 = Context.get("1","flowA");
|
||||||
|
context1.set("foo.bar","test");
|
||||||
|
context1.get("foo").should.eql({bar:"test"});
|
||||||
|
});
|
||||||
|
it('deletes local property',function() {
|
||||||
|
var context1 = Context.get("1","flowA");
|
||||||
|
context1.set("foo.abc.bar1","test1");
|
||||||
|
context1.set("foo.abc.bar2","test2");
|
||||||
|
context1.get("foo.abc").should.eql({bar1:"test1",bar2:"test2"});
|
||||||
|
context1.set("foo.abc.bar1",undefined);
|
||||||
|
context1.get("foo.abc").should.eql({bar2:"test2"});
|
||||||
|
context1.set("foo.abc",undefined);
|
||||||
|
should.not.exist(context1.get("foo.abc"));
|
||||||
|
context1.set("foo",undefined);
|
||||||
|
should.not.exist(context1.get("foo"));
|
||||||
|
});
|
||||||
|
it('stores flow property',function() {
|
||||||
|
var context1 = Context.get("1","flowA");
|
||||||
|
should.not.exist(context1.flow.get("foo"));
|
||||||
|
context1.flow.set("foo","test");
|
||||||
|
context1.flow.get("foo").should.equal("test");
|
||||||
|
});
|
||||||
|
it('stores global property',function() {
|
||||||
|
var context1 = Context.get("1","flowA");
|
||||||
|
should.not.exist(context1.global.get("foo"));
|
||||||
|
context1.global.set("foo","test");
|
||||||
|
context1.global.get("foo").should.equal("test");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('keeps local context local', function() {
|
||||||
|
var context1 = Context.get("1","flowA");
|
||||||
|
var context2 = Context.get("2","flowA");
|
||||||
|
|
||||||
|
should.not.exist(context1.get("foo"));
|
||||||
|
should.not.exist(context2.get("foo"));
|
||||||
|
context1.set("foo","test");
|
||||||
|
|
||||||
|
context1.get("foo").should.equal("test");
|
||||||
|
should.not.exist(context2.get("foo"));
|
||||||
|
});
|
||||||
|
it('flow context accessible to all flow nodes', function() {
|
||||||
|
var context1 = Context.get("1","flowA");
|
||||||
|
var context2 = Context.get("2","flowA");
|
||||||
|
|
||||||
|
should.not.exist(context1.flow.get("foo"));
|
||||||
|
should.not.exist(context2.flow.get("foo"));
|
||||||
|
|
||||||
|
context1.flow.set("foo","test");
|
||||||
|
context1.flow.get("foo").should.equal("test");
|
||||||
|
context2.flow.get("foo").should.equal("test");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('flow context not shared to nodes on other flows', function() {
|
||||||
|
var context1 = Context.get("1","flowA");
|
||||||
|
var context2 = Context.get("2","flowB");
|
||||||
|
|
||||||
|
should.not.exist(context1.flow.get("foo"));
|
||||||
|
should.not.exist(context2.flow.get("foo"));
|
||||||
|
|
||||||
|
context1.flow.set("foo","test");
|
||||||
|
context1.flow.get("foo").should.equal("test");
|
||||||
|
should.not.exist(context2.flow.get("foo"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('global context shared to all nodes', function() {
|
||||||
|
var context1 = Context.get("1","flowA");
|
||||||
|
var context2 = Context.get("2","flowB");
|
||||||
|
|
||||||
|
should.not.exist(context1.global.get("foo"));
|
||||||
|
should.not.exist(context2.global.get("foo"));
|
||||||
|
|
||||||
|
context1.global.set("foo","test");
|
||||||
|
context1.global.get("foo").should.equal("test");
|
||||||
|
context2.global.get("foo").should.equal("test");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('deletes context',function() {
|
||||||
|
var context = Context.get("1","flowA");
|
||||||
|
should.not.exist(context.get("foo"));
|
||||||
|
context.set("foo","abc");
|
||||||
|
context.get("foo").should.equal("abc");
|
||||||
|
|
||||||
|
return Context.delete("1","flowA").then(function(){
|
||||||
|
context = Context.get("1","flowA");
|
||||||
|
should.not.exist(context.get("foo"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('enumerates context keys', function() {
|
||||||
|
var context = Context.get("1","flowA");
|
||||||
|
|
||||||
|
var keys = context.keys();
|
||||||
|
keys.should.be.an.Array();
|
||||||
|
keys.should.be.empty();
|
||||||
|
|
||||||
|
context.set("foo","bar");
|
||||||
|
keys = context.keys();
|
||||||
|
keys.should.have.length(1);
|
||||||
|
keys[0].should.equal("foo");
|
||||||
|
|
||||||
|
context.set("abc.def","bar");
|
||||||
|
keys = context.keys();
|
||||||
|
keys.should.have.length(2);
|
||||||
|
keys[1].should.equal("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enumerate only context keys when GlobalContext was given', function() {
|
||||||
|
Context.init({functionGlobalContext: {foo:"bar"}});
|
||||||
|
return Context.load().then(function(){
|
||||||
|
var context = Context.get("1","flowA");
|
||||||
|
var keys = context.global.keys();
|
||||||
|
keys.should.have.length(1);
|
||||||
|
keys[0].should.equal("foo");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('external context storage',function() {
|
||||||
|
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
|
||||||
|
var sandbox = sinon.sandbox.create();
|
||||||
|
var stubGet = sandbox.stub();
|
||||||
|
var stubSet = sandbox.stub();
|
||||||
|
var stubKeys = sandbox.stub();
|
||||||
|
var stubDelete = sandbox.stub().returns(Promise.resolve());
|
||||||
|
var stubClean = sandbox.stub().returns(Promise.resolve());
|
||||||
|
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().returns(Promise.resolve());
|
||||||
|
var stubClean2 = sandbox.stub().returns(Promise.resolve());
|
||||||
|
var stubOpen2 = sandbox.stub().returns(Promise.resolve());
|
||||||
|
var stubClose2 = sandbox.stub().returns(Promise.resolve());
|
||||||
|
var testPlugin = function(config){
|
||||||
|
function Test(){}
|
||||||
|
Test.prototype.get = stubGet;
|
||||||
|
Test.prototype.set = stubSet;
|
||||||
|
Test.prototype.keys = stubKeys;
|
||||||
|
Test.prototype.delete = stubDelete;
|
||||||
|
Test.prototype.clean = stubClean;
|
||||||
|
Test.prototype.open = stubOpen;
|
||||||
|
Test.prototype.close = stubClose;
|
||||||
|
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.clean = stubClean2;
|
||||||
|
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:{}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var contextAlias={
|
||||||
|
default: "test",
|
||||||
|
test:{
|
||||||
|
module: testPlugin,
|
||||||
|
config:{}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
sandbox.reset();
|
||||||
|
return Context.clean({allNodes:{}}).then(function(){
|
||||||
|
return Context.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('load modules',function(){
|
||||||
|
it('should call open()', function() {
|
||||||
|
Context.init({contextStorage:contextDefaultStorage});
|
||||||
|
return Context.load().then(function(){
|
||||||
|
stubOpen.called.should.be.true();
|
||||||
|
stubOpen2.called.should.be.true();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should load memory module', function() {
|
||||||
|
Context.init({contextStorage:{memory:{module:"memory"}}});
|
||||||
|
return Context.load();
|
||||||
|
});
|
||||||
|
it('should load localfilesystem module', function() {
|
||||||
|
Context.init({contextStorage:{file:{module:"localfilesystem",config:{dir:resourcesDir}}}});
|
||||||
|
return Context.load();
|
||||||
|
});
|
||||||
|
it('should accept special storage name', function(done) {
|
||||||
|
Context.init({
|
||||||
|
contextStorage:{
|
||||||
|
"#%&":{module:testPlugin},
|
||||||
|
\u3042:{module:testPlugin},
|
||||||
|
1:{module:testPlugin},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Context.load().then(function(){
|
||||||
|
var context = Context.get("1","flow");
|
||||||
|
var cb = function(){done("An error occurred")}
|
||||||
|
context.set("sign","sign1","#%&",cb);
|
||||||
|
context.set("file","file2","\u3042",cb);
|
||||||
|
context.set("num","num3","1",cb);
|
||||||
|
stubSet.calledWithExactly("1:flow","sign","sign1",cb).should.be.true();
|
||||||
|
stubSet.calledWithExactly("1:flow","file","file2",cb).should.be.true();
|
||||||
|
stubSet.calledWithExactly("1:flow","num","num3",cb).should.be.true();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should ignore reserved storage name `_`', function(done) {
|
||||||
|
Context.init({contextStorage:{_:{module:testPlugin}}});
|
||||||
|
Context.load().then(function(){
|
||||||
|
var context = Context.get("1","flow");
|
||||||
|
var cb = function(){}
|
||||||
|
context.set("foo","bar","_",cb);
|
||||||
|
context.get("foo","_",cb);
|
||||||
|
context.keys("_",cb);
|
||||||
|
stubSet.called.should.be.false();
|
||||||
|
stubGet.called.should.be.false();
|
||||||
|
stubKeys.called.should.be.false();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
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('close modules',function(){
|
||||||
|
it('should call close()', function() {
|
||||||
|
Context.init({contextStorage:contextDefaultStorage});
|
||||||
|
return Context.load().then(function(){
|
||||||
|
return Context.close().then(function(){
|
||||||
|
stubClose.called.should.be.true();
|
||||||
|
stubClose2.called.should.be.true();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('store context',function() {
|
||||||
|
it('should store local property to external context storage',function(done) {
|
||||||
|
Context.init({contextStorage:contextStorage});
|
||||||
|
var cb = function(){done("An error occurred")}
|
||||||
|
Context.load().then(function(){
|
||||||
|
var context = Context.get("1","flow");
|
||||||
|
context.set("foo","bar","test",cb);
|
||||||
|
context.get("foo","test",cb);
|
||||||
|
context.keys("test",cb);
|
||||||
|
stubSet.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
|
||||||
|
stubGet.calledWithExactly("1:flow","foo",cb).should.be.true();
|
||||||
|
stubKeys.calledWithExactly("1:flow",cb).should.be.true();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should store flow property to external context storage',function(done) {
|
||||||
|
Context.init({contextStorage:contextStorage});
|
||||||
|
Context.load().then(function(){
|
||||||
|
var context = Context.get("1","flow");
|
||||||
|
var cb = function(){done("An error occurred")}
|
||||||
|
context.flow.set("foo","bar","test",cb);
|
||||||
|
context.flow.get("foo","test",cb);
|
||||||
|
context.flow.keys("test",cb);
|
||||||
|
stubSet.calledWithExactly("flow","foo","bar",cb).should.be.true();
|
||||||
|
stubGet.calledWithExactly("flow","foo",cb).should.be.true();
|
||||||
|
stubKeys.calledWithExactly("flow",cb).should.be.true();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should store global property to external context storage',function(done) {
|
||||||
|
Context.init({contextStorage:contextStorage});
|
||||||
|
Context.load().then(function(){
|
||||||
|
var context = Context.get("1","flow");
|
||||||
|
var cb = function(){done("An error occurred")}
|
||||||
|
context.global.set("foo","bar","test",cb);
|
||||||
|
context.global.get("foo","test",cb);
|
||||||
|
context.global.keys("test",cb);
|
||||||
|
stubSet.calledWithExactly("global","foo","bar",cb).should.be.true();
|
||||||
|
stubGet.calledWithExactly("global","foo",cb).should.be.true();
|
||||||
|
stubKeys.calledWithExactly("global",cb).should.be.true();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should store data to the default context when non-existent context storage was specified', function(done) {
|
||||||
|
Context.init({contextStorage:contextDefaultStorage});
|
||||||
|
Context.load().then(function(){
|
||||||
|
var context = Context.get("1","flow");
|
||||||
|
var cb = function(){done("An error occurred")}
|
||||||
|
context.set("foo","bar","nonexist",cb);
|
||||||
|
context.get("foo","nonexist",cb);
|
||||||
|
context.keys("nonexist",cb);
|
||||||
|
stubGet.called.should.be.false();
|
||||||
|
stubSet.called.should.be.false();
|
||||||
|
stubKeys.called.should.be.false();
|
||||||
|
stubSet2.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
|
||||||
|
stubGet2.calledWithExactly("1:flow","foo",cb).should.be.true();
|
||||||
|
stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should use the default context', function(done) {
|
||||||
|
Context.init({contextStorage:contextDefaultStorage});
|
||||||
|
Context.load().then(function(){
|
||||||
|
var context = Context.get("1","flow");
|
||||||
|
var cb = function(){done("An error occurred")}
|
||||||
|
context.set("foo","bar","defaultt",cb);
|
||||||
|
context.get("foo","default",cb);
|
||||||
|
context.keys("default",cb);
|
||||||
|
stubGet.called.should.be.false();
|
||||||
|
stubSet.called.should.be.false();
|
||||||
|
stubKeys.called.should.be.false();
|
||||||
|
stubSet2.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
|
||||||
|
stubGet2.calledWithExactly("1:flow","foo",cb).should.be.true();
|
||||||
|
stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should use the alias of default context', function(done) {
|
||||||
|
Context.init({contextStorage:contextDefaultStorage});
|
||||||
|
Context.load().then(function(){
|
||||||
|
var context = Context.get("1","flow");
|
||||||
|
var cb = function(){done("An error occurred")}
|
||||||
|
context.set("foo","alias",cb);
|
||||||
|
context.get("foo",cb);
|
||||||
|
context.keys(cb);
|
||||||
|
stubGet.called.should.be.false();
|
||||||
|
stubSet.called.should.be.false();
|
||||||
|
stubKeys.called.should.be.false();
|
||||||
|
stubSet2.calledWithExactly("1:flow","foo","alias",cb).should.be.true();
|
||||||
|
stubGet2.calledWithExactly("1:flow","foo",cb).should.be.true();
|
||||||
|
stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should use default as the alias of other context', function(done) {
|
||||||
|
Context.init({contextStorage:contextAlias});
|
||||||
|
Context.load().then(function(){
|
||||||
|
var context = Context.get("1","flow");
|
||||||
|
var cb = function(){done("An error occurred")}
|
||||||
|
context.set("foo","alias",cb);
|
||||||
|
context.get("foo",cb);
|
||||||
|
context.keys(cb);
|
||||||
|
stubSet.calledWithExactly("1:flow","foo","alias",cb).should.be.true();
|
||||||
|
stubGet.calledWithExactly("1:flow","foo",cb).should.be.true();
|
||||||
|
stubKeys.calledWithExactly("1:flow",cb).should.be.true();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
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");
|
||||||
|
var cb = function(){done("An error occurred")}
|
||||||
|
context.get("local","nonexist",cb);
|
||||||
|
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");
|
||||||
|
var cb = function(){done("An error occurred")}
|
||||||
|
context.flow.get("flow","nonexist",cb);
|
||||||
|
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('delete context',function(){
|
||||||
|
it('should not call delete() when external context storage is used', function() {
|
||||||
|
Context.init({contextStorage:contextDefaultStorage});
|
||||||
|
return Context.load().then(function(){
|
||||||
|
Context.get("flowA");
|
||||||
|
return Context.delete("flowA").then(function(){
|
||||||
|
stubDelete.called.should.be.false();
|
||||||
|
stubDelete2.called.should.be.false();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('clean context',function(){
|
||||||
|
it('should call clean()', function() {
|
||||||
|
Context.init({contextStorage:contextDefaultStorage});
|
||||||
|
return Context.load().then(function(){
|
||||||
|
return Context.clean({allNodes:{}}).then(function(){
|
||||||
|
stubClean.calledWithExactly([]).should.be.true();
|
||||||
|
stubClean2.calledWithExactly([]).should.be.true();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
378
test/red/runtime/nodes/context/localfilesystem_spec.js
Normal file
378
test/red/runtime/nodes/context/localfilesystem_spec.js
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* 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');
|
||||||
|
var fs = require('fs-extra');
|
||||||
|
var path = require("path");
|
||||||
|
var LocalFileSystem = require('../../../../../red/runtime/nodes/context/localfilesystem');
|
||||||
|
|
||||||
|
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
|
||||||
|
|
||||||
|
describe('localfilesystem',function() {
|
||||||
|
var context;
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
return fs.remove(resourcesDir);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
context = LocalFileSystem({dir: resourcesDir});
|
||||||
|
return context.open();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
return context.clean([]).then(function(){
|
||||||
|
return context.close().then(function(){
|
||||||
|
return fs.remove(resourcesDir);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#get/set',function() {
|
||||||
|
it('should store property',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo","test",function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.equal("test");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store property - creates parent properties',function(done) {
|
||||||
|
context.set("nodeX","foo.bar","test",function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.eql({bar:"test"});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete property',function(done) {
|
||||||
|
context.set("nodeX","foo.abc.bar1","test1",function(err){
|
||||||
|
context.set("nodeX","foo.abc.bar2","test2",function(err){
|
||||||
|
context.get("nodeX","foo.abc",function(err, value){
|
||||||
|
value.should.be.eql({bar1:"test1",bar2:"test2"});
|
||||||
|
context.set("nodeX","foo.abc.bar1",undefined,function(err){
|
||||||
|
context.get("nodeX","foo.abc",function(err, value){
|
||||||
|
value.should.be.eql({bar2:"test2"});
|
||||||
|
context.set("nodeX","foo.abc",undefined,function(err){
|
||||||
|
context.get("nodeX","foo.abc",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo",undefined,function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not shared context with other scope', function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo","testX",function(err){
|
||||||
|
context.set("nodeY","foo","testY",function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.equal("testX"),
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
value.should.be.equal("testY");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store string',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo","bar",function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.String();
|
||||||
|
value.should.be.equal("bar");
|
||||||
|
context.set("nodeX","foo","1",function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.String();
|
||||||
|
value.should.be.equal("1");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store number',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo",1,function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.Number();
|
||||||
|
value.should.be.equal(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store null',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo",null,function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should(value).be.null();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store boolean',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo",true,function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.Boolean().and.true();
|
||||||
|
context.set("nodeX","foo",false,function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.Boolean().and.false();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store object',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo",{obj:"bar"},function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.Object();
|
||||||
|
value.should.eql({obj:"bar"});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store array',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo",["a","b","c"],function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.Array();
|
||||||
|
value.should.eql(["a","b","c"]);
|
||||||
|
context.get("nodeX","foo[1]",function(err, value){
|
||||||
|
value.should.be.String();
|
||||||
|
value.should.equal("b");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store array of arrays',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo",[["a","b","c"],[1,2,3,4],[true,false]],function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.Array();
|
||||||
|
value.should.have.length(3);
|
||||||
|
value[0].should.have.length(3);
|
||||||
|
value[1].should.have.length(4);
|
||||||
|
value[2].should.have.length(2);
|
||||||
|
context.get("nodeX","foo[1]",function(err, value){
|
||||||
|
value.should.be.Array();
|
||||||
|
value.should.have.length(4);
|
||||||
|
value.should.be.eql([1,2,3,4]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store array of objects',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo",[{obj:"bar1"},{obj:"bar2"},{obj:"bar3"}],function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.Array();
|
||||||
|
value.should.have.length(3);
|
||||||
|
value[0].should.be.Object();
|
||||||
|
value[1].should.be.Object();
|
||||||
|
value[2].should.be.Object();
|
||||||
|
context.get("nodeX","foo[1]",function(err, value){
|
||||||
|
value.should.be.Object();
|
||||||
|
value.should.be.eql({obj:"bar2"});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#keys',function() {
|
||||||
|
it('should enumerate context keys', function(done) {
|
||||||
|
context.keys("nodeX",function(err, value){
|
||||||
|
value.should.be.an.Array();
|
||||||
|
value.should.be.empty();
|
||||||
|
context.set("nodeX","foo","bar",function(err){
|
||||||
|
context.keys("nodeX",function(err, value){
|
||||||
|
value.should.have.length(1);
|
||||||
|
value[0].should.equal("foo");
|
||||||
|
context.set("nodeX","abc.def","bar",function(err){
|
||||||
|
context.keys("nodeX",function(err, value){
|
||||||
|
value.should.have.length(2);
|
||||||
|
value[1].should.equal("abc");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enumerate context keys in each scopes', function(done) {
|
||||||
|
context.keys("nodeX",function(err, value){
|
||||||
|
value.should.be.an.Array();
|
||||||
|
value.should.be.empty();
|
||||||
|
context.keys("nodeY",function(err, value){
|
||||||
|
value.should.be.an.Array();
|
||||||
|
value.should.be.empty();
|
||||||
|
context.set("nodeX","foo","bar",function(err){
|
||||||
|
context.set("nodeY","hoge","piyo",function(err){
|
||||||
|
context.keys("nodeX",function(err, value){
|
||||||
|
value.should.have.length(1);
|
||||||
|
value[0].should.equal("foo");
|
||||||
|
context.keys("nodeY",function(err, value){
|
||||||
|
value.should.have.length(1);
|
||||||
|
value[0].should.equal("hoge");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#delete',function() {
|
||||||
|
it('should delete context',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo","testX",function(err){
|
||||||
|
context.set("nodeY","foo","testY",function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.equal("testX");
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
value.should.be.equal("testY");
|
||||||
|
context.delete("nodeX").then(function(){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
value.should.be.equal("testY");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#clean',function() {
|
||||||
|
it('should clean unnecessary context',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo","testX",function(err){
|
||||||
|
context.set("nodeY","foo","testY",function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.equal("testX");
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
value.should.be.equal("testY");
|
||||||
|
context.clean([]).then(function(){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not clean active context',function(done) {
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
context.set("nodeX","foo","testX",function(err){
|
||||||
|
context.set("nodeY","foo","testY",function(err){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.equal("testX");
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
value.should.be.equal("testY");
|
||||||
|
context.clean(["nodeX"]).then(function(){
|
||||||
|
context.get("nodeX","foo",function(err, value){
|
||||||
|
value.should.be.equal("testX");
|
||||||
|
context.get("nodeY","foo",function(err, value){
|
||||||
|
should.not.exist(value);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
179
test/red/runtime/nodes/context/memory_spec.js
Normal file
179
test/red/runtime/nodes/context/memory_spec.js
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* 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');
|
||||||
|
var Memory = require('../../../../../red/runtime/nodes/context/memory');
|
||||||
|
|
||||||
|
describe('memory',function() {
|
||||||
|
var context;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
context = Memory({});
|
||||||
|
return context.open();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
return context.clean([]).then(function(){
|
||||||
|
return context.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#get/set',function() {
|
||||||
|
it('should store property',function() {
|
||||||
|
should.not.exist(context.get("nodeX","foo"));
|
||||||
|
context.set("nodeX","foo","test");
|
||||||
|
context.get("nodeX","foo").should.equal("test");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store property - creates parent properties',function() {
|
||||||
|
context.set("nodeX","foo.bar","test");
|
||||||
|
context.get("nodeX","foo").should.eql({bar:"test"});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete property',function() {
|
||||||
|
context.set("nodeX","foo.abc.bar1","test1");
|
||||||
|
context.set("nodeX","foo.abc.bar2","test2");
|
||||||
|
context.get("nodeX","foo.abc").should.eql({bar1:"test1",bar2:"test2"});
|
||||||
|
context.set("nodeX","foo.abc.bar1",undefined);
|
||||||
|
context.get("nodeX","foo.abc").should.eql({bar2:"test2"});
|
||||||
|
context.set("nodeX","foo.abc",undefined);
|
||||||
|
should.not.exist(context.get("nodeX","foo.abc"));
|
||||||
|
context.set("nodeX","foo",undefined);
|
||||||
|
should.not.exist(context.get("nodeX","foo"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not shared context with other scope', function() {
|
||||||
|
should.not.exist(context.get("nodeX","foo"));
|
||||||
|
should.not.exist(context.get("nodeY","foo"));
|
||||||
|
context.set("nodeX","foo","testX");
|
||||||
|
context.set("nodeY","foo","testY");
|
||||||
|
|
||||||
|
context.get("nodeX","foo").should.equal("testX");
|
||||||
|
context.get("nodeY","foo").should.equal("testY");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#keys',function() {
|
||||||
|
it('should enumerate context keys', function() {
|
||||||
|
var keys = context.keys("nodeX");
|
||||||
|
keys.should.be.an.Array();
|
||||||
|
keys.should.be.empty();
|
||||||
|
|
||||||
|
context.set("nodeX","foo","bar");
|
||||||
|
keys = context.keys("nodeX");
|
||||||
|
keys.should.have.length(1);
|
||||||
|
keys[0].should.equal("foo");
|
||||||
|
|
||||||
|
context.set("nodeX","abc.def","bar");
|
||||||
|
keys = context.keys("nodeX");
|
||||||
|
keys.should.have.length(2);
|
||||||
|
keys[1].should.equal("abc");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enumerate context keys in each scopes', function() {
|
||||||
|
var keysX = context.keys("nodeX");
|
||||||
|
keysX.should.be.an.Array();
|
||||||
|
keysX.should.be.empty();
|
||||||
|
|
||||||
|
var keysY = context.keys("nodeY");
|
||||||
|
keysY.should.be.an.Array();
|
||||||
|
keysY.should.be.empty();
|
||||||
|
|
||||||
|
context.set("nodeX","foo","bar");
|
||||||
|
context.set("nodeY","hoge","piyo");
|
||||||
|
keysX = context.keys("nodeX");
|
||||||
|
keysX.should.have.length(1);
|
||||||
|
keysX[0].should.equal("foo");
|
||||||
|
|
||||||
|
keysY = context.keys("nodeY");
|
||||||
|
keysY.should.have.length(1);
|
||||||
|
keysY[0].should.equal("hoge");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enumerate only context keys when GlobalContext was given', function() {
|
||||||
|
var keys = context.keys("global");
|
||||||
|
keys.should.be.an.Array();
|
||||||
|
keys.should.be.empty();
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
foo: "bar"
|
||||||
|
}
|
||||||
|
context.setGlobalContext(data);
|
||||||
|
keys = context.keys("global");
|
||||||
|
keys.should.have.length(1);
|
||||||
|
keys[0].should.equal("foo");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#delete',function() {
|
||||||
|
it('should delete context',function() {
|
||||||
|
should.not.exist(context.get("nodeX","foo"));
|
||||||
|
should.not.exist(context.get("nodeY","foo"));
|
||||||
|
context.set("nodeX","foo","abc");
|
||||||
|
context.set("nodeY","foo","abc");
|
||||||
|
context.get("nodeX","foo").should.equal("abc");
|
||||||
|
context.get("nodeY","foo").should.equal("abc");
|
||||||
|
|
||||||
|
return context.delete("nodeX").then(function(){
|
||||||
|
should.not.exist(context.get("nodeX","foo"));
|
||||||
|
should.exist(context.get("nodeY","foo"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#clean',function() {
|
||||||
|
it('should clean unnecessary context',function() {
|
||||||
|
should.not.exist(context.get("nodeX","foo"));
|
||||||
|
should.not.exist(context.get("nodeY","foo"));
|
||||||
|
context.set("nodeX","foo","abc");
|
||||||
|
context.set("nodeY","foo","abc");
|
||||||
|
context.get("nodeX","foo").should.equal("abc");
|
||||||
|
context.get("nodeY","foo").should.equal("abc");
|
||||||
|
|
||||||
|
return context.clean([]).then(function(){
|
||||||
|
should.not.exist(context.get("nodeX","foo"));
|
||||||
|
should.not.exist(context.get("nodeY","foo"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should not clean active context',function() {
|
||||||
|
should.not.exist(context.get("nodeX","foo"));
|
||||||
|
should.not.exist(context.get("nodeY","foo"));
|
||||||
|
context.set("nodeX","foo","abc");
|
||||||
|
context.set("nodeY","foo","abc");
|
||||||
|
context.get("nodeX","foo").should.equal("abc");
|
||||||
|
context.get("nodeY","foo").should.equal("abc");
|
||||||
|
|
||||||
|
return context.clean(["nodeX"]).then(function(){
|
||||||
|
should.exist(context.get("nodeX","foo"));
|
||||||
|
should.not.exist(context.get("nodeY","foo"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#setGlobalContext',function() {
|
||||||
|
it('should initialize global context with argument', function() {
|
||||||
|
var keys = context.keys("global");
|
||||||
|
keys.should.be.an.Array();
|
||||||
|
keys.should.be.empty();
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
foo: "bar"
|
||||||
|
}
|
||||||
|
context.setGlobalContext(data);
|
||||||
|
context.get("global","foo").should.equal("bar");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,144 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
|
||||||
*
|
|
||||||
* 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");
|
|
||||||
var sinon = require('sinon');
|
|
||||||
var Context = require("../../../../red/runtime/nodes/context");
|
|
||||||
|
|
||||||
describe('context', function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
Context.init({});
|
|
||||||
});
|
|
||||||
afterEach(function() {
|
|
||||||
Context.clean({allNodes:{}});
|
|
||||||
});
|
|
||||||
it('stores local property',function() {
|
|
||||||
var context1 = Context.get("1","flowA");
|
|
||||||
should.not.exist(context1.get("foo"));
|
|
||||||
context1.set("foo","test");
|
|
||||||
context1.get("foo").should.eql("test");
|
|
||||||
});
|
|
||||||
it('stores local property - creates parent properties',function() {
|
|
||||||
var context1 = Context.get("1","flowA");
|
|
||||||
context1.set("foo.bar","test");
|
|
||||||
context1.get("foo").should.eql({bar:"test"});
|
|
||||||
});
|
|
||||||
it('deletes local property',function() {
|
|
||||||
var context1 = Context.get("1","flowA");
|
|
||||||
context1.set("foo.abc.bar1","test1");
|
|
||||||
context1.set("foo.abc.bar2","test2");
|
|
||||||
context1.get("foo.abc").should.eql({bar1:"test1",bar2:"test2"});
|
|
||||||
context1.set("foo.abc.bar1",undefined);
|
|
||||||
context1.get("foo.abc").should.eql({bar2:"test2"});
|
|
||||||
context1.set("foo.abc",undefined);
|
|
||||||
should.not.exist(context1.get("foo.abc"));
|
|
||||||
context1.set("foo",undefined);
|
|
||||||
should.not.exist(context1.get("foo"));
|
|
||||||
});
|
|
||||||
it('stores flow property',function() {
|
|
||||||
var context1 = Context.get("1","flowA");
|
|
||||||
should.not.exist(context1.flow.get("foo"));
|
|
||||||
context1.flow.set("foo","test");
|
|
||||||
context1.flow.get("foo").should.eql("test");
|
|
||||||
});
|
|
||||||
it('stores global property',function() {
|
|
||||||
var context1 = Context.get("1","flowA");
|
|
||||||
should.not.exist(context1.global.get("foo"));
|
|
||||||
context1.global.set("foo","test");
|
|
||||||
context1.global.get("foo").should.eql("test");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('keeps local context local', function() {
|
|
||||||
var context1 = Context.get("1","flowA");
|
|
||||||
var context2 = Context.get("2","flowA");
|
|
||||||
|
|
||||||
should.not.exist(context1.get("foo"));
|
|
||||||
should.not.exist(context2.get("foo"));
|
|
||||||
context1.set("foo","test");
|
|
||||||
|
|
||||||
context1.get("foo").should.eql("test");
|
|
||||||
should.not.exist(context2.get("foo"));
|
|
||||||
});
|
|
||||||
it('flow context accessible to all flow nodes', function() {
|
|
||||||
var context1 = Context.get("1","flowA");
|
|
||||||
var context2 = Context.get("2","flowA");
|
|
||||||
|
|
||||||
should.not.exist(context1.flow.get("foo"));
|
|
||||||
should.not.exist(context2.flow.get("foo"));
|
|
||||||
|
|
||||||
context1.flow.set("foo","test");
|
|
||||||
context1.flow.get("foo").should.eql("test");
|
|
||||||
context2.flow.get("foo").should.eql("test");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('flow context not shared to nodes on other flows', function() {
|
|
||||||
var context1 = Context.get("1","flowA");
|
|
||||||
var context2 = Context.get("2","flowB");
|
|
||||||
|
|
||||||
should.not.exist(context1.flow.get("foo"));
|
|
||||||
should.not.exist(context2.flow.get("foo"));
|
|
||||||
|
|
||||||
context1.flow.set("foo","test");
|
|
||||||
context1.flow.get("foo").should.eql("test");
|
|
||||||
should.not.exist(context2.flow.get("foo"));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('global context shared to all nodes', function() {
|
|
||||||
var context1 = Context.get("1","flowA");
|
|
||||||
var context2 = Context.get("2","flowB");
|
|
||||||
|
|
||||||
should.not.exist(context1.global.get("foo"));
|
|
||||||
should.not.exist(context2.global.get("foo"));
|
|
||||||
|
|
||||||
context1.global.set("foo","test");
|
|
||||||
context1.global.get("foo").should.eql("test");
|
|
||||||
context2.global.get("foo").should.eql("test");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('deletes context',function() {
|
|
||||||
var context = Context.get("1","flowA");
|
|
||||||
should.not.exist(context.get("foo"));
|
|
||||||
context.set("foo","abc");
|
|
||||||
context.get("foo").should.eql("abc");
|
|
||||||
|
|
||||||
Context.delete("1","flowA");
|
|
||||||
context = Context.get("1","flowA");
|
|
||||||
should.not.exist(context.get("foo"));
|
|
||||||
})
|
|
||||||
|
|
||||||
it('enumerates context keys', function() {
|
|
||||||
var context = Context.get("1","flowA");
|
|
||||||
|
|
||||||
var keys = context.keys();
|
|
||||||
keys.should.be.an.Array();
|
|
||||||
keys.should.be.empty();
|
|
||||||
|
|
||||||
context.set("foo","bar");
|
|
||||||
keys = context.keys();
|
|
||||||
keys.should.have.length(1);
|
|
||||||
keys[0].should.eql("foo");
|
|
||||||
|
|
||||||
context.set("abc.def","bar");
|
|
||||||
keys = context.keys();
|
|
||||||
keys.should.have.length(2);
|
|
||||||
keys[1].should.eql("abc");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
});
|
|
Loading…
Reference in New Issue
Block a user