@depup/fakeredis 2.0.0-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codeclimate.yml +15 -0
- package/.editorconfig +16 -0
- package/.jshintrc +6 -0
- package/.travis.yml +14 -0
- package/Changelog.md +53 -0
- package/README.md +31 -0
- package/changes.json +10 -0
- package/covertest +16 -0
- package/lib/backend.js +1951 -0
- package/lib/connection.js +474 -0
- package/lib/helpers.js +172 -0
- package/main.js +268 -0
- package/package.json +56 -0
- package/redis.test.js +2352 -0
- package/runtest +10 -0
- package/test.js +1025 -0
package/main.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// By default fakeredis simulates a ridiculous amount of network latency
|
|
4
|
+
// to help you discover race-conditions when testing multi-client setups.
|
|
5
|
+
// Instantiate your 'clients' with a truthy .fast option,
|
|
6
|
+
// or set it here globally to make things go a bit faster.
|
|
7
|
+
|
|
8
|
+
exports.fast = false;
|
|
9
|
+
|
|
10
|
+
var index = require("redis")
|
|
11
|
+
, Backend = require("./lib/backend").Backend
|
|
12
|
+
, Connection = require("./lib/connection").Connection
|
|
13
|
+
, helpers = require("./lib/helpers")
|
|
14
|
+
|
|
15
|
+
, backends = {}
|
|
16
|
+
, RedisClient = index.RedisClient
|
|
17
|
+
|
|
18
|
+
, anon = 0;
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
// Re-export redis exports.
|
|
22
|
+
|
|
23
|
+
exports.RedisClient = index.RedisClient;
|
|
24
|
+
exports.Multi = index.Multi;
|
|
25
|
+
exports.print = index.print;
|
|
26
|
+
exports.backends = backends;
|
|
27
|
+
|
|
28
|
+
// Overriden client factory.
|
|
29
|
+
|
|
30
|
+
exports.createClient = function(port, host, options) {
|
|
31
|
+
if (arguments.length == 1 && typeof port == "object") {
|
|
32
|
+
options = port;
|
|
33
|
+
if (options.port || options.host) {
|
|
34
|
+
port = options.port;
|
|
35
|
+
host = options.host;
|
|
36
|
+
}
|
|
37
|
+
if (options.url || options.path) {
|
|
38
|
+
host = options.url || options.path;
|
|
39
|
+
port = "";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
var id = !port && !host ? 'fake_' + (++anon) : (host || "") + ((port) ? ":" + port : null || "")
|
|
43
|
+
, lat = options && options.fast || exports.fast ? 1 : null
|
|
44
|
+
, c = new Connection(backends[id] || (backends[id] = new Backend), lat, lat)
|
|
45
|
+
, real_create_stream = RedisClient.prototype.create_stream
|
|
46
|
+
, returnBuffers = options && options.return_buffers
|
|
47
|
+
, detectBuffers = options && options.detect_buffers;
|
|
48
|
+
|
|
49
|
+
// Mock create_stream to create a new RedisClient without creating a socket
|
|
50
|
+
RedisClient.prototype.create_stream = function () {
|
|
51
|
+
this.connected = true;
|
|
52
|
+
this.ready = true;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
var cl = new RedisClient(/* options */)
|
|
56
|
+
|
|
57
|
+
// Replace the mocked create_stream function again with the original one
|
|
58
|
+
RedisClient.prototype.create_stream = real_create_stream;
|
|
59
|
+
|
|
60
|
+
if (options && options.verbose)
|
|
61
|
+
c.verbose = true;
|
|
62
|
+
|
|
63
|
+
cl.end = function() {
|
|
64
|
+
cl.send_command = function(command) {
|
|
65
|
+
throw new Error("fakeredis: You've closed this connection with .end(), cannot " + command);
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
cl.send_command = function(command, args, callback) {
|
|
70
|
+
|
|
71
|
+
// Interpret arguments, copy-paste from mranney/redis/index.js for best compat.
|
|
72
|
+
if (typeof command !== "string") {
|
|
73
|
+
throw new Error("First argument to send_command must be the command name string, not " + typeof command);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (Array.isArray(args)) {
|
|
77
|
+
if (typeof callback === "function") {
|
|
78
|
+
// probably the fastest way:
|
|
79
|
+
// client.command([arg1, arg2], cb); (straight passthrough)
|
|
80
|
+
// send_command(command, [arg1, arg2], cb);
|
|
81
|
+
} else if (! callback) {
|
|
82
|
+
// most people find this variable argument length form more convenient, but it uses arguments, which is slower
|
|
83
|
+
// client.command(arg1, arg2, cb); (wraps up arguments into an array)
|
|
84
|
+
// send_command(command, [arg1, arg2, cb]);
|
|
85
|
+
// client.command(arg1, arg2); (callback is optional)
|
|
86
|
+
// send_command(command, [arg1, arg2]);
|
|
87
|
+
// client.command(arg1, arg2, undefined); (callback is undefined)
|
|
88
|
+
// send_command(command, [arg1, arg2, undefined]);
|
|
89
|
+
var last_arg_type = typeof args[args.length - 1];
|
|
90
|
+
if (last_arg_type === "function" || last_arg_type === "undefined") {
|
|
91
|
+
callback = args.pop();
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
throw new Error("send_command: last argument must be a callback or undefined");
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
throw new Error("send_command: second argument must be an array");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// if the last argument is an array, expand it out. This allows commands like this:
|
|
101
|
+
// client.command(arg1, [arg2, arg3, arg4], cb);
|
|
102
|
+
// and converts to:
|
|
103
|
+
// client.command(arg1, arg2, arg3, arg4, cb);
|
|
104
|
+
// which is convenient for some things like sadd
|
|
105
|
+
if (Array.isArray(args[args.length - 1])) {
|
|
106
|
+
args = args.slice(0, - 1).concat(args[args.length - 1]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
// Arg check.
|
|
111
|
+
|
|
112
|
+
var useBuffers = returnBuffers;
|
|
113
|
+
var i, n;
|
|
114
|
+
n = args.length;
|
|
115
|
+
for (i = 0; i < n; i++) {
|
|
116
|
+
var arg = args[i];
|
|
117
|
+
|
|
118
|
+
// buf support
|
|
119
|
+
if (Buffer.isBuffer(arg)) {
|
|
120
|
+
args[i] = packageBuffer(arg);
|
|
121
|
+
if (detectBuffers)
|
|
122
|
+
useBuffers = true;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// lint
|
|
126
|
+
else if (typeof arg !== 'string' && typeof arg !== 'number') {
|
|
127
|
+
var err = new Error("fakeredis/lint: Argument #" + i + " for " + command + " is not a String, Buffer or Number: " + arg);
|
|
128
|
+
if (callback)
|
|
129
|
+
return callback(err);
|
|
130
|
+
else
|
|
131
|
+
throw err;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
// Callback middleware.
|
|
137
|
+
|
|
138
|
+
if (callback) {
|
|
139
|
+
|
|
140
|
+
// hgetall sugar
|
|
141
|
+
if (/^hgetall/i.test(command))
|
|
142
|
+
callback = makeReplyToObjectAdaptor(callback);
|
|
143
|
+
|
|
144
|
+
// buffer support
|
|
145
|
+
callback = makeUnpackageBuffersAdaptor(useBuffers, callback);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
//
|
|
150
|
+
|
|
151
|
+
c.push(this, command, args, callback);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
cl.pushMessage = cl.emit.bind(cl);
|
|
155
|
+
|
|
156
|
+
(function() {
|
|
157
|
+
var prop;
|
|
158
|
+
for (prop in helpers)
|
|
159
|
+
cl[prop] = helpers[prop];
|
|
160
|
+
}
|
|
161
|
+
());
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
// Schedule some events.
|
|
165
|
+
|
|
166
|
+
process.nextTick(function() {
|
|
167
|
+
cl.ready = true;
|
|
168
|
+
cl.emit('ready');
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
//
|
|
173
|
+
return cl;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
//
|
|
178
|
+
|
|
179
|
+
function makeReplyToObjectAdaptor(callback) {
|
|
180
|
+
return function(err, data) {
|
|
181
|
+
if (!err && data)
|
|
182
|
+
data = reply_to_object(data);
|
|
183
|
+
|
|
184
|
+
callback(err, data);
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function makeUnpackageBuffersAdaptor(returnAsBuffers, callback) {
|
|
189
|
+
return function(err, data) {
|
|
190
|
+
if (!err)
|
|
191
|
+
data = returnAsBuffers
|
|
192
|
+
? unpackageBuffersAsObjects(data)
|
|
193
|
+
: unpackageBuffersAsStrings(data);
|
|
194
|
+
|
|
195
|
+
callback(err, data);
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
// Helpers for node_redis compat.
|
|
201
|
+
|
|
202
|
+
// hgetall converts its replies to an Object. If the reply is empty, null is returned.
|
|
203
|
+
function reply_to_object(reply) {
|
|
204
|
+
var obj = {}, j, jl, key, val;
|
|
205
|
+
|
|
206
|
+
if (reply.length === 0) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
for (j = 0, jl = reply.length; j < jl; j += 2) {
|
|
211
|
+
key = reply[j].toString();
|
|
212
|
+
val = reply[j + 1];
|
|
213
|
+
obj[key] = val;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return obj;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
// I realize this is possibly the most idiotic way to add support for buffers.
|
|
221
|
+
|
|
222
|
+
var BUFFER_PREFIX = "\t!bUF?!1\t";
|
|
223
|
+
|
|
224
|
+
function packageBuffer(buf) {
|
|
225
|
+
|
|
226
|
+
// If possible, try storing the buffer as a utf8 string.
|
|
227
|
+
// For this to work baking the string back to a buffer must yield the exact same bytes.
|
|
228
|
+
var asString = buf.toString('utf8');
|
|
229
|
+
var enc = new Buffer(asString, 'utf8');
|
|
230
|
+
var n = enc.length;
|
|
231
|
+
if (n === buf.length) {
|
|
232
|
+
var ok = true;
|
|
233
|
+
while (n--)
|
|
234
|
+
if (buf[n] !== enc[n]) {
|
|
235
|
+
ok = false;
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (ok)
|
|
240
|
+
return asString;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// If not possible, keep the buffer as a prefixed, base64 encoded string internally.
|
|
244
|
+
return BUFFER_PREFIX + buf.toString('base64');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function unpackageBuffersAsObjects(data) {
|
|
248
|
+
if (Array.isArray(data))
|
|
249
|
+
return data.map(unpackageBuffersAsObjects);
|
|
250
|
+
|
|
251
|
+
if (typeof data === 'string' && data.indexOf(BUFFER_PREFIX) === 0)
|
|
252
|
+
return new Buffer(data.substr(BUFFER_PREFIX.length), 'base64');
|
|
253
|
+
else if (data)
|
|
254
|
+
return new Buffer(data.toString(), 'utf8');
|
|
255
|
+
else
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function unpackageBuffersAsStrings(data) {
|
|
260
|
+
if (Array.isArray(data))
|
|
261
|
+
return data.map(unpackageBuffersAsStrings);
|
|
262
|
+
|
|
263
|
+
if (typeof data === 'string' && data.indexOf(BUFFER_PREFIX) === 0)
|
|
264
|
+
return new Buffer(data.substr(BUFFER_PREFIX.length), 'base64').toString('utf8');
|
|
265
|
+
else
|
|
266
|
+
return data;
|
|
267
|
+
}
|
|
268
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@depup/fakeredis",
|
|
3
|
+
"version": "2.0.0-depup.0",
|
|
4
|
+
"description": "Fake redis for testing, works as a drop-in replacement for node_redis (with updated dependencies)",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"fakeredis",
|
|
7
|
+
"depup",
|
|
8
|
+
"updated-dependencies",
|
|
9
|
+
"security",
|
|
10
|
+
"latest",
|
|
11
|
+
"patched",
|
|
12
|
+
"test",
|
|
13
|
+
"spec",
|
|
14
|
+
"fake",
|
|
15
|
+
"redis",
|
|
16
|
+
"simulated",
|
|
17
|
+
"implementation",
|
|
18
|
+
"client"
|
|
19
|
+
],
|
|
20
|
+
"author": "Hristo Dachev <tutini@gmail.com>",
|
|
21
|
+
"main": "./main.js",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"redis": "^5.11.0"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"mail": "tutini@gmail.com",
|
|
28
|
+
"url": "http://github.com/hdachev/fakeredis/issues"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git://github.com/hdachev/fakeredis.git"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"test": "./runtest",
|
|
36
|
+
"coverage": "./covertest"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"coveralls": "^2.11.6",
|
|
40
|
+
"istanbul": "^0.4.2",
|
|
41
|
+
"lcov-result-merger": "^1.0.2"
|
|
42
|
+
},
|
|
43
|
+
"depup": {
|
|
44
|
+
"changes": {
|
|
45
|
+
"redis": {
|
|
46
|
+
"from": "2.6.0-0",
|
|
47
|
+
"to": "^5.11.0"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"depsUpdated": 1,
|
|
51
|
+
"originalPackage": "fakeredis",
|
|
52
|
+
"originalVersion": "2.0.0",
|
|
53
|
+
"processedAt": "2026-03-19T03:03:52.393Z",
|
|
54
|
+
"smokeTest": "passed"
|
|
55
|
+
}
|
|
56
|
+
}
|