From 92ab16ba745cba6d41e8dbe0661c21281add129f Mon Sep 17 00:00:00 2001 From: Dominic Bosch Date: Thu, 13 Feb 2014 18:16:03 +0100 Subject: [PATCH] Persistence module implementation and testing finished --- ...db_interface.coffee => persistence.coffee} | 101 +- coffee/request_handler.coffee | 4 +- coffee/server.coffee | 6 +- js-coffee/engine.js | 2 +- js-coffee/{db_interface.js => persistence.js} | 112 ++- js-coffee/queue.js | 57 -- js-coffee/request_handler.js | 2 +- js-coffee/server.js | 4 +- testing/test_db_interface.coffee | 799 ---------------- testing/test_persistence.coffee | 878 ++++++++++++++++++ 10 files changed, 1016 insertions(+), 949 deletions(-) rename coffee/{db_interface.coffee => persistence.coffee} (95%) rename js-coffee/{db_interface.js => persistence.js} (95%) delete mode 100644 js-coffee/queue.js delete mode 100644 testing/test_db_interface.coffee create mode 100644 testing/test_persistence.coffee diff --git a/coffee/db_interface.coffee b/coffee/persistence.coffee similarity index 95% rename from coffee/db_interface.coffee rename to coffee/persistence.coffee index 8d52317..e69ba85 100644 --- a/coffee/db_interface.coffee +++ b/coffee/persistence.coffee @@ -1,6 +1,6 @@ ### -DB Interface +Persistence ============ > Handles the connection to the database and provides functionalities for > event pollers, action invokers, rules and the encrypted storing of authentication tokens. @@ -24,7 +24,8 @@ DB Interface # - [Logging](logging.html) log = require './logging' -# - External Modules: [crypto-js](https://github.com/evanvosberg/crypto-js) and +# - External Modules: +# [crypto-js](https://github.com/evanvosberg/crypto-js) and # [redis](https://github.com/mranney/node_redis) crypto = require 'crypto-js' redis = require 'redis' @@ -629,7 +630,7 @@ Get users activated for a rule and hand it to cb(err, obj). @param {function} cb ### exports.getRuleActivatedUsers = ( ruleId, cb ) => - log.print 'DB', "getRuleLinkedUsers: for rule '#{ ruleId }'" + log.print 'DB', "getRuleActivatedUsers: for rule '#{ ruleId }'" @db.smembers "rule:#{ ruleId }:active-users", cb ### @@ -745,13 +746,48 @@ exports.deleteUser = ( userId ) => # We also need to delete all associated roles @db.smembers "user:#{ userId }:roles", ( err, obj ) => - delActivatedRoleUser = ( roleId ) => + delRoleUser = ( roleId ) => @db.srem "role:#{ roleId }:users", userId, replyHandler "Deleting user key '#{ userId }' in role '#{ roleId }'" - delActivatedRoleUser( id ) for id in obj + delRoleUser( id ) for id in obj @db.del "user:#{ userId }:roles", replyHandler "Deleting user '#{ userId }' roles" +### +Checks the credentials and on success returns the user object to the +callback(err, obj) function. The password has to be hashed (SHA-3-512) +beforehand by the instance closest to the user that enters the password, +because we only store hashes of passwords for security6 reasons. + +@public loginUser( *userId, password, cb* ) +@param {String} userId +@param {String} password +@param {function} cb +### +#TODO verify and test whole function +exports.loginUser = ( userId, password, cb ) => + log.print 'DB', "User '#{ userId }' tries to log in" + fCheck = ( pw ) -> + ( err, obj ) -> + if err + cb err, null + else if obj and obj.password + if pw == obj.password + log.print 'DB', "User '#{ obj.username }' logged in!" + cb null, obj + else + cb (new Error 'Wrong credentials!'), null + else + cb (new Error 'User not found!'), null + @db.hgetall "user:#{ userId }", fCheck password + +#TODO implement functions required for user sessions? + + +### +## User Roles +### + ### Associate a role with a user. @@ -772,50 +808,37 @@ Fetch all roles of a user and pass them to cb(err, obj). @public getUserRoles( *userId* ) @param {String} userId +@param {function} cb ### -exports.getUserRoles = ( userId ) => - log.print 'DB', "getUserRole: '#{ userId }'" - @db.get "user-roles:#{ userId }", cb +exports.getUserRoles = ( userId, cb ) => + log.print 'DB', "getUserRoles: '#{ userId }'" + @db.smembers "user:#{ userId }:roles", cb ### Fetch all users of a role and pass them to cb(err, obj). @public getUserRoles( *role* ) @param {String} role -### -exports.getRoleUsers = ( role ) => - log.print 'DB', "getRoleUsers: '#{ role }'" - @db.get "role-users:#{ role }", cb - -### -Checks the credentials and on success returns the user object to the -callback(err, obj) function. The password has to be hashed (SHA-3-512) -beforehand by the instance closest to the user that enters the password, -because we only store hashes of passwords for safety reasons. - -@public loginUser( *userId, password, cb* ) -@param {String} userId -@param {String} password @param {function} cb ### -#TODO verify and test whole function -exports.loginUser = ( userId, password, cb ) => - log.print 'DB', "User '#{ userId }' tries to log in" - fCheck = ( pw ) -> - ( err, obj ) -> - if err - cb err - else if obj and obj.password - if pw == obj.password - log.print 'DB', "User '#{ obj.username }' logged in!" - cb null, obj - else - cb new Error 'Wrong credentials!' - else - cb new Error 'User not found!' - @db.hgetall "user:#{ userId }", fCheck password +exports.getRoleUsers = ( role, cb ) => + log.print 'DB', "getRoleUsers: '#{ role }'" + @db.smembers "role:#{ role }:users", cb + +### +Remove a role from a user. + +@public removeRoleFromUser( *role, userId* ) +@param {String} role +@param {String} userId +### +exports.removeUserRole = ( userId, role ) => + log.print 'DB', "removeRoleFromUser: role '#{ role }', user '#{ userId }'" + @db.srem "user:#{ userId }:roles", role, + replyHandler "Removing role '#{ role }' from user '#{ userId }'" + @db.srem "role:#{ role }:users", userId, + replyHandler "Removing user '#{ userId }' from role '#{ role }'" -#TODO implement functions required for user sessions? ### Shuts down the db link. diff --git a/coffee/request_handler.coffee b/coffee/request_handler.coffee index 59b5f03..265b83d 100644 --- a/coffee/request_handler.coffee +++ b/coffee/request_handler.coffee @@ -11,8 +11,8 @@ Request Handler # - [Logging](logging.html) log = require './logging' -# - [DB Interface](db_interface.html) -db = require './db_interface' +# - [Persistence](persistence.html) +db = require './persistence' # - [Module Manager](module_manager.html) mm = require './module_manager' diff --git a/coffee/server.coffee b/coffee/server.coffee index 4318db1..4a9ea8a 100644 --- a/coffee/server.coffee +++ b/coffee/server.coffee @@ -29,8 +29,8 @@ log = require './logging' # - [Configuration](config.html) conf = require './config' -# - [DB Interface](db_interface.html) -db = require './db_interface' +# - [Persistence](persistence.html) +db = require './persistence' # - [Engine](engine.html) engine = require './engine' @@ -98,7 +98,7 @@ init = -> # > Distribute handlers between modules to link the application. log.print 'RS', 'Passing handlers to engine' - engine.addDBLinkAndLoadActionsAndRules db + engine.addPersistence db log.print 'RS', 'Passing handlers to http listener' #TODO engine pushEvent needs to go into redis queue http_listener.addHandlers shutDown diff --git a/js-coffee/engine.js b/js-coffee/engine.js index 4ea45d2..78babcc 100644 --- a/js-coffee/engine.js +++ b/js-coffee/engine.js @@ -27,7 +27,7 @@ exports = module.exports = function(args) { * @param {String} db_port the db port * @param {String} crypto_key the key to be used for encryption on the db, max legnth 256 */ -exports.addDBLinkAndLoadActionsAndRules = function(db_link) { +exports.addPersistence = function(db_link) { db = db_link; // if(ml && db) db.getActionModules(function(err, obj) { // if(err) log.error('EN', 'retrieving Action Modules from DB!'); diff --git a/js-coffee/db_interface.js b/js-coffee/persistence.js similarity index 95% rename from js-coffee/db_interface.js rename to js-coffee/persistence.js index a01fefc..fd35317 100644 --- a/js-coffee/db_interface.js +++ b/js-coffee/persistence.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript 1.6.3 /* -DB Interface +Persistence ============ > Handles the connection to the database and provides functionalities for > event pollers, action invokers, rules and the encrypted storing of authentication tokens. @@ -798,7 +798,7 @@ DB Interface exports.getRuleActivatedUsers = function(ruleId, cb) { - log.print('DB', "getRuleLinkedUsers: for rule '" + ruleId + "'"); + log.print('DB', "getRuleActivatedUsers: for rule '" + ruleId + "'"); return _this.db.smembers("rule:" + ruleId + ":active-users", cb); }; @@ -945,20 +945,60 @@ DB Interface }); _this.db.del("user:" + userId + ":active-rules", replyHandler("Deleting user '" + userId + "' rules")); _this.db.smembers("user:" + userId + ":roles", function(err, obj) { - var delActivatedRoleUser, id, _i, _len, _results; - delActivatedRoleUser = function(roleId) { + var delRoleUser, id, _i, _len, _results; + delRoleUser = function(roleId) { return _this.db.srem("role:" + roleId + ":users", userId, replyHandler("Deleting user key '" + userId + "' in role '" + roleId + "'")); }; _results = []; for (_i = 0, _len = obj.length; _i < _len; _i++) { id = obj[_i]; - _results.push(delActivatedRoleUser(id)); + _results.push(delRoleUser(id)); } return _results; }); return _this.db.del("user:" + userId + ":roles", replyHandler("Deleting user '" + userId + "' roles")); }; + /* + Checks the credentials and on success returns the user object to the + callback(err, obj) function. The password has to be hashed (SHA-3-512) + beforehand by the instance closest to the user that enters the password, + because we only store hashes of passwords for security6 reasons. + + @public loginUser( *userId, password, cb* ) + @param {String} userId + @param {String} password + @param {function} cb + */ + + + exports.loginUser = function(userId, password, cb) { + var fCheck; + log.print('DB', "User '" + userId + "' tries to log in"); + fCheck = function(pw) { + return function(err, obj) { + if (err) { + return cb(err, null); + } else if (obj && obj.password) { + if (pw === obj.password) { + log.print('DB', "User '" + obj.username + "' logged in!"); + return cb(null, obj); + } else { + return cb(new Error('Wrong credentials!'), null); + } + } else { + return cb(new Error('User not found!'), null); + } + }; + }; + return _this.db.hgetall("user:" + userId, fCheck(password)); + }; + + /* + ## User Roles + */ + + /* Associate a role with a user. @@ -980,12 +1020,13 @@ DB Interface @public getUserRoles( *userId* ) @param {String} userId + @param {function} cb */ - exports.getUserRoles = function(userId) { - log.print('DB', "getUserRole: '" + userId + "'"); - return _this.db.get("user-roles:" + userId, cb); + exports.getUserRoles = function(userId, cb) { + log.print('DB', "getUserRoles: '" + userId + "'"); + return _this.db.smembers("user:" + userId + ":roles", cb); }; /* @@ -993,47 +1034,28 @@ DB Interface @public getUserRoles( *role* ) @param {String} role - */ - - - exports.getRoleUsers = function(role) { - log.print('DB', "getRoleUsers: '" + role + "'"); - return _this.db.get("role-users:" + role, cb); - }; - - /* - Checks the credentials and on success returns the user object to the - callback(err, obj) function. The password has to be hashed (SHA-3-512) - beforehand by the instance closest to the user that enters the password, - because we only store hashes of passwords for safety reasons. - - @public loginUser( *userId, password, cb* ) - @param {String} userId - @param {String} password @param {function} cb */ - exports.loginUser = function(userId, password, cb) { - var fCheck; - log.print('DB', "User '" + userId + "' tries to log in"); - fCheck = function(pw) { - return function(err, obj) { - if (err) { - return cb(err); - } else if (obj && obj.password) { - if (pw === obj.password) { - log.print('DB', "User '" + obj.username + "' logged in!"); - return cb(null, obj); - } else { - return cb(new Error('Wrong credentials!')); - } - } else { - return cb(new Error('User not found!')); - } - }; - }; - return _this.db.hgetall("user:" + userId, fCheck(password)); + exports.getRoleUsers = function(role, cb) { + log.print('DB', "getRoleUsers: '" + role + "'"); + return _this.db.smembers("role:" + role + ":users", cb); + }; + + /* + Remove a role from a user. + + @public removeRoleFromUser( *role, userId* ) + @param {String} role + @param {String} userId + */ + + + exports.removeUserRole = function(userId, role) { + log.print('DB', "removeRoleFromUser: role '" + role + "', user '" + userId + "'"); + _this.db.srem("user:" + userId + ":roles", role, replyHandler("Removing role '" + role + "' from user '" + userId + "'")); + return _this.db.srem("role:" + role + ":users", userId, replyHandler("Removing user '" + userId + "' from role '" + role + "'")); }; /* diff --git a/js-coffee/queue.js b/js-coffee/queue.js deleted file mode 100644 index 906692e..0000000 --- a/js-coffee/queue.js +++ /dev/null @@ -1,57 +0,0 @@ -// *(will be replaced by a Redis DB queue)* - -// Queue.js -// ======== -// -// *A function to represent a queue* - -// *Created by Stephen Morley - http://code.stephenmorley.org/ - and released under -// the terms of the CC0 1.0 Universal legal code:* - -// *http://creativecommons.org/publicdomain/zero/1.0/legalcode* - -// *items are added to the end of the queue and removed from the front.* - -exports.Queue = function(){ - // initialise the queue and offset - var queue = []; - var offset = 0; - this.getLength = function(){ - // return the length of the queue - return (queue.length - offset); - }; - - /* Returns true if the queue is empty, and false otherwise. - */ - this.isEmpty = function(){ return (queue.length == 0); }; - - /* Enqueues the specified item. The parameter is: - * item - the item to enqueue - */ - this.enqueue = function(item){ queue.push(item); }; - - /* Dequeues an item and returns it. If the queue is empty then undefined is - * returned. - */ - this.dequeue = function(){ - // if the queue is empty, return undefined - if (queue.length == 0) return undefined; - // store the item at the front of the queue - var item = queue[offset]; - // increment the offset and remove the free space if necessary - if (++ offset * 2 >= queue.length){ - queue = queue.slice(offset); - offset = 0; - } - // return the dequeued item - return item; - }; - - /* Returns the item at the front of the queue (without dequeuing it). If the - * queue is empty then undefined is returned. - */ - this.peek = function(){ - // return the item at the front of the queue - return (queue.length > 0 ? queue[offset] : undefined); - }; -}; diff --git a/js-coffee/request_handler.js b/js-coffee/request_handler.js index c66e5ac..e46bae5 100644 --- a/js-coffee/request_handler.js +++ b/js-coffee/request_handler.js @@ -13,7 +13,7 @@ Request Handler log = require('./logging'); - db = require('./db_interface'); + db = require('./persistence'); mm = require('./module_manager'); diff --git a/js-coffee/server.js b/js-coffee/server.js index 154bc43..737de63 100644 --- a/js-coffee/server.js +++ b/js-coffee/server.js @@ -30,7 +30,7 @@ TODO how about we allow spawning child processes with servers based on address? conf = require('./config'); - db = require('./db_interface'); + db = require('./persistence'); engine = require('./engine'); @@ -105,7 +105,7 @@ TODO how about we allow spawning child processes with servers based on address? log.print('RS', 'Initialzing http listener'); http_listener(args); log.print('RS', 'Passing handlers to engine'); - engine.addDBLinkAndLoadActionsAndRules(db); + engine.addPersistence(db); log.print('RS', 'Passing handlers to http listener'); return http_listener.addHandlers(shutDown); } diff --git a/testing/test_db_interface.coffee b/testing/test_db_interface.coffee deleted file mode 100644 index 3eaf1d4..0000000 --- a/testing/test_db_interface.coffee +++ /dev/null @@ -1,799 +0,0 @@ - -exports.setUp = ( cb ) => - @db = require '../js-coffee/db_interface' - @db logType: 2 - cb() - -exports.tearDown = ( cb ) => - @db.shutDown() - cb() - - -### -# Test AVAILABILITY -### -exports.Availability = - testRequire: ( test ) => - test.expect 1 - - test.ok @db, 'DB interface loaded' - test.done() - - testConnect: ( test ) => - test.expect 1 - - @db.isConnected ( err ) -> - test.ifError err, 'Connection failed!' - test.done() - - testNoConfig: ( test ) => - test.expect 1 - - @db - configPath: 'nonexistingconf.file' - @db.isConnected ( err ) -> - test.ok err, 'Still connected!?' - test.done() - - testWrongConfig: ( test ) => - test.expect 1 - - @db { configPath: 'testing/jsonWrongConfig.json' } - @db.isConnected ( err ) -> - test.ok err, 'Still connected!?' - test.done() - - testPurgeQueue: ( test ) => - test.expect 2 - - evt = - eventid: '1' - event: 'mail' - @db.pushEvent evt - @db.purgeEventQueue() - @db.popEvent ( err, obj ) => - test.ifError err, 'Error during pop after purging!' - test.strictEqual obj, null, 'There was an event in the queue!?' - test.done() - - -### -# Test EVENT QUEUE -### -exports.EventQueue = - setUp: ( cb ) => - @evt1 = - eventid: '1' - event: 'mail' - @evt2 = - eventid: '2' - event: 'mail' - @db.purgeEventQueue() - cb() - - testEmptyPopping: ( test ) => - test.expect 2 - - @db.popEvent ( err, obj ) => - test.ifError err, - 'Error during pop after purging!' - test.strictEqual obj, null, - 'There was an event in the queue!?' - test.done() - - testEmptyPushing: ( test ) => - test.expect 2 - - @db.pushEvent null - @db.popEvent ( err, obj ) => - test.ifError err, - 'Error during non-empty pushing!' - test.strictEqual obj, null, - 'There was an event in the queue!?' - test.done() - - testNonEmptyPopping: ( test ) => - test.expect 3 - - @db.pushEvent @evt1 - @db.popEvent ( err, obj ) => - test.ifError err, - 'Error during non-empty popping!' - test.notStrictEqual obj, null, - 'There was no event in the queue!' - test.deepEqual @evt1, obj, - 'Wrong event in queue!' - test.done() - - testMultiplePushAndPops: ( test ) => - test.expect 6 - - semaphore = 2 - forkEnds = () -> - test.done() if --semaphore is 0 - - @db.pushEvent @evt1 - @db.pushEvent @evt2 - # eventually it would be wise to not care about the order of events - @db.popEvent ( err, obj ) => - test.ifError err, - 'Error during multiple push and pop!' - test.notStrictEqual obj, null, - 'There was no event in the queue!' - test.deepEqual @evt1, obj, - 'Wrong event in queue!' - forkEnds() - @db.popEvent ( err, obj ) => - test.ifError err, - 'Error during multiple push and pop!' - test.notStrictEqual obj, null, - 'There was no event in the queue!' - test.deepEqual @evt2, obj, - 'Wrong event in queue!' - forkEnds() - - -### -# Test ACTION INVOKER -### -exports.ActionInvoker = - testCreateAndRead: ( test ) => - test.expect 3 - - id = 'test-action-invoker' - action = 'unit-test action invoker content' - - # store an entry to start with - @db.storeActionInvoker id, action - - # test that the ID shows up in the set - @db.getActionInvokerIds ( err , obj ) => - test.ok id in obj, - 'Expected key not in action-invokers set' - - # the retrieved object really is the one we expected - @db.getActionInvoker id, ( err , obj ) => - test.strictEqual obj, action, - 'Retrieved Action Invoker is not what we expected' - - # Ensure the action invoker is in the list of all existing ones - @db.getActionInvokers ( err , obj ) => - test.deepEqual action, obj[id], - 'Action Invoker ist not in result set' - @db.deleteActionInvoker id - test.done() - - testUpdate: ( test ) => - test.expect 2 - - id = 'test-action-invoker' - action = 'unit-test action invoker content' - actionNew = 'unit-test action invoker new content' - - # store an entry to start with - @db.storeActionInvoker id, action - @db.storeActionInvoker id, actionNew - - # the retrieved object really is the one we expected - @db.getActionInvoker id, ( err , obj ) => - test.strictEqual obj, actionNew, - 'Retrieved Action Invoker is not what we expected' - - # Ensure the action invoker is in the list of all existing ones - @db.getActionInvokers ( err , obj ) => - test.deepEqual actionNew, obj[id], - 'Action Invoker ist not in result set' - @db.deleteActionInvoker id - test.done() - - testDelete: ( test ) => - test.expect 2 - - id = 'test-action-invoker' - action = 'unit-test action invoker content' - - # store an entry to start with - @db.storeActionInvoker id, action - - # Ensure the action invoker has been deleted - @db.deleteActionInvoker id - @db.getActionInvoker id, ( err , obj ) => - test.strictEqual obj, null, - 'Action Invoker still exists' - - # Ensure the ID has been removed from the set - @db.getActionInvokerIds ( err , obj ) => - test.ok id not in obj, - 'Action Invoker key still exists in set' - test.done() - - - testFetchSeveral: ( test ) => - test.expect 3 - - semaphore = 2 - action1name = 'test-action-invoker_1' - action2name = 'test-action-invoker_2' - action1 = 'unit-test action invoker 1 content' - action2 = 'unit-test action invoker 2 content' - - fCheckInvoker = ( modname, mod ) => - myTest = test - forkEnds = () -> - myTest.done() if --semaphore is 0 - ( err, obj ) => - myTest.strictEqual mod, obj, - "Invoker #{ modname } does not equal the expected one" - @db.deleteActionInvoker modname - forkEnds() - - @db.storeActionInvoker action1name, action1 - @db.storeActionInvoker action2name, action2 - @db.getActionInvokerIds ( err, obj ) => - test.ok action1name in obj and action2name in obj, - 'Not all action invoker Ids in set' - @db.getActionInvoker action1name, fCheckInvoker action1name, action1 - @db.getActionInvoker action2name, fCheckInvoker action2name, action2 - - -### -# Test ACTION INVOKER PARAMS -### -exports.ActionInvokerParams = - testCreateAndRead: ( test ) => - test.expect 2 - - userId = 'tester1' - actionId = 'test-action-invoker_1' - params = 'shouldn\'t this be an object?' - - # store an entry to start with - @db.storeActionParams actionId, userId, params - - # test that the ID shows up in the set - @db.getActionParamsIds ( err, obj ) => - test.ok actionId+':'+userId in obj, - 'Expected key not in action-params set' - - # the retrieved object really is the one we expected - @db.getActionParams actionId, userId, ( err, obj ) => - test.strictEqual obj, params, - 'Retrieved action params is not what we expected' - @db.deleteActionParams actionId, userId - test.done() - - testUpdate: ( test ) => - test.expect 1 - - userId = 'tester1' - actionId = 'test-action-invoker_1' - params = 'shouldn\'t this be an object?' - paramsNew = 'shouldn\'t this be a new object?' - - # store an entry to start with - @db.storeActionParams actionId, userId, params - @db.storeActionParams actionId, userId, paramsNew - - # the retrieved object really is the one we expected - @db.getActionParams actionId, userId, ( err, obj ) => - test.strictEqual obj, paramsNew, - 'Retrieved action params is not what we expected' - @db.deleteActionParams actionId, userId - test.done() - - testDelete: ( test ) => - test.expect 2 - - userId = 'tester1' - actionId = 'test-action-invoker_1' - params = 'shouldn\'t this be an object?' - - # store an entry to start with and delte it right away - @db.storeActionParams actionId, userId, params - @db.deleteActionParams actionId, userId - - # Ensure the action params have been deleted - @db.getActionParams actionId, userId, ( err, obj ) => - test.strictEqual obj, null, - 'Action params still exists' - # Ensure the ID has been removed from the set - @db.getActionParamsIds ( err, obj ) => - test.ok actionId+':'+userId not in obj, - 'Action Params key still exists in set' - test.done() - - -### -# Test EVENT POLLER -### -exports.EventPoller = - testCreateAndRead: ( test ) => - test.expect 3 - - id = 'test-event-poller' - event = 'unit-test event poller content' - - # store an entry to start with - @db.storeEventPoller id, event - - # test that the ID shows up in the set - @db.getEventPollerIds ( err , obj ) => - test.ok id in obj, - 'Expected key not in event-pollers set' - - # the retrieved object really is the one we expected - @db.getEventPoller id, ( err , obj ) => - test.strictEqual obj, event, - 'Retrieved Event Poller is not what we expected' - - # Ensure the event poller is in the list of all existing ones - @db.getEventPollers ( err , obj ) => - test.deepEqual event, obj[id], - 'Event Poller ist not in result set' - @db.deleteEventPoller id - test.done() - - testUpdate: ( test ) => - test.expect 2 - - id = 'test-event-poller' - event = 'unit-test event poller content' - eventNew = 'unit-test event poller new content' - - # store an entry to start with - @db.storeEventPoller id, event - @db.storeEventPoller id, eventNew - - # the retrieved object really is the one we expected - @db.getEventPoller id, ( err , obj ) => - test.strictEqual obj, eventNew, - 'Retrieved Event Poller is not what we expected' - - # Ensure the event poller is in the list of all existing ones - @db.getEventPollers ( err , obj ) => - test.deepEqual eventNew, obj[id], - 'Event Poller ist not in result set' - @db.deleteEventPoller id - test.done() - - testDelete: ( test ) => - test.expect 2 - - id = 'test-event-poller' - event = 'unit-test event poller content' - - # store an entry to start with - @db.storeEventPoller id, event - - # Ensure the event poller has been deleted - @db.deleteEventPoller id - @db.getEventPoller id, ( err , obj ) => - test.strictEqual obj, null, - 'Event Poller still exists' - - # Ensure the ID has been removed from the set - @db.getEventPollerIds ( err , obj ) => - test.ok id not in obj, - 'Event Poller key still exists in set' - test.done() - - - testFetchSeveral: ( test ) => - test.expect 3 - - semaphore = 2 - event1name = 'test-event-poller_1' - event2name = 'test-event-poller_2' - event1 = 'unit-test event poller 1 content' - event2 = 'unit-test event poller 2 content' - - fCheckPoller = ( modname, mod ) => - myTest = test - forkEnds = () -> - myTest.done() if --semaphore is 0 - ( err, obj ) => - myTest.strictEqual mod, obj, - "Invoker #{ modname } does not equal the expected one" - @db.deleteEventPoller modname - forkEnds() - - @db.storeEventPoller event1name, event1 - @db.storeEventPoller event2name, event2 - @db.getEventPollerIds ( err, obj ) => - test.ok event1name in obj and event2name in obj, - 'Not all event poller Ids in set' - @db.getEventPoller event1name, fCheckPoller event1name, event1 - @db.getEventPoller event2name, fCheckPoller event2name, event2 - - -### -# Test EVENT POLLER PARAMS -### -exports.EventPollerParams = - testCreateAndRead: ( test ) => - test.expect 2 - - userId = 'tester1' - eventId = 'test-event-poller_1' - params = 'shouldn\'t this be an object?' - - # store an entry to start with - @db.storeEventParams eventId, userId, params - - # test that the ID shows up in the set - @db.getEventParamsIds ( err, obj ) => - test.ok eventId+':'+userId in obj, - 'Expected key not in event-params set' - - # the retrieved object really is the one we expected - @db.getEventParams eventId, userId, ( err, obj ) => - test.strictEqual obj, params, - 'Retrieved event params is not what we expected' - @db.deleteEventParams eventId, userId - test.done() - - testUpdate: ( test ) => - test.expect 1 - - userId = 'tester1' - eventId = 'test-event-poller_1' - params = 'shouldn\'t this be an object?' - paramsNew = 'shouldn\'t this be a new object?' - - # store an entry to start with - @db.storeEventParams eventId, userId, params - @db.storeEventParams eventId, userId, paramsNew - - # the retrieved object really is the one we expected - @db.getEventParams eventId, userId, ( err, obj ) => - test.strictEqual obj, paramsNew, - 'Retrieved event params is not what we expected' - @db.deleteEventParams eventId, userId - test.done() - - testDelete: ( test ) => - test.expect 2 - - userId = 'tester1' - eventId = 'test-event-poller_1' - params = 'shouldn\'t this be an object?' - - # store an entry to start with and delete it right away - @db.storeEventParams eventId, userId, params - @db.deleteEventParams eventId, userId - - # Ensure the event params have been deleted - @db.getEventParams eventId, userId, ( err, obj ) => - test.strictEqual obj, null, - 'Event params still exists' - # Ensure the ID has been removed from the set - @db.getEventParamsIds ( err, obj ) => - test.ok eventId+':'+userId not in obj, - 'Event Params key still exists in set' - test.done() - - -### -# Test RULES -### -exports.Rules = - setUp: ( cb ) => - # @db logType: 1 - @userId = 'tester-1' - @ruleId = 'test-rule_1' - @rule = - "id": "rule_id", - "event": "custom", - "condition": - "property": "yourValue", - "actions": [] - @ruleNew = - "id": "rule_new", - "event": "custom", - "condition": - "property": "yourValue", - "actions": [] - cb() - - tearDown: ( cb ) => - @db.deleteRule @ruleId - cb() - - testCreateAndRead: ( test ) => - test.expect 3 - - # store an entry to start with - @db.storeRule @ruleId, JSON.stringify(@rule) - - # test that the ID shows up in the set - @db.getRuleIds ( err, obj ) => - test.ok @ruleId in obj, - 'Expected key not in rule key set' - - # the retrieved object really is the one we expected - @db.getRule @ruleId, ( err, obj ) => - test.deepEqual JSON.parse(obj), @rule, - 'Retrieved rule is not what we expected' - - # Ensure the rule is in the list of all existing ones - @db.getRules ( err , obj ) => - test.deepEqual @rule, JSON.parse(obj[@ruleId]), - 'Rule not in result set' - @db.deleteRule @ruleId - test.done() - - testUpdate: ( test ) => - test.expect 1 - - # store an entry to start with - @db.storeRule @ruleId, JSON.stringify(@rule) - @db.storeRule @ruleId, JSON.stringify(@ruleNew) - - # the retrieved object really is the one we expected - @db.getRule @ruleId, ( err, obj ) => - test.deepEqual JSON.parse(obj), @ruleNew, - 'Retrieved rule is not what we expected' - @db.deleteRule @ruleId - test.done() - - testDelete: ( test ) => - test.expect 2 - - # store an entry to start with and delete it right away - @db.storeRule @ruleId, JSON.stringify(@rule) - @db.deleteRule @ruleId - - # Ensure the event params have been deleted - @db.getRule @ruleId, ( err, obj ) => - test.strictEqual obj, null, - 'Rule still exists' - - # Ensure the ID has been removed from the set - @db.getRuleIds ( err, obj ) => - test.ok @ruleId not in obj, - 'Rule key still exists in set' - test.done() - - testLink: ( test ) => - test.expect 2 - - # link a rule to the user - @db.linkRule @ruleId, @userId - - # Ensure the user is linked to the rule - @db.getRuleLinkedUsers @ruleId, ( err, obj ) => - test.ok @userId in obj, - "Rule not linked to user #{ @userId }" - - # Ensure the rule is linked to the user - @db.getUserLinkedRules @userId, ( err, obj ) => - test.ok @ruleId in obj, - "User not linked to rule #{ @ruleId }" - test.done() - - testUnlink: ( test ) => - test.expect 2 - - # link and unlink immediately afterwards - @db.linkRule @ruleId, @userId - @db.unlinkRule @ruleId, @userId - - # Ensure the user is linked to the rule - @db.getRuleLinkedUsers @ruleId, ( err, obj ) => - test.ok @userId not in obj, - "Rule still linked to user #{ @userId }" - - # Ensure the rule is linked to the user - @db.getUserLinkedRules @userId, ( err, obj ) => - test.ok @ruleId not in obj, - "User still linked to rule #{ @ruleId }" - test.done() - - testActivate: ( test ) => - test.expect 4 - - usr = - username: "tester-1" - password: "tester-1" - @db.storeUser usr - @db.activateRule @ruleId, @userId - # activate a rule for a user - - # Ensure the user is activated to the rule - @db.getRuleActivatedUsers @ruleId, ( err, obj ) => - test.ok @userId in obj, - "Rule not activated for user #{ @userId }" - - # Ensure the rule is linked to the user - @db.getUserActivatedRules @userId, ( err, obj ) => - test.ok @ruleId in obj, - "User not activated for rule #{ @ruleId }" - - # Ensure the rule is showing up in all active rules - @db.getAllActivatedRuleIdsPerUser ( err, obj ) => - test.notStrictEqual obj[@userId], undefined, - "User #{ @userId } not in activated rules set" - if obj[@userId] - test.ok @ruleId in obj[@userId], - "Rule #{ @ruleId } not in activated rules set" - else - test.ok true, - "Dummy so we meet the expected num of tests" - test.done() - - testDeactivate: ( test ) => - test.expect 3 - - # store an entry to start with and link it to te user - @db.activateRule @ruleId, @userId - @db.deactivateRule @ruleId, @userId - - # Ensure the user is linked to the rule - @db.getRuleActivatedUsers @ruleId, ( err, obj ) => - test.ok @userId not in obj, - "Rule still activated for user #{ @userId }" - - # Ensure the rule is linked to the user - @db.getUserActivatedRules @userId, ( err, obj ) => - test.ok @ruleId not in obj, - "User still activated for rule #{ @ruleId }" - - # Ensure the rule is showing up in all active rules - @db.getAllActivatedRuleIdsPerUser ( err, obj ) => - if obj[@userId] - test.ok @ruleId not in obj[@userId], - "Rule #{ @ruleId } still in activated rules set" - else - test.ok true, - "We are fine since there are no entries for this user anymore" - test.done() - - testUnlinkAndDeactivateAfterDeletion: ( test ) => - test.expect 2 - - # store an entry to start with and link it to te user - @db.storeRule @ruleId, JSON.stringify(@rule) - @db.linkRule @ruleId, @userId - @db.activateRule @ruleId, @userId - - # We need to wait here and there since these calls are asynchronous - fWaitForTest = () => - - # Ensure the user is unlinked to the rule - @db.getUserLinkedRules @userId, ( err, obj ) => - test.ok @ruleId not in obj, - "Rule #{ @ruleId } still linked to user #{ @userId }" - - # Ensure the rule is deactivated for the user - @db.getUserActivatedRules @userId, ( err, obj ) => - test.ok @ruleId not in obj, - "Rule #{ @ruleId } still activated for user #{ @userId }" - test.done() - - fWaitForDeletion = () => - @db.deleteRule @ruleId - setTimeout fWaitForTest, 100 - - setTimeout fWaitForDeletion, 100 - - -### -# Test USER -### -exports.User = - setUp: ( cb ) => - @db logType: 1 - @oUser = - username: "tester-1" - password: "password" - cb() - tearDown: ( cb ) => - @db.deleteUser @oUser.username - cb() - - testCreateInvalid: ( test ) => - test.expect 4 - - oUserInvOne = - username: "tester-1-invalid" - oUserInvTwo = - password: "password" - - # try to store invalid users, ensure they weren't - @db.storeUser oUserInvOne - @db.storeUser oUserInvTwo - - @db.getUser oUserInvOne.username, ( err, obj ) => - test.strictEqual obj, null, - 'User One was stored!?' - - @db.getUser oUserInvTwo.username, ( err, obj ) => - test.strictEqual obj, null, - 'User Two was stored!?' - - @db.getUserIds ( err, obj ) => - test.ok oUserInvOne.username not in obj, - 'User key was stored!?' - test.ok oUserInvTwo.username not in obj, - 'User key was stored!?' - test.done() - - testDelete: ( test ) => - test.expect 2 - - # Store the user - @db.storeUser @oUser - - @db.getUser @oUser.username, ( err, obj ) => - test.deepEqual obj, @oUser, - "User #{ @oUser.username } is not what we expect!" - - @db.getUserIds ( err, obj ) => - test.ok @oUser.username in obj, - 'User key was not stored!?' - test.done() - - testUpdate: ( test ) => - test.expect 2 - - oUserOne = - username: "tester-1-update" - password: "password" - - # Store the user - @db.storeUser oUserOne - oUserOne.password = "password-update" - @db.storeUser oUserOne - - @db.getUser oUserOne.username, ( err, obj ) => - test.deepEqual obj, oUserOne, - "User #{ @oUser.username } is not what we expect!" - - @db.getUserIds ( err, obj ) => - test.ok oUserOne.username in obj, - 'User key was not stored!?' - @db.deleteUser oUserOne.username - test.done() - - testDelete: ( test ) => - test.expect 2 - - # Wait until the user and his rules and roles are stored - fWaitForPersistence = () => - @db.deleteUser @oUser.username - setTimeout fWaitForDeletion, 200 - - # Wait until the user and his rules and roles are deleted - fWaitForDeletion = () => - @db.getUserIds ( err, obj ) => - test.ok @oUser.username not in obj, - 'User key still in set!' - - @db.getUser @oUser.username, ( err, obj ) => - test.strictEqual obj, null, - 'User key still exists!' - test.done() - - # Store the user and make some links - @db.storeUser @oUser - @db.linkRule 'rule-1', @oUser.username - @db.linkRule 'rule-2', @oUser.username - @db.linkRule 'rule-3', @oUser.username - @db.activateRule 'rule-1', @oUser.username - @db.storeUserRole @oUser.username, 'tester' - setTimeout fWaitForPersistence, 100 - - -### -# Test ROLES -### -# exports.Roles = - # setUp: ( cb ) => - # @db logType: 1 - # @oUser = - # username: "tester-1" - # password: "password" - # cb() - # tearDown: ( cb ) => - # @db.deleteUser @oUser.username - # cb() diff --git a/testing/test_persistence.coffee b/testing/test_persistence.coffee new file mode 100644 index 0000000..d198eac --- /dev/null +++ b/testing/test_persistence.coffee @@ -0,0 +1,878 @@ + +exports.setUp = ( cb ) => + @db = require '../js-coffee/persistence' + @db logType: 2 + cb() + +exports.tearDown = ( cb ) => + @db.shutDown() + cb() + + +### +# Test AVAILABILITY +### +exports.Availability = + testRequire: ( test ) => + test.expect 1 + + test.ok @db, 'DB interface loaded' + test.done() + + testConnect: ( test ) => + test.expect 1 + + @db.isConnected ( err ) -> + test.ifError err, 'Connection failed!' + test.done() + + testNoConfig: ( test ) => + test.expect 1 + + @db + configPath: 'nonexistingconf.file' + @db.isConnected ( err ) -> + test.ok err, 'Still connected!?' + test.done() + + testWrongConfig: ( test ) => + test.expect 1 + + @db { configPath: 'testing/jsonWrongConfig.json' } + @db.isConnected ( err ) -> + test.ok err, 'Still connected!?' + test.done() + + testPurgeQueue: ( test ) => + test.expect 2 + + evt = + eventid: '1' + event: 'mail' + @db.pushEvent evt + @db.purgeEventQueue() + @db.popEvent ( err, obj ) => + test.ifError err, 'Error during pop after purging!' + test.strictEqual obj, null, 'There was an event in the queue!?' + test.done() + + +### +# Test EVENT QUEUE +### +exports.EventQueue = + setUp: ( cb ) => + @evt1 = + eventid: '1' + event: 'mail' + @evt2 = + eventid: '2' + event: 'mail' + @db.purgeEventQueue() + cb() + + testEmptyPopping: ( test ) => + test.expect 2 + + @db.popEvent ( err, obj ) => + test.ifError err, + 'Error during pop after purging!' + test.strictEqual obj, null, + 'There was an event in the queue!?' + test.done() + + testEmptyPushing: ( test ) => + test.expect 2 + + @db.pushEvent null + @db.popEvent ( err, obj ) => + test.ifError err, + 'Error during non-empty pushing!' + test.strictEqual obj, null, + 'There was an event in the queue!?' + test.done() + + testNonEmptyPopping: ( test ) => + test.expect 3 + + @db.pushEvent @evt1 + @db.popEvent ( err, obj ) => + test.ifError err, + 'Error during non-empty popping!' + test.notStrictEqual obj, null, + 'There was no event in the queue!' + test.deepEqual @evt1, obj, + 'Wrong event in queue!' + test.done() + + testMultiplePushAndPops: ( test ) => + test.expect 6 + + semaphore = 2 + forkEnds = () -> + test.done() if --semaphore is 0 + + @db.pushEvent @evt1 + @db.pushEvent @evt2 + # eventually it would be wise to not care about the order of events + @db.popEvent ( err, obj ) => + test.ifError err, + 'Error during multiple push and pop!' + test.notStrictEqual obj, null, + 'There was no event in the queue!' + test.deepEqual @evt1, obj, + 'Wrong event in queue!' + forkEnds() + @db.popEvent ( err, obj ) => + test.ifError err, + 'Error during multiple push and pop!' + test.notStrictEqual obj, null, + 'There was no event in the queue!' + test.deepEqual @evt2, obj, + 'Wrong event in queue!' + forkEnds() + + +### +# Test ACTION INVOKER +### +exports.ActionInvoker = + testCreateAndRead: ( test ) => + test.expect 3 + + id = 'test-action-invoker' + action = 'unit-test action invoker content' + + # store an entry to start with + @db.storeActionInvoker id, action + + # test that the ID shows up in the set + @db.getActionInvokerIds ( err , obj ) => + test.ok id in obj, + 'Expected key not in action-invokers set' + + # the retrieved object really is the one we expected + @db.getActionInvoker id, ( err , obj ) => + test.strictEqual obj, action, + 'Retrieved Action Invoker is not what we expected' + + # Ensure the action invoker is in the list of all existing ones + @db.getActionInvokers ( err , obj ) => + test.deepEqual action, obj[id], + 'Action Invoker ist not in result set' + @db.deleteActionInvoker id + test.done() + + testUpdate: ( test ) => + test.expect 2 + + id = 'test-action-invoker' + action = 'unit-test action invoker content' + actionNew = 'unit-test action invoker new content' + + # store an entry to start with + @db.storeActionInvoker id, action + @db.storeActionInvoker id, actionNew + + # the retrieved object really is the one we expected + @db.getActionInvoker id, ( err , obj ) => + test.strictEqual obj, actionNew, + 'Retrieved Action Invoker is not what we expected' + + # Ensure the action invoker is in the list of all existing ones + @db.getActionInvokers ( err , obj ) => + test.deepEqual actionNew, obj[id], + 'Action Invoker ist not in result set' + @db.deleteActionInvoker id + test.done() + + testDelete: ( test ) => + test.expect 2 + + id = 'test-action-invoker' + action = 'unit-test action invoker content' + + # store an entry to start with + @db.storeActionInvoker id, action + + # Ensure the action invoker has been deleted + @db.deleteActionInvoker id + @db.getActionInvoker id, ( err , obj ) => + test.strictEqual obj, null, + 'Action Invoker still exists' + + # Ensure the ID has been removed from the set + @db.getActionInvokerIds ( err , obj ) => + test.ok id not in obj, + 'Action Invoker key still exists in set' + test.done() + + + testFetchSeveral: ( test ) => + test.expect 3 + + semaphore = 2 + action1name = 'test-action-invoker_1' + action2name = 'test-action-invoker_2' + action1 = 'unit-test action invoker 1 content' + action2 = 'unit-test action invoker 2 content' + + fCheckInvoker = ( modname, mod ) => + myTest = test + forkEnds = () -> + myTest.done() if --semaphore is 0 + ( err, obj ) => + myTest.strictEqual mod, obj, + "Invoker #{ modname } does not equal the expected one" + @db.deleteActionInvoker modname + forkEnds() + + @db.storeActionInvoker action1name, action1 + @db.storeActionInvoker action2name, action2 + @db.getActionInvokerIds ( err, obj ) => + test.ok action1name in obj and action2name in obj, + 'Not all action invoker Ids in set' + @db.getActionInvoker action1name, fCheckInvoker action1name, action1 + @db.getActionInvoker action2name, fCheckInvoker action2name, action2 + + +### +# Test ACTION INVOKER PARAMS +### +exports.ActionInvokerParams = + testCreateAndRead: ( test ) => + test.expect 2 + + userId = 'tester1' + actionId = 'test-action-invoker_1' + params = 'shouldn\'t this be an object?' + + # store an entry to start with + @db.storeActionParams actionId, userId, params + + # test that the ID shows up in the set + @db.getActionParamsIds ( err, obj ) => + test.ok actionId+':'+userId in obj, + 'Expected key not in action-params set' + + # the retrieved object really is the one we expected + @db.getActionParams actionId, userId, ( err, obj ) => + test.strictEqual obj, params, + 'Retrieved action params is not what we expected' + @db.deleteActionParams actionId, userId + test.done() + + testUpdate: ( test ) => + test.expect 1 + + userId = 'tester1' + actionId = 'test-action-invoker_1' + params = 'shouldn\'t this be an object?' + paramsNew = 'shouldn\'t this be a new object?' + + # store an entry to start with + @db.storeActionParams actionId, userId, params + @db.storeActionParams actionId, userId, paramsNew + + # the retrieved object really is the one we expected + @db.getActionParams actionId, userId, ( err, obj ) => + test.strictEqual obj, paramsNew, + 'Retrieved action params is not what we expected' + @db.deleteActionParams actionId, userId + test.done() + + testDelete: ( test ) => + test.expect 2 + + userId = 'tester1' + actionId = 'test-action-invoker_1' + params = 'shouldn\'t this be an object?' + + # store an entry to start with and delte it right away + @db.storeActionParams actionId, userId, params + @db.deleteActionParams actionId, userId + + # Ensure the action params have been deleted + @db.getActionParams actionId, userId, ( err, obj ) => + test.strictEqual obj, null, + 'Action params still exists' + # Ensure the ID has been removed from the set + @db.getActionParamsIds ( err, obj ) => + test.ok actionId+':'+userId not in obj, + 'Action Params key still exists in set' + test.done() + + +### +# Test EVENT POLLER +### +exports.EventPoller = + testCreateAndRead: ( test ) => + test.expect 3 + + id = 'test-event-poller' + event = 'unit-test event poller content' + + # store an entry to start with + @db.storeEventPoller id, event + + # test that the ID shows up in the set + @db.getEventPollerIds ( err , obj ) => + test.ok id in obj, + 'Expected key not in event-pollers set' + + # the retrieved object really is the one we expected + @db.getEventPoller id, ( err , obj ) => + test.strictEqual obj, event, + 'Retrieved Event Poller is not what we expected' + + # Ensure the event poller is in the list of all existing ones + @db.getEventPollers ( err , obj ) => + test.deepEqual event, obj[id], + 'Event Poller ist not in result set' + @db.deleteEventPoller id + test.done() + + testUpdate: ( test ) => + test.expect 2 + + id = 'test-event-poller' + event = 'unit-test event poller content' + eventNew = 'unit-test event poller new content' + + # store an entry to start with + @db.storeEventPoller id, event + @db.storeEventPoller id, eventNew + + # the retrieved object really is the one we expected + @db.getEventPoller id, ( err , obj ) => + test.strictEqual obj, eventNew, + 'Retrieved Event Poller is not what we expected' + + # Ensure the event poller is in the list of all existing ones + @db.getEventPollers ( err , obj ) => + test.deepEqual eventNew, obj[id], + 'Event Poller ist not in result set' + @db.deleteEventPoller id + test.done() + + testDelete: ( test ) => + test.expect 2 + + id = 'test-event-poller' + event = 'unit-test event poller content' + + # store an entry to start with + @db.storeEventPoller id, event + + # Ensure the event poller has been deleted + @db.deleteEventPoller id + @db.getEventPoller id, ( err , obj ) => + test.strictEqual obj, null, + 'Event Poller still exists' + + # Ensure the ID has been removed from the set + @db.getEventPollerIds ( err , obj ) => + test.ok id not in obj, + 'Event Poller key still exists in set' + test.done() + + + testFetchSeveral: ( test ) => + test.expect 3 + + semaphore = 2 + event1name = 'test-event-poller_1' + event2name = 'test-event-poller_2' + event1 = 'unit-test event poller 1 content' + event2 = 'unit-test event poller 2 content' + + fCheckPoller = ( modname, mod ) => + myTest = test + forkEnds = () -> + myTest.done() if --semaphore is 0 + ( err, obj ) => + myTest.strictEqual mod, obj, + "Invoker #{ modname } does not equal the expected one" + @db.deleteEventPoller modname + forkEnds() + + @db.storeEventPoller event1name, event1 + @db.storeEventPoller event2name, event2 + @db.getEventPollerIds ( err, obj ) => + test.ok event1name in obj and event2name in obj, + 'Not all event poller Ids in set' + @db.getEventPoller event1name, fCheckPoller event1name, event1 + @db.getEventPoller event2name, fCheckPoller event2name, event2 + + +### +# Test EVENT POLLER PARAMS +### +exports.EventPollerParams = + testCreateAndRead: ( test ) => + test.expect 2 + + userId = 'tester1' + eventId = 'test-event-poller_1' + params = 'shouldn\'t this be an object?' + + # store an entry to start with + @db.storeEventParams eventId, userId, params + + # test that the ID shows up in the set + @db.getEventParamsIds ( err, obj ) => + test.ok eventId+':'+userId in obj, + 'Expected key not in event-params set' + + # the retrieved object really is the one we expected + @db.getEventParams eventId, userId, ( err, obj ) => + test.strictEqual obj, params, + 'Retrieved event params is not what we expected' + @db.deleteEventParams eventId, userId + test.done() + + testUpdate: ( test ) => + test.expect 1 + + userId = 'tester1' + eventId = 'test-event-poller_1' + params = 'shouldn\'t this be an object?' + paramsNew = 'shouldn\'t this be a new object?' + + # store an entry to start with + @db.storeEventParams eventId, userId, params + @db.storeEventParams eventId, userId, paramsNew + + # the retrieved object really is the one we expected + @db.getEventParams eventId, userId, ( err, obj ) => + test.strictEqual obj, paramsNew, + 'Retrieved event params is not what we expected' + @db.deleteEventParams eventId, userId + test.done() + + testDelete: ( test ) => + test.expect 2 + + userId = 'tester1' + eventId = 'test-event-poller_1' + params = 'shouldn\'t this be an object?' + + # store an entry to start with and delete it right away + @db.storeEventParams eventId, userId, params + @db.deleteEventParams eventId, userId + + # Ensure the event params have been deleted + @db.getEventParams eventId, userId, ( err, obj ) => + test.strictEqual obj, null, + 'Event params still exists' + # Ensure the ID has been removed from the set + @db.getEventParamsIds ( err, obj ) => + test.ok eventId+':'+userId not in obj, + 'Event Params key still exists in set' + test.done() + + +### +# Test RULES +### +exports.Rules = + setUp: ( cb ) => + # @db logType: 1 + @userId = 'tester-1' + @ruleId = 'test-rule_1' + @rule = + "id": "rule_id", + "event": "custom", + "condition": + "property": "yourValue", + "actions": [] + @ruleNew = + "id": "rule_new", + "event": "custom", + "condition": + "property": "yourValue", + "actions": [] + cb() + + tearDown: ( cb ) => + @db.deleteRule @ruleId + cb() + + testCreateAndRead: ( test ) => + test.expect 3 + + # store an entry to start with + @db.storeRule @ruleId, JSON.stringify(@rule) + + # test that the ID shows up in the set + @db.getRuleIds ( err, obj ) => + test.ok @ruleId in obj, + 'Expected key not in rule key set' + + # the retrieved object really is the one we expected + @db.getRule @ruleId, ( err, obj ) => + test.deepEqual JSON.parse(obj), @rule, + 'Retrieved rule is not what we expected' + + # Ensure the rule is in the list of all existing ones + @db.getRules ( err , obj ) => + test.deepEqual @rule, JSON.parse(obj[@ruleId]), + 'Rule not in result set' + @db.deleteRule @ruleId + test.done() + + testUpdate: ( test ) => + test.expect 1 + + # store an entry to start with + @db.storeRule @ruleId, JSON.stringify(@rule) + @db.storeRule @ruleId, JSON.stringify(@ruleNew) + + # the retrieved object really is the one we expected + @db.getRule @ruleId, ( err, obj ) => + test.deepEqual JSON.parse(obj), @ruleNew, + 'Retrieved rule is not what we expected' + @db.deleteRule @ruleId + test.done() + + testDelete: ( test ) => + test.expect 2 + + # store an entry to start with and delete it right away + @db.storeRule @ruleId, JSON.stringify(@rule) + @db.deleteRule @ruleId + + # Ensure the event params have been deleted + @db.getRule @ruleId, ( err, obj ) => + test.strictEqual obj, null, + 'Rule still exists' + + # Ensure the ID has been removed from the set + @db.getRuleIds ( err, obj ) => + test.ok @ruleId not in obj, + 'Rule key still exists in set' + test.done() + + testLink: ( test ) => + test.expect 2 + + # link a rule to the user + @db.linkRule @ruleId, @userId + + # Ensure the user is linked to the rule + @db.getRuleLinkedUsers @ruleId, ( err, obj ) => + test.ok @userId in obj, + "Rule not linked to user #{ @userId }" + + # Ensure the rule is linked to the user + @db.getUserLinkedRules @userId, ( err, obj ) => + test.ok @ruleId in obj, + "User not linked to rule #{ @ruleId }" + test.done() + + testUnlink: ( test ) => + test.expect 2 + + # link and unlink immediately afterwards + @db.linkRule @ruleId, @userId + @db.unlinkRule @ruleId, @userId + + # Ensure the user is linked to the rule + @db.getRuleLinkedUsers @ruleId, ( err, obj ) => + test.ok @userId not in obj, + "Rule still linked to user #{ @userId }" + + # Ensure the rule is linked to the user + @db.getUserLinkedRules @userId, ( err, obj ) => + test.ok @ruleId not in obj, + "User still linked to rule #{ @ruleId }" + test.done() + + testActivate: ( test ) => + test.expect 4 + + usr = + username: "tester-1" + password: "tester-1" + @db.storeUser usr + @db.activateRule @ruleId, @userId + # activate a rule for a user + + # Ensure the user is activated to the rule + @db.getRuleActivatedUsers @ruleId, ( err, obj ) => + test.ok @userId in obj, + "Rule not activated for user #{ @userId }" + + # Ensure the rule is linked to the user + @db.getUserActivatedRules @userId, ( err, obj ) => + test.ok @ruleId in obj, + "User not activated for rule #{ @ruleId }" + + # Ensure the rule is showing up in all active rules + @db.getAllActivatedRuleIdsPerUser ( err, obj ) => + test.notStrictEqual obj[@userId], undefined, + "User #{ @userId } not in activated rules set" + if obj[@userId] + test.ok @ruleId in obj[@userId], + "Rule #{ @ruleId } not in activated rules set" + # else + # test.ok true, + # "Dummy so we meet the expected num of tests" + test.done() + + testDeactivate: ( test ) => + test.expect 3 + + # store an entry to start with and link it to te user + @db.activateRule @ruleId, @userId + @db.deactivateRule @ruleId, @userId + + # Ensure the user is linked to the rule + @db.getRuleActivatedUsers @ruleId, ( err, obj ) => + test.ok @userId not in obj, + "Rule still activated for user #{ @userId }" + + # Ensure the rule is linked to the user + @db.getUserActivatedRules @userId, ( err, obj ) => + test.ok @ruleId not in obj, + "User still activated for rule #{ @ruleId }" + + # Ensure the rule is showing up in all active rules + @db.getAllActivatedRuleIdsPerUser ( err, obj ) => + if obj[@userId] + test.ok @ruleId not in obj[@userId], + "Rule #{ @ruleId } still in activated rules set" + else + test.ok true, + "We are fine since there are no entries for this user anymore" + test.done() + + testUnlinkAndDeactivateAfterDeletion: ( test ) => + test.expect 2 + + # store an entry to start with and link it to te user + @db.storeRule @ruleId, JSON.stringify(@rule) + @db.linkRule @ruleId, @userId + @db.activateRule @ruleId, @userId + + # We need to wait here and there since these calls are asynchronous + fWaitForTest = () => + + # Ensure the user is unlinked to the rule + @db.getUserLinkedRules @userId, ( err, obj ) => + test.ok @ruleId not in obj, + "Rule #{ @ruleId } still linked to user #{ @userId }" + + # Ensure the rule is deactivated for the user + @db.getUserActivatedRules @userId, ( err, obj ) => + test.ok @ruleId not in obj, + "Rule #{ @ruleId } still activated for user #{ @userId }" + test.done() + + fWaitForDeletion = () => + @db.deleteRule @ruleId + setTimeout fWaitForTest, 100 + + setTimeout fWaitForDeletion, 100 + + +### +# Test USER +### +exports.User = + setUp: ( cb ) => + @oUser = + username: "tester-1" + password: "password" + cb() + tearDown: ( cb ) => + @db.deleteUser @oUser.username + cb() + + testCreateInvalid: ( test ) => + test.expect 4 + + oUserInvOne = + username: "tester-1-invalid" + oUserInvTwo = + password: "password" + + # try to store invalid users, ensure they weren't + @db.storeUser oUserInvOne + @db.storeUser oUserInvTwo + + @db.getUser oUserInvOne.username, ( err, obj ) => + test.strictEqual obj, null, + 'User One was stored!?' + + @db.getUser oUserInvTwo.username, ( err, obj ) => + test.strictEqual obj, null, + 'User Two was stored!?' + + @db.getUserIds ( err, obj ) => + test.ok oUserInvOne.username not in obj, + 'User key was stored!?' + test.ok oUserInvTwo.username not in obj, + 'User key was stored!?' + test.done() + + testDelete: ( test ) => + test.expect 2 + + # Store the user + @db.storeUser @oUser + + @db.getUser @oUser.username, ( err, obj ) => + test.deepEqual obj, @oUser, + "User #{ @oUser.username } is not what we expect!" + + @db.getUserIds ( err, obj ) => + test.ok @oUser.username in obj, + 'User key was not stored!?' + test.done() + + testUpdate: ( test ) => + test.expect 2 + + oUserOne = + username: "tester-1-update" + password: "password" + + # Store the user + @db.storeUser oUserOne + oUserOne.password = "password-update" + @db.storeUser oUserOne + + @db.getUser oUserOne.username, ( err, obj ) => + test.deepEqual obj, oUserOne, + "User #{ @oUser.username } is not what we expect!" + + @db.getUserIds ( err, obj ) => + test.ok oUserOne.username in obj, + 'User key was not stored!?' + @db.deleteUser oUserOne.username + test.done() + + testDelete: ( test ) => + test.expect 2 + + # Wait until the user and his rules and roles are deleted + fWaitForDeletion = () => + @db.getUserIds ( err, obj ) => + test.ok @oUser.username not in obj, + 'User key still in set!' + + @db.getUser @oUser.username, ( err, obj ) => + test.strictEqual obj, null, + 'User key still exists!' + test.done() + + # Store the user and make some links + @db.storeUser @oUser + @db.deleteUser @oUser.username + setTimeout fWaitForDeletion, 100 + + + testDeleteLinks: ( test ) => + test.expect 4 + + # Wait until the user and his rules and roles are stored + fWaitForPersistence = () => + @db.deleteUser @oUser.username + setTimeout fWaitForDeletion, 200 + + # Wait until the user and his rules and roles are deleted + fWaitForDeletion = () => + @db.getRoleUsers 'tester', ( err, obj ) => + test.ok @oUser.username not in obj, + 'User key still in role tester!' + + @db.getUserRoles @oUser.username, ( err, obj ) => + test.ok obj.length is 0, + 'User still associated to roles!' + + @db.getUserLinkedRules @oUser.username, ( err, obj ) => + test.ok obj.length is 0, + 'User still associated to rules!' + + @db.getUserActivatedRules @oUser.username, ( err, obj ) => + test.ok obj.length is 0, + 'User still associated to activated rules!' + test.done() + + # Store the user and make some links + @db.storeUser @oUser + @db.linkRule 'rule-1', @oUser.username + @db.linkRule 'rule-2', @oUser.username + @db.linkRule 'rule-3', @oUser.username + @db.activateRule 'rule-1', @oUser.username + @db.storeUserRole @oUser.username, 'tester' + setTimeout fWaitForPersistence, 100 + + + testLogin: ( test ) => + test.expect 3 + + # Store the user and make some links + @db.storeUser @oUser + @db.loginUser @oUser.username, @oUser.password, ( err, obj ) => + test.deepEqual obj, @oUser, + 'User not logged in!' + + @db.loginUser 'dummyname', @oUser.password, ( err, obj ) => + test.strictEqual obj, null, + 'User logged in?!' + + @db.loginUser @oUser.username, 'wrongpass', ( err, obj ) => + test.strictEqual obj, null, + 'User logged in?!' + test.done() + + +### +# Test ROLES +### +exports.Roles = + setUp: ( cb ) => + @db logType: 1 + @oUser = + username: "tester-1" + password: "password" + cb() + tearDown: ( cb ) => + @db.deleteUser @oUser.username + cb() + + testStore: ( test ) => + test.expect 2 + + @db.storeUser @oUser + @db.storeUserRole @oUser.username, 'tester' + + @db.getUserRoles @oUser.username, ( err, obj ) => + test.ok 'tester' in obj, + 'User role tester not stored!' + + @db.getRoleUsers 'tester', ( err, obj ) => + test.ok @oUser.username in obj, + "User #{ @oUser.username } not stored in role tester!" + + test.done() + + testDelete: ( test ) => + test.expect 2 + + @db.storeUser @oUser + @db.storeUserRole @oUser.username, 'tester' + @db.removeUserRole @oUser.username, 'tester' + + @db.getUserRoles @oUser.username, ( err, obj ) => + test.ok 'tester' not in obj, + 'User role tester not stored!' + + @db.getRoleUsers 'tester', ( err, obj ) => + test.ok @oUser.username not in obj, + "User #{ @oUser.username } not stored in role tester!" + + test.done()