UNPKG

redis-mock

Version:

Redis client mock object for unit testing

419 lines (346 loc) 9.79 kB
/** * Module dependencies */ const Item = require("./item.js"); const helpers = require('../helpers'); const patternToRegex = require('../helpers').patternToRegex; /** * Hget */ exports.hget = function (hash, key, callback) { var value = null; var err = null; if (this.storage[hash]) { if (this.storage[hash].type === "hash") { if (this.storage[hash].value.hasOwnProperty(key)) { value = this.storage[hash].value[key]; } else { value = null; } } else { err = new Error("ERR Operation against a key holding the wrong kind of value"); } } helpers.callCallback(callback, err, value); }; /** * Hexists */ exports.hexists = function (hash, key, callback) { var b = 0; var err = null; if (this.storage[hash]) { if (this.storage[hash].type === "hash") { b = this.storage[hash].value[key] === undefined ? 0 : 1; } else { err = new Error("ERR Operation against a key holding the wrong kind of value"); } } helpers.callCallback(callback, err, b); }; /** * Hdel */ exports.hdel = function (hash) { var nb = 0; var err = null; // We require at least 3 arguments: // 0: mockInstance // 1: hash name // 2..N-1: key // N: callback (optional) var len = arguments.length; if (len < 2) { return; } var callback; if ('function' === typeof arguments[len - 1]) { callback = arguments[len-1]; } if (this.storage[hash]) { if (this.storage[hash].type === "hash") { for (var i = 1; i < len; i += 1) { if (len <= (i + 1)) { // should skip the callback here break; } var k = arguments[i]; if (this.storage[hash].value[k]) { delete this.storage[hash].value[k]; nb++; } } } else { err = new Error("ERR Operation against a key holding the wrong kind of value"); } } // Do we have a callback? if (callback) { helpers.callCallback(callback, err, nb); } }; /* * Hset */ exports.hset = function (hash, key, value, callback) { var update = false; if (this.storage[hash]) { if (this.storage[hash].type !== "hash") { return helpers.callCallback(callback, new Error("ERR Operation against a key holding the wrong kind of value")); } if (this.storage[hash].value[key]) { update = true; } } else { this.storage[hash] = Item.createHash(); } this.storage[hash].value[key] = value.toString(); helpers.callCallback(callback, null, update ? 0 : 1); }; /** * Hsetnx */ exports.hsetnx = function (hash, key, value, callback) { if (!this.storage[hash] || this.storage[hash].type !== "hash" || !this.storage[hash].value[key]) { this.hset(hash, key, value, callback); } else { helpers.callCallback(callback, null, 0); } }; /** * Hincrby */ exports.hincrby = function (hash, key, increment, callback) { if (this.storage[hash]) { if (this.storage[hash].type !== "hash") { return helpers.callCallback(callback, new Error("ERR Operation against a key holding the wrong kind of value")); } } else { this.storage[hash] = Item.createHash(); } if (this.storage[hash].value[key] && !/^\d+$/.test(this.storage[hash].value[key])) { return helpers.callCallback(callback, new Error("ERR hash value is not an integer")); } this.storage[hash].value[key] = parseInt(this.storage[hash].value[key], 10) || 0; this.storage[hash].value[key] += increment; this.storage[hash].value[key] += ""; //Because HGET returns Strings helpers.callCallback(callback, null, parseInt(this.storage[hash].value[key], 10)); //Because HINCRBY returns integers }; /** * Hincrbyfloat */ exports.hincrbyfloat = function (hash, key, increment, callback) { if (this.storage[hash]) { if (this.storage[hash].type !== "hash") { return helpers.callCallback(callback, new Error("ERR Operation against a key holding the wrong kind of value")); } } else { this.storage[hash] = Item.createHash(); } function isFloat(n) { return n === +n && n !== (n|0); } if (this.storage[hash].value[key] && !isFloat(parseFloat(this.storage[hash].value[key]))) { return helpers.callCallback(callback, new Error("ERR value is not a valid float")); } this.storage[hash].value[key] = parseFloat(this.storage[hash].value[key]) || 0; this.storage[hash].value[key] += parseFloat(increment); //convert to string this.storage[hash].value[key] = this.storage[hash].value[key].toString(); helpers.callCallback(callback, null, this.storage[hash].value[key]); }; /** * Hgetall */ exports.hgetall = function (hash, callback) { // TODO: Confirm if this should return null or empty obj when key does not exist var obj = {}; var nb = 0; if (this.storage[hash] && this.storage[hash].type !== "hash") { return helpers.callCallback(callback, new Error("ERR Operation against a key holding the wrong kind of value")); } if (this.storage[hash]) { for (var k in this.storage[hash].value) { nb++; obj[k] = this.storage[hash].value[k]; } } helpers.callCallback(callback, null, nb === 0 ? null : obj); }; /** * Hscan */ exports.hscan = function (hash, index, pattern, count, callback) { var regex = patternToRegex(pattern); var keyvals = []; var idx = 1; var resIdx = 0; count = count || 10; if (this.storage[hash] && this.storage[hash].type !== "hash") { return helpers.callCallback(callback, null, ['0',[]]); } if (this.storage[hash]) { for (var key in this.storage[hash].value) { if (idx >= index && regex.test(key)) { keyvals.push(key); keyvals.push(this.storage[hash].value[key]); count--; if(count === 0) { resIdx = idx+1; break; } } idx++; } } helpers.callCallback(callback, null, [resIdx.toString(), keyvals]); }; /** * Hkeys */ exports.hkeys = function (hash, callback) { var list = []; if (this.storage[hash] && this.storage[hash].type !== "hash") { return helpers.callCallback(callback, new Error("ERR Operation against a key holding the wrong kind of value")); } if (this.storage[hash]) { for (var k in this.storage[hash].value) { list.push(k); } } helpers.callCallback(callback, null, list); }; /** * Hvals */ exports.hvals = function (hash, callback) { var list = []; if (this.storage[hash] && this.storage[hash].type !== "hash") { return helpers.callCallback(callback, new Error("ERR Operation against a key holding the wrong kind of value")); } if (this.storage[hash]) { for (var k in this.storage[hash].value) { list.push(this.storage[hash].value[k]); } } helpers.callCallback(callback, null, list); }; /** * Hmset */ exports.hmset = function (hash) { // We require at least 3 arguments // 0: mockInstance // 1: hash name // 2..N-2: key // 3..N-1: value // N: callback (optional) var len = arguments.length; if (len <= 2) { return; } var callback; if ('function' === typeof arguments[len - 1]) { callback = arguments[len-1]; } // check to see if this hash exists if (this.storage[hash]) { if (this.storage[hash].type !== "hash" && callback) { return helpers.callCallback(callback, new Error("ERR Operation against a key holding the wrong kind of value")); } } else { this.storage[hash] = Item.createHash(); } for (var i = 1; i < len; i += 2) { if (len <= (i + 1)) { // should skip the callback here break; } var k = arguments[i]; var v = arguments[i + 1]; this.storage[hash].value[k] = v.toString(); } // Do we have a callback? if (callback) { helpers.callCallback(callback, null, "OK"); } }; /** * Hmget */ exports.hmget = function (mockInstance) { // We require at least 3 arguments // 1: hash name // 2: key/value object or first key name if (arguments.length <= 2) { if ('function' === typeof arguments[arguments.length - 1]) { helpers.callCallback( arguments[arguments.length - 1], new Error("ERR wrong number of arguments for 'hmget' command"), keyValues ); } return; } var keyValuesToGet = []; for (var i = 1; i < arguments.length; i++) { // Neither key nor value is a callback if ('function' !== typeof arguments[i] && 'function' !== typeof arguments[i]) { keyValuesToGet.push(arguments[i]); } else { break; } } var err = null; var keyValues = null; var hash = arguments[0]; if (this.storage[hash]) { if (this.storage[hash].type !== "hash") { err = new Error("ERR Operation against a key holding the wrong kind of value"); } else { keyValues = []; for (var k in keyValuesToGet) { keyValues.push(this.storage[hash].value[keyValuesToGet[k]] || null); } } } else { keyValues = []; for (k in keyValuesToGet) { keyValues.push(null); } } // Do we have a callback? if ('function' === typeof arguments[arguments.length - 1]) { helpers.callCallback(arguments[arguments.length - 1], err, keyValues); } }; /** * Hlen */ exports.hlen = function (hash, callback) { if (!this.storage[hash]) { return helpers.callCallback(callback, null, 0); } if (this.storage[hash].type !== "hash") { return helpers.callCallback(callback, new Error("ERR Operation against a key holding the wrong kind of value")); } var cnt = 0; for (var p in this.storage[hash].value) { if (this.storage[hash].value.hasOwnProperty(p)) { // eslint-disable-line no-prototype-builtins cnt++; } } helpers.callCallback(callback, null, cnt); };