Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / redis / test.js
1 /*global require console setTimeout process Buffer */
2 var redis = require("./index"),
3     client = redis.createClient(),
4     client2 = redis.createClient(),
5     client3 = redis.createClient(),
6     assert = require("assert"),
7     crypto = require("crypto"),
8     util = require("./lib/util"),
9     test_db_num = 15, // this DB will be flushed and used for testing
10     tests = {},
11     connected = false,
12     ended = false,
13     next, cur_start, run_next_test, all_tests, all_start, test_count;
14
15 // Set this to truthy to see the wire protocol and other debugging info
16 redis.debug_mode = process.argv[2];
17
18 function buffers_to_strings(arr) {
19     return arr.map(function (val) {
20         return val.toString();
21     });
22 }
23
24 function require_number(expected, label) {
25     return function (err, results) {
26         assert.strictEqual(null, err, label + " expected " + expected + ", got error: " + err);
27         assert.strictEqual(expected, results, label + " " + expected + " !== " + results);
28         assert.strictEqual(typeof results, "number", label);
29         return true;
30     };
31 }
32
33 function require_number_any(label) {
34     return function (err, results) {
35         assert.strictEqual(null, err, label + " expected any number, got error: " + err);
36         assert.strictEqual(typeof results, "number", label + " " + results + " is not a number");
37         return true;
38     };
39 }
40
41 function require_number_pos(label) {
42     return function (err, results) {
43         assert.strictEqual(null, err, label + " expected positive number, got error: " + err);
44         assert.strictEqual(true, (results > 0), label + " " + results + " is not a positive number");
45         return true;
46     };
47 }
48
49 function require_string(str, label) {
50     return function (err, results) {
51         assert.strictEqual(null, err, label + " expected string '" + str + "', got error: " + err);
52         assert.equal(str, results, label + " " + str + " does not match " + results);
53         return true;
54     };
55 }
56
57 function require_null(label) {
58     return function (err, results) {
59         assert.strictEqual(null, err, label + " expected null, got error: " + err);
60         assert.strictEqual(null, results, label + ": " + results + " is not null");
61         return true;
62     };
63 }
64
65 function require_error(label) {
66     return function (err, results) {
67         assert.notEqual(err, null, label + " err is null, but an error is expected here.");
68         return true;
69     };
70 }
71
72 function is_empty_array(obj) {
73     return Array.isArray(obj) && obj.length === 0;
74 }
75
76 function last(name, fn) {
77     return function (err, results) {
78         fn(err, results);
79         next(name);
80     };
81 }
82
83 next = function next(name) {
84     console.log(" \x1b[33m" + (Date.now() - cur_start) + "\x1b[0m ms");
85     run_next_test();
86 };
87
88 // Tests are run in the order they are defined.  So FLUSHDB should be stay first.
89
90 tests.FLUSHDB = function () {
91     var name = "FLUSHDB";
92     client.select(test_db_num, require_string("OK", name));
93     client2.select(test_db_num, require_string("OK", name));
94     client3.select(test_db_num, require_string("OK", name));
95     client.mset("flush keys 1", "flush val 1", "flush keys 2", "flush val 2", require_string("OK", name));
96     client.FLUSHDB(require_string("OK", name));
97     client.dbsize(last(name, require_number(0, name)));
98 };
99
100 tests.MULTI_1 = function () {
101     var name = "MULTI_1", multi1, multi2;
102
103     // Provoke an error at queue time
104     multi1 = client.multi();
105     multi1.mset("multifoo", "10", "multibar", "20", require_string("OK", name));
106     multi1.set("foo2", require_error(name));
107     multi1.incr("multifoo", require_number(11, name));
108     multi1.incr("multibar", require_number(21, name));
109     multi1.exec();
110
111     // Confirm that the previous command, while containing an error, still worked.
112     multi2 = client.multi();
113     multi2.incr("multibar", require_number(22, name));
114     multi2.incr("multifoo", require_number(12, name));
115     multi2.exec(function (err, replies) {
116         assert.strictEqual(22, replies[0]);
117         assert.strictEqual(12, replies[1]);
118         next(name);
119     });
120 };
121
122 tests.MULTI_2 = function () {
123     var name = "MULTI_2";
124
125     // test nested multi-bulk replies
126     client.multi([
127         ["mget", "multifoo", "multibar", function (err, res) {
128             assert.strictEqual(2, res.length, name);
129             assert.strictEqual("12", res[0].toString(), name);
130             assert.strictEqual("22", res[1].toString(), name);
131         }],
132         ["set", "foo2", require_error(name)],
133         ["incr", "multifoo", require_number(13, name)],
134         ["incr", "multibar", require_number(23, name)]
135     ]).exec(function (err, replies) {
136         assert.strictEqual(2, replies[0].length, name);
137         assert.strictEqual("12", replies[0][0].toString(), name);
138         assert.strictEqual("22", replies[0][1].toString(), name);
139
140         assert.strictEqual("13", replies[1].toString());
141         assert.strictEqual("23", replies[2].toString());
142         next(name);
143     });
144 };
145
146 tests.MULTI_3 = function () {
147     var name = "MULTI_3";
148
149     client.sadd("some set", "mem 1");
150     client.sadd("some set", "mem 2");
151     client.sadd("some set", "mem 3");
152     client.sadd("some set", "mem 4");
153
154     // make sure empty mb reply works
155     client.del("some missing set");
156     client.smembers("some missing set", function (err, reply) {
157         // make sure empty mb reply works
158         assert.strictEqual(true, is_empty_array(reply), name);
159     });
160
161     // test nested multi-bulk replies with empty mb elements.
162     client.multi([
163         ["smembers", "some set"],
164         ["del", "some set"],
165         ["smembers", "some set"]
166     ])
167     .scard("some set")
168     .exec(function (err, replies) {
169         assert.strictEqual(true, is_empty_array(replies[2]), name);
170         next(name);
171     });
172 };
173
174 tests.MULTI_4 = function () {
175     var name = "MULTI_4";
176
177     client.multi()
178         .mset('some', '10', 'keys', '20')
179         .incr('some')
180         .incr('keys')
181         .mget('some', 'keys')
182         .exec(function (err, replies) {
183             assert.strictEqual(null, err);
184             assert.equal('OK', replies[0]);
185             assert.equal(11, replies[1]);
186             assert.equal(21, replies[2]);
187             assert.equal(11, replies[3][0].toString());
188             assert.equal(21, replies[3][1].toString());
189             next(name);
190         });
191 };
192
193 tests.MULTI_5 = function () {
194     var name = "MULTI_5";
195
196     // test nested multi-bulk replies with nulls.
197     client.multi([
198         ["mget", ["multifoo", "some", "random value", "keys"]],
199         ["incr", "multifoo"]
200     ])
201     .exec(function (err, replies) {
202         assert.strictEqual(replies.length, 2, name);
203         assert.strictEqual(replies[0].length, 4, name);
204         next(name);
205     });
206 };
207
208 tests.MULTI_6 = function () {
209     var name = "MULTI_6";
210
211     client.multi()
212         .hmset("multihash", "a", "foo", "b", 1)
213         .hmset("multihash", {
214             extra: "fancy",
215             things: "here"
216         })
217         .hgetall("multihash")
218         .exec(function (err, replies) {
219             assert.strictEqual(null, err);
220             assert.equal("OK", replies[0]);
221             assert.equal(Object.keys(replies[2]).length, 4);
222             assert.equal("foo", replies[2].a);
223             assert.equal("1", replies[2].b);
224             assert.equal("fancy", replies[2].extra);
225             assert.equal("here", replies[2].things);
226             next(name);
227         });
228 };
229
230 tests.EVAL_1 = function () {
231     var name = "EVAL_1";
232
233     if (client.server_info.versions[0] >= 2 && client.server_info.versions[1] >= 5) {
234         // test {EVAL - Lua integer -> Redis protocol type conversion}
235         client.eval("return 100.5", 0, require_number(100, name));
236         // test {EVAL - Lua string -> Redis protocol type conversion}
237         client.eval("return 'hello world'", 0, require_string("hello world", name));
238         // test {EVAL - Lua true boolean -> Redis protocol type conversion}
239         client.eval("return true", 0, require_number(1, name));
240         // test {EVAL - Lua false boolean -> Redis protocol type conversion}
241         client.eval("return false", 0, require_null(name));
242         // test {EVAL - Lua status code reply -> Redis protocol type conversion}
243         client.eval("return {ok='fine'}", 0, require_string("fine", name));
244         // test {EVAL - Lua error reply -> Redis protocol type conversion}
245         client.eval("return {err='this is an error'}", 0, require_error(name));
246         // test {EVAL - Lua table -> Redis protocol type conversion}
247         client.eval("return {1,2,3,'ciao',{1,2}}", 0, function (err, res) {
248             assert.strictEqual(5, res.length, name);
249             assert.strictEqual(1, res[0], name);
250             assert.strictEqual(2, res[1], name);
251             assert.strictEqual(3, res[2], name);
252             assert.strictEqual("ciao", res[3], name);
253             assert.strictEqual(2, res[4].length, name);
254             assert.strictEqual(1, res[4][0], name);
255             assert.strictEqual(2, res[4][1], name);
256         });
257         // test {EVAL - Are the KEYS and ARGS arrays populated correctly?}
258         client.eval("return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", 2, "a", "b", "c", "d", function (err, res) {
259             assert.strictEqual(4, res.length, name);
260             assert.strictEqual("a", res[0], name);
261             assert.strictEqual("b", res[1], name);
262             assert.strictEqual("c", res[2], name);
263             assert.strictEqual("d", res[3], name);
264         });
265
266         // prepare sha sum for evalsha cache test
267         var source = "return redis.call('get', 'sha test')",
268             sha = crypto.createHash('sha1').update(source).digest('hex');
269
270         client.set("sha test", "eval get sha test", function (err, res) {
271             if (err) throw err;
272             // test {EVAL - is Lua able to call Redis API?}
273             client.eval(source, 0, function (err, res) {
274                 require_string("eval get sha test", name)(err, res);
275                 // test {EVALSHA - Can we call a SHA1 if already defined?}
276                 client.evalsha(sha, 0, require_string("eval get sha test", name));
277                 // test {EVALSHA - Do we get an error on non defined SHA1?}
278                 client.evalsha("ffffffffffffffffffffffffffffffffffffffff", 0, require_error(name));
279             });
280         });
281
282         // test {EVAL - Redis integer -> Lua type conversion}
283         client.set("incr key", 0, function (err, reply) {
284             if (err) throw err;
285             client.eval("local foo = redis.call('incr','incr key')\n" + "return {type(foo),foo}", 0, function (err, res) {
286                 if (err) throw err;
287                 assert.strictEqual(2, res.length, name);
288                 assert.strictEqual("number", res[0], name);
289                 assert.strictEqual(1, res[1], name);
290             });
291         });
292
293         client.set("bulk reply key", "bulk reply value", function (err, res) {
294             // test {EVAL - Redis bulk -> Lua type conversion}
295             client.eval("local foo = redis.call('get','bulk reply key'); return {type(foo),foo}", 0, function (err, res) {
296                 if (err) throw err;
297                 assert.strictEqual(2, res.length, name);
298                 assert.strictEqual("string", res[0], name);
299                 assert.strictEqual("bulk reply value", res[1], name);
300             });
301         });
302
303         // test {EVAL - Redis multi bulk -> Lua type conversion}
304         client.multi()
305             .del("mylist")
306             .rpush("mylist", "a")
307             .rpush("mylist", "b")
308             .rpush("mylist", "c")
309             .exec(function (err, replies) {
310                 if (err) throw err;
311                 client.eval("local foo = redis.call('lrange','mylist',0,-1); return {type(foo),foo[1],foo[2],foo[3],# foo}", 0, function (err, res) {
312                     assert.strictEqual(5, res.length, name);
313                     assert.strictEqual("table", res[0], name);
314                     assert.strictEqual("a", res[1], name);
315                     assert.strictEqual("b", res[2], name);
316                     assert.strictEqual("c", res[3], name);
317                     assert.strictEqual(3, res[4], name);
318                 });
319             });
320         // test {EVAL - Redis status reply -> Lua type conversion}
321         client.eval("local foo = redis.call('set','mykey','myval'); return {type(foo),foo['ok']}", 0, function (err, res) {
322             if (err) throw err;
323             assert.strictEqual(2, res.length, name);
324             assert.strictEqual("table", res[0], name);
325             assert.strictEqual("OK", res[1], name);
326         });
327         // test {EVAL - Redis error reply -> Lua type conversion}
328         client.set("error reply key", "error reply value", function (err, res) {
329             if (err) throw err;
330             client.eval("local foo = redis.pcall('incr','error reply key'); return {type(foo),foo['err']}", 0, function (err, res) {
331                 if (err) throw err;
332                 assert.strictEqual(2, res.length, name);
333                 assert.strictEqual("table", res[0], name);
334                 assert.strictEqual("ERR value is not an integer or out of range", res[1], name);
335             });
336         });
337         // test {EVAL - Redis nil bulk reply -> Lua type conversion}
338         client.del("nil reply key", function (err, res) {
339             if (err) throw err;
340             client.eval("local foo = redis.call('get','nil reply key'); return {type(foo),foo == false}", 0, function (err, res) {
341                 if (err) throw err;
342                 assert.strictEqual(2, res.length, name);
343                 assert.strictEqual("boolean", res[0], name);
344                 assert.strictEqual(1, res[1], name);
345                 next(name);
346             });
347         });
348     } else {
349         console.log("Skipping " + name + " because server version isn't new enough.");
350         next(name);
351     }
352 };
353
354 tests.WATCH_MULTI = function () {
355     var name = 'WATCH_MULTI', multi;
356
357     if (client.server_info.versions[0] >= 2 && client.server_info.versions[1] >= 1) {
358         client.watch(name);
359         client.incr(name);
360         multi = client.multi();
361         multi.incr(name);
362         multi.exec(last(name, require_null(name)));
363     } else {
364         console.log("Skipping " + name + " because server version isn't new enough.");
365         next(name);
366     }
367 };
368
369 tests.detect_buffers = function () {
370     var name = "detect_buffers", detect_client = redis.createClient(null, null, {detect_buffers: true});
371
372     detect_client.on("ready", function () {
373         // single Buffer or String
374         detect_client.set("string key 1", "string value");
375         detect_client.get("string key 1", require_string("string value", name));
376         detect_client.get(new Buffer("string key 1"), function (err, reply) {
377             assert.strictEqual(null, err, name);
378             assert.strictEqual(true, Buffer.isBuffer(reply), name);
379             assert.strictEqual("<Buffer 73 74 72 69 6e 67 20 76 61 6c 75 65>", reply.inspect(), name);
380         });
381
382         detect_client.hmset("hash key 2", "key 1", "val 1", "key 2", "val 2");
383         // array of Buffers or Strings
384         detect_client.hmget("hash key 2", "key 1", "key 2", function (err, reply) {
385             assert.strictEqual(null, err, name);
386             assert.strictEqual(true, Array.isArray(reply), name);
387             assert.strictEqual(2, reply.length, name);
388             assert.strictEqual("val 1", reply[0], name);
389             assert.strictEqual("val 2", reply[1], name);
390         });
391         detect_client.hmget(new Buffer("hash key 2"), "key 1", "key 2", function (err, reply) {
392             assert.strictEqual(null, err, name);
393             assert.strictEqual(true, Array.isArray(reply));
394             assert.strictEqual(2, reply.length, name);
395             assert.strictEqual(true, Buffer.isBuffer(reply[0]));
396             assert.strictEqual(true, Buffer.isBuffer(reply[1]));
397             assert.strictEqual("<Buffer 76 61 6c 20 31>", reply[0].inspect(), name);
398             assert.strictEqual("<Buffer 76 61 6c 20 32>", reply[1].inspect(), name);
399         });
400
401         // Object of Buffers or Strings
402         detect_client.hgetall("hash key 2", function (err, reply) {
403             assert.strictEqual(null, err, name);
404             assert.strictEqual("object", typeof reply, name);
405             assert.strictEqual(2, Object.keys(reply).length, name);
406             assert.strictEqual("val 1", reply["key 1"], name);
407             assert.strictEqual("val 2", reply["key 2"], name);
408         });
409         detect_client.hgetall(new Buffer("hash key 2"), function (err, reply) {
410             assert.strictEqual(null, err, name);
411             assert.strictEqual("object", typeof reply, name);
412             assert.strictEqual(2, Object.keys(reply).length, name);
413             assert.strictEqual(true, Buffer.isBuffer(reply["key 1"]));
414             assert.strictEqual(true, Buffer.isBuffer(reply["key 2"]));
415             assert.strictEqual("<Buffer 76 61 6c 20 31>", reply["key 1"].inspect(), name);
416             assert.strictEqual("<Buffer 76 61 6c 20 32>", reply["key 2"].inspect(), name);
417         });
418
419         detect_client.quit(function (err, res) {
420             next(name);
421         });
422     });
423 };
424
425 tests.socket_nodelay = function () {
426     var name = "socket_nodelay", c1, c2, c3, ready_count = 0, quit_count = 0;
427
428     c1 = redis.createClient(null, null, {socket_nodelay: true});
429     c2 = redis.createClient(null, null, {socket_nodelay: false});
430     c3 = redis.createClient(null, null);
431
432     function quit_check() {
433         quit_count++;
434
435         if (quit_count === 3) {
436             next(name);
437         }
438     }
439
440     function run() {
441         assert.strictEqual(true, c1.options.socket_nodelay, name);
442         assert.strictEqual(false, c2.options.socket_nodelay, name);
443         assert.strictEqual(true, c3.options.socket_nodelay, name);
444
445         c1.set(["set key 1", "set val"], require_string("OK", name));
446         c1.set(["set key 2", "set val"], require_string("OK", name));
447         c1.get(["set key 1"], require_string("set val", name));
448         c1.get(["set key 2"], require_string("set val", name));
449
450         c2.set(["set key 3", "set val"], require_string("OK", name));
451         c2.set(["set key 4", "set val"], require_string("OK", name));
452         c2.get(["set key 3"], require_string("set val", name));
453         c2.get(["set key 4"], require_string("set val", name));
454
455         c3.set(["set key 5", "set val"], require_string("OK", name));
456         c3.set(["set key 6", "set val"], require_string("OK", name));
457         c3.get(["set key 5"], require_string("set val", name));
458         c3.get(["set key 6"], require_string("set val", name));
459
460         c1.quit(quit_check);
461         c2.quit(quit_check);
462         c3.quit(quit_check);
463     }
464
465     function ready_check() {
466         ready_count++;
467         if (ready_count === 3) {
468             run();
469         }
470     }
471
472     c1.on("ready", ready_check);
473     c2.on("ready", ready_check);
474     c3.on("ready", ready_check);
475 };
476
477 tests.reconnect = function () {
478     var name = "reconnect";
479
480     client.set("recon 1", "one");
481     client.set("recon 2", "two", function (err, res) {
482         // Do not do this in normal programs. This is to simulate the server closing on us.
483         // For orderly shutdown in normal programs, do client.quit()
484         client.stream.destroy();
485     });
486
487     client.on("reconnecting", function on_recon(params) {
488         client.on("connect", function on_connect() {
489             client.select(test_db_num, require_string("OK", name));
490             client.get("recon 1", require_string("one", name));
491             client.get("recon 1", require_string("one", name));
492             client.get("recon 2", require_string("two", name));
493             client.get("recon 2", require_string("two", name));
494             client.removeListener("connect", on_connect);
495             client.removeListener("reconnecting", on_recon);
496             next(name);
497         });
498     });
499 };
500
501 tests.idle = function () {
502   var name = "idle";
503
504   client.on("idle", function on_idle() {
505     client.removeListener("idle", on_idle);
506     next(name);
507   });
508
509   client.set("idle", "test");
510 };
511
512 tests.HSET = function () {
513     var key = "test hash",
514         field1 = new Buffer("0123456789"),
515         value1 = new Buffer("abcdefghij"),
516         field2 = new Buffer(0),
517         value2 = new Buffer(0),
518         name = "HSET";
519
520     client.HSET(key, field1, value1, require_number(1, name));
521     client.HGET(key, field1, require_string(value1.toString(), name));
522
523     // Empty value
524     client.HSET(key, field1, value2, require_number(0, name));
525     client.HGET([key, field1], require_string("", name));
526
527     // Empty key, empty value
528     client.HSET([key, field2, value1], require_number(1, name));
529     client.HSET(key, field2, value2, last(name, require_number(0, name)));
530 };
531
532 tests.HLEN = function () {
533     var key = "test hash",
534         field1 = new Buffer("0123456789"),
535         value1 = new Buffer("abcdefghij"),
536         field2 = new Buffer(0),
537         value2 = new Buffer(0),
538         name = "HSET",
539         timeout = 1000;
540
541     client.HSET(key, field1, value1, function (err, results) {
542         client.HLEN(key, function (err, len) {
543             assert.ok(2 === +len);
544             next(name);
545         });
546     });
547 }
548
549 tests.HMSET_BUFFER_AND_ARRAY = function () {
550     // Saving a buffer and an array to the same key should not error
551     var key = "test hash",
552         field1 = "buffer",
553         value1 = new Buffer("abcdefghij"),
554         field2 = "array",
555         value2 = ["array contents"],
556         name = "HSET";
557
558     client.HMSET(key, field1, value1, field2, value2, last(name, require_string("OK", name)));
559 };
560
561 // TODO - add test for HMSET with optional callbacks
562
563 tests.HMGET = function () {
564     var key1 = "test hash 1", key2 = "test hash 2", name = "HMGET";
565
566     // redis-like hmset syntax
567     client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value", require_string("OK", name));
568
569     // fancy hmset syntax
570     client.HMSET(key2, {
571         "0123456789": "abcdefghij",
572         "some manner of key": "a type of value"
573     }, require_string("OK", name));
574
575     client.HMGET(key1, "0123456789", "some manner of key", function (err, reply) {
576         assert.strictEqual("abcdefghij", reply[0].toString(), name);
577         assert.strictEqual("a type of value", reply[1].toString(), name);
578     });
579
580     client.HMGET(key2, "0123456789", "some manner of key", function (err, reply) {
581         assert.strictEqual("abcdefghij", reply[0].toString(), name);
582         assert.strictEqual("a type of value", reply[1].toString(), name);
583     });
584
585     client.HMGET(key1, ["0123456789"], function (err, reply) {
586         assert.strictEqual("abcdefghij", reply[0], name);
587     });
588
589     client.HMGET(key1, ["0123456789", "some manner of key"], function (err, reply) {
590         assert.strictEqual("abcdefghij", reply[0], name);
591         assert.strictEqual("a type of value", reply[1], name);
592     });
593
594     client.HMGET(key1, "missing thing", "another missing thing", function (err, reply) {
595         assert.strictEqual(null, reply[0], name);
596         assert.strictEqual(null, reply[1], name);
597         next(name);
598     });
599 };
600
601 tests.HINCRBY = function () {
602     var name = "HINCRBY";
603     client.hset("hash incr", "value", 10, require_number(1, name));
604     client.HINCRBY("hash incr", "value", 1, require_number(11, name));
605     client.HINCRBY("hash incr", "value 2", 1, last(name, require_number(1, name)));
606 };
607
608 tests.SUBSCRIBE = function () {
609     var client1 = client, msg_count = 0, name = "SUBSCRIBE";
610
611     client1.on("subscribe", function (channel, count) {
612         if (channel === "chan1") {
613             client2.publish("chan1", "message 1", require_number(1, name));
614             client2.publish("chan2", "message 2", require_number(1, name));
615             client2.publish("chan1", "message 3", require_number(1, name));
616         }
617     });
618
619     client1.on("unsubscribe", function (channel, count) {
620         if (count === 0) {
621             // make sure this connection can go into and out of pub/sub mode
622             client1.incr("did a thing", last(name, require_number(2, name)));
623         }
624     });
625
626     client1.on("message", function (channel, message) {
627         msg_count += 1;
628         assert.strictEqual("message " + msg_count, message.toString());
629         if (msg_count === 3) {
630             client1.unsubscribe("chan1", "chan2");
631         }
632     });
633
634     client1.set("did a thing", 1, require_string("OK", name));
635     client1.subscribe("chan1", "chan2", function (err, results) {
636         assert.strictEqual(null, err, "result sent back unexpected error: " + err);
637         assert.strictEqual("chan1", results.toString(), name);
638     });
639 };
640
641 tests.SUB_UNSUB_SUB = function () {
642     var name = "SUB_UNSUB_SUB";
643     client3.subscribe('chan3');
644     client3.unsubscribe('chan3');
645     client3.subscribe('chan3', function (err, results) {
646         assert.strictEqual(null, err, "unexpected error: " + err);
647         client2.publish('chan3', 'foo');
648     });
649     client3.on('message', function (channel, message) {
650         assert.strictEqual(channel, 'chan3');
651         assert.strictEqual(message, 'foo');
652         next(name);
653     });
654 };
655
656 tests.SUBSCRIBE_QUIT = function () {
657     var name = "SUBSCRIBE_QUIT";
658     client3.on("end", function () {
659         next(name);
660     });
661     client3.on("subscribe", function (channel, count) {
662         client3.quit();
663     });
664     client3.subscribe("chan3");
665 };
666
667 tests.SUBSCRIBE_CLOSE_RESUBSCRIBE = function () {
668     var name = "SUBSCRIBE_CLOSE_RESUBSCRIBE";
669     var c1 = redis.createClient();
670     var c2 = redis.createClient();
671     var count = 0;
672
673     /* Create two clients. c1 subscribes to two channels, c2 will publish to them.
674        c2 publishes the first message.
675        c1 gets the message and drops its connection. It must resubscribe itself.
676        When it resubscribes, c2 publishes the second message, on the same channel
677        c1 gets the message and drops its connection. It must resubscribe itself, again.
678        When it resubscribes, c2 publishes the third message, on the second channel
679        c1 gets the message and drops its connection. When it reconnects, the test ends.
680     */
681
682     c1.on("message", function(channel, message) {
683         if (channel === "chan1") {
684             assert.strictEqual(message, "hi on channel 1");
685             c1.stream.end();
686
687         } else if (channel === "chan2") {
688             assert.strictEqual(message, "hi on channel 2");
689             c1.stream.end();
690
691         } else {
692             c1.quit();
693             c2.quit();
694             assert.fail("test failed");
695         }
696     })
697
698     c1.subscribe("chan1", "chan2");
699
700     c2.once("ready", function() {
701         console.log("c2 is ready");
702         c1.on("ready", function(err, results) {
703             console.log("c1 is ready", count);
704
705             count++;
706             if (count == 1) {
707                 c2.publish("chan1", "hi on channel 1");
708                 return;
709
710             } else if (count == 2) {
711                 c2.publish("chan2", "hi on channel 2");
712
713             } else {
714                 c1.quit(function() {
715                     c2.quit(function() {
716                         next(name);
717                     });
718                 });
719             }
720         });
721
722         c2.publish("chan1", "hi on channel 1");
723
724     });
725 };
726
727 tests.EXISTS = function () {
728     var name = "EXISTS";
729     client.del("foo", "foo2", require_number_any(name));
730     client.set("foo", "bar", require_string("OK", name));
731     client.EXISTS("foo", require_number(1, name));
732     client.EXISTS("foo2", last(name, require_number(0, name)));
733 };
734
735 tests.DEL = function () {
736     var name = "DEL";
737     client.DEL("delkey", require_number_any(name));
738     client.set("delkey", "delvalue", require_string("OK", name));
739     client.DEL("delkey", require_number(1, name));
740     client.exists("delkey", require_number(0, name));
741     client.DEL("delkey", require_number(0, name));
742     client.mset("delkey", "delvalue", "delkey2", "delvalue2", require_string("OK", name));
743     client.DEL("delkey", "delkey2", last(name, require_number(2, name)));
744 };
745
746 tests.TYPE = function () {
747     var name = "TYPE";
748     client.set(["string key", "should be a string"], require_string("OK", name));
749     client.rpush(["list key", "should be a list"], require_number_pos(name));
750     client.sadd(["set key", "should be a set"], require_number_any(name));
751     client.zadd(["zset key", "10.0", "should be a zset"], require_number_any(name));
752     client.hset(["hash key", "hashtest", "should be a hash"], require_number_any(0, name));
753
754     client.TYPE(["string key"], require_string("string", name));
755     client.TYPE(["list key"], require_string("list", name));
756     client.TYPE(["set key"], require_string("set", name));
757     client.TYPE(["zset key"], require_string("zset", name));
758     client.TYPE("not here yet", require_string("none", name));
759     client.TYPE(["hash key"], last(name, require_string("hash", name)));
760 };
761
762 tests.KEYS = function () {
763     var name = "KEYS";
764     client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], require_string("OK", name));
765     client.KEYS(["test keys*"], function (err, results) {
766         assert.strictEqual(null, err, "result sent back unexpected error: " + err);
767         assert.strictEqual(2, results.length, name);
768         assert.strictEqual("test keys 1", results[0].toString(), name);
769         assert.strictEqual("test keys 2", results[1].toString(), name);
770         next(name);
771     });
772 };
773
774 tests.MULTIBULK_ZERO_LENGTH = function () {
775     var name = "MULTIBULK_ZERO_LENGTH";
776     client.KEYS(['users:*'], function (err, results) {
777         assert.strictEqual(null, err, 'error on empty multibulk reply');
778         assert.strictEqual(true, is_empty_array(results), "not an empty array");
779         next(name);
780     });
781 };
782
783 tests.RANDOMKEY = function () {
784     var name = "RANDOMKEY";
785     client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], require_string("OK", name));
786     client.RANDOMKEY([], function (err, results) {
787         assert.strictEqual(null, err, name + " result sent back unexpected error: " + err);
788         assert.strictEqual(true, /\w+/.test(results), name);
789         next(name);
790     });
791 };
792
793 tests.RENAME = function () {
794     var name = "RENAME";
795     client.set(['foo', 'bar'], require_string("OK", name));
796     client.RENAME(["foo", "new foo"], require_string("OK", name));
797     client.exists(["foo"], require_number(0, name));
798     client.exists(["new foo"], last(name, require_number(1, name)));
799 };
800
801 tests.RENAMENX = function () {
802     var name = "RENAMENX";
803     client.set(['foo', 'bar'], require_string("OK", name));
804     client.set(['foo2', 'bar2'], require_string("OK", name));
805     client.RENAMENX(["foo", "foo2"], require_number(0, name));
806     client.exists(["foo"], require_number(1, name));
807     client.exists(["foo2"], require_number(1, name));
808     client.del(["foo2"], require_number(1, name));
809     client.RENAMENX(["foo", "foo2"], require_number(1, name));
810     client.exists(["foo"], require_number(0, name));
811     client.exists(["foo2"], last(name, require_number(1, name)));
812 };
813
814 tests.DBSIZE = function () {
815     var name = "DBSIZE";
816     client.set(['foo', 'bar'], require_string("OK", name));
817     client.DBSIZE([], last(name, require_number_pos("DBSIZE")));
818 };
819
820 tests.GET = function () {
821     var name = "GET";
822     client.set(["get key", "get val"], require_string("OK", name));
823     client.GET(["get key"], last(name, require_string("get val", name)));
824 };
825
826 tests.SET = function () {
827     var name = "SET";
828     client.SET(["set key", "set val"], require_string("OK", name));
829     client.get(["set key"], last(name, require_string("set val", name)));
830 };
831
832 tests.GETSET = function () {
833     var name = "GETSET";
834     client.set(["getset key", "getset val"], require_string("OK", name));
835     client.GETSET(["getset key", "new getset val"], require_string("getset val", name));
836     client.get(["getset key"], last(name, require_string("new getset val", name)));
837 };
838
839 tests.MGET = function () {
840     var name = "MGET";
841     client.mset(["mget keys 1", "mget val 1", "mget keys 2", "mget val 2", "mget keys 3", "mget val 3"], require_string("OK", name));
842     client.MGET("mget keys 1", "mget keys 2", "mget keys 3", function (err, results) {
843         assert.strictEqual(null, err, "result sent back unexpected error: " + err);
844         assert.strictEqual(3, results.length, name);
845         assert.strictEqual("mget val 1", results[0].toString(), name);
846         assert.strictEqual("mget val 2", results[1].toString(), name);
847         assert.strictEqual("mget val 3", results[2].toString(), name);
848     });
849     client.MGET(["mget keys 1", "mget keys 2", "mget keys 3"], function (err, results) {
850         assert.strictEqual(null, err, "result sent back unexpected error: " + err);
851         assert.strictEqual(3, results.length, name);
852         assert.strictEqual("mget val 1", results[0].toString(), name);
853         assert.strictEqual("mget val 2", results[1].toString(), name);
854         assert.strictEqual("mget val 3", results[2].toString(), name);
855     });
856     client.MGET(["mget keys 1", "some random shit", "mget keys 2", "mget keys 3"], function (err, results) {
857         assert.strictEqual(null, err, "result sent back unexpected error: " + err);
858         assert.strictEqual(4, results.length, name);
859         assert.strictEqual("mget val 1", results[0].toString(), name);
860         assert.strictEqual(null, results[1], name);
861         assert.strictEqual("mget val 2", results[2].toString(), name);
862         assert.strictEqual("mget val 3", results[3].toString(), name);
863         next(name);
864     });
865 };
866
867 tests.SETNX = function () {
868     var name = "SETNX";
869     client.set(["setnx key", "setnx value"], require_string("OK", name));
870     client.SETNX(["setnx key", "new setnx value"], require_number(0, name));
871     client.del(["setnx key"], require_number(1, name));
872     client.exists(["setnx key"], require_number(0, name));
873     client.SETNX(["setnx key", "new setnx value"], require_number(1, name));
874     client.exists(["setnx key"], last(name, require_number(1, name)));
875 };
876
877 tests.SETEX = function () {
878     var name = "SETEX";
879     client.SETEX(["setex key", "100", "setex val"], require_string("OK", name));
880     client.exists(["setex key"], require_number(1, name));
881     client.ttl(["setex key"], last(name, require_number_pos(name)));
882 };
883
884 tests.MSETNX = function () {
885     var name = "MSETNX";
886     client.mset(["mset1", "val1", "mset2", "val2", "mset3", "val3"], require_string("OK", name));
887     client.MSETNX(["mset3", "val3", "mset4", "val4"], require_number(0, name));
888     client.del(["mset3"], require_number(1, name));
889     client.MSETNX(["mset3", "val3", "mset4", "val4"], require_number(1, name));
890     client.exists(["mset3"], require_number(1, name));
891     client.exists(["mset4"], last(name, require_number(1, name)));
892 };
893
894 tests.HGETALL = function () {
895     var name = "HGETALL";
896     client.hmset(["hosts", "mjr", "1", "another", "23", "home", "1234"], require_string("OK", name));
897     client.HGETALL(["hosts"], function (err, obj) {
898         assert.strictEqual(null, err, name + " result sent back unexpected error: " + err);
899         assert.strictEqual(3, Object.keys(obj).length, name);
900         assert.strictEqual("1", obj.mjr.toString(), name);
901         assert.strictEqual("23", obj.another.toString(), name);
902         assert.strictEqual("1234", obj.home.toString(), name);
903         next(name);
904     });
905 };
906
907 tests.HGETALL_NULL = function () {
908     var name = "HGETALL_NULL";
909
910     client.hgetall("missing", function (err, obj) {
911         assert.strictEqual(null, err);
912         assert.strictEqual(null, obj);
913         next(name);
914     });
915 };
916
917 tests.UTF8 = function () {
918     var name = "UTF8",
919         utf8_sample = "ಠ_ಠ";
920
921     client.set(["utf8test", utf8_sample], require_string("OK", name));
922     client.get(["utf8test"], function (err, obj) {
923         assert.strictEqual(null, err);
924         assert.strictEqual(utf8_sample, obj);
925         next(name);
926     });
927 };
928
929 // Set tests were adapted from Brian Hammond's redis-node-client.js, which has a comprehensive test suite
930
931 tests.SADD = function () {
932     var name = "SADD";
933
934     client.del('set0');
935     client.SADD('set0', 'member0', require_number(1, name));
936     client.sadd('set0', 'member0', last(name, require_number(0, name)));
937 };
938
939 tests.SADD2 = function () {
940     var name = "SADD2";
941
942     client.del("set0");
943     client.sadd("set0", ["member0", "member1", "member2"], require_number(3, name));
944     client.smembers("set0", function (err, res) {
945         assert.strictEqual(res.length, 3);
946         assert.strictEqual(res[0], "member0");
947         assert.strictEqual(res[1], "member1");
948         assert.strictEqual(res[2], "member2");
949     });
950     client.SADD("set1", ["member0", "member1", "member2"], require_number(3, name));
951     client.smembers("set1", function (err, res) {
952         assert.strictEqual(res.length, 3);
953         assert.strictEqual(res[0], "member0");
954         assert.strictEqual(res[1], "member1");
955         assert.strictEqual(res[2], "member2");
956         next(name);
957     });
958 };
959
960 tests.SISMEMBER = function () {
961     var name = "SISMEMBER";
962
963     client.del('set0');
964     client.sadd('set0', 'member0', require_number(1, name));
965     client.sismember('set0', 'member0', require_number(1, name));
966     client.sismember('set0', 'member1', last(name, require_number(0, name)));
967 };
968
969 tests.SCARD = function () {
970     var name = "SCARD";
971
972     client.del('set0');
973     client.sadd('set0', 'member0', require_number(1, name));
974     client.scard('set0', require_number(1, name));
975     client.sadd('set0', 'member1', require_number(1, name));
976     client.scard('set0', last(name, require_number(2, name)));
977 };
978
979 tests.SREM = function () {
980     var name = "SREM";
981
982     client.del('set0');
983     client.sadd('set0', 'member0', require_number(1, name));
984     client.srem('set0', 'foobar', require_number(0, name));
985     client.srem('set0', 'member0', require_number(1, name));
986     client.scard('set0', last(name, require_number(0, name)));
987 };
988
989 tests.SPOP = function () {
990     var name = "SPOP";
991
992     client.del('zzz');
993     client.sadd('zzz', 'member0', require_number(1, name));
994     client.scard('zzz', require_number(1, name));
995
996     client.spop('zzz', function (err, value) {
997         if (err) {
998             assert.fail(err);
999         }
1000         assert.equal(value, 'member0', name);
1001     });
1002
1003     client.scard('zzz', last(name, require_number(0, name)));
1004 };
1005
1006 tests.SDIFF = function () {
1007     var name = "SDIFF";
1008
1009     client.del('foo');
1010     client.sadd('foo', 'x', require_number(1, name));
1011     client.sadd('foo', 'a', require_number(1, name));
1012     client.sadd('foo', 'b', require_number(1, name));
1013     client.sadd('foo', 'c', require_number(1, name));
1014
1015     client.sadd('bar', 'c', require_number(1, name));
1016
1017     client.sadd('baz', 'a', require_number(1, name));
1018     client.sadd('baz', 'd', require_number(1, name));
1019
1020     client.sdiff('foo', 'bar', 'baz', function (err, values) {
1021         if (err) {
1022             assert.fail(err, name);
1023         }
1024         values.sort();
1025         assert.equal(values.length, 2, name);
1026         assert.equal(values[0], 'b', name);
1027         assert.equal(values[1], 'x', name);
1028         next(name);
1029     });
1030 };
1031
1032 tests.SDIFFSTORE = function () {
1033     var name = "SDIFFSTORE";
1034
1035     client.del('foo');
1036     client.del('bar');
1037     client.del('baz');
1038     client.del('quux');
1039
1040     client.sadd('foo', 'x', require_number(1, name));
1041     client.sadd('foo', 'a', require_number(1, name));
1042     client.sadd('foo', 'b', require_number(1, name));
1043     client.sadd('foo', 'c', require_number(1, name));
1044
1045     client.sadd('bar', 'c', require_number(1, name));
1046
1047     client.sadd('baz', 'a', require_number(1, name));
1048     client.sadd('baz', 'd', require_number(1, name));
1049
1050     // NB: SDIFFSTORE returns the number of elements in the dstkey
1051
1052     client.sdiffstore('quux', 'foo', 'bar', 'baz', require_number(2, name));
1053
1054     client.smembers('quux', function (err, values) {
1055         if (err) {
1056             assert.fail(err, name);
1057         }
1058         var members = buffers_to_strings(values).sort();
1059
1060         assert.deepEqual(members, [ 'b', 'x' ], name);
1061         next(name);
1062     });
1063 };
1064
1065 tests.SMEMBERS = function () {
1066     var name = "SMEMBERS";
1067
1068     client.del('foo');
1069     client.sadd('foo', 'x', require_number(1, name));
1070
1071     client.smembers('foo', function (err, members) {
1072         if (err) {
1073             assert.fail(err, name);
1074         }
1075         assert.deepEqual(buffers_to_strings(members), [ 'x' ], name);
1076     });
1077
1078     client.sadd('foo', 'y', require_number(1, name));
1079
1080     client.smembers('foo', function (err, values) {
1081         if (err) {
1082             assert.fail(err, name);
1083         }
1084         assert.equal(values.length, 2, name);
1085         var members = buffers_to_strings(values).sort();
1086
1087         assert.deepEqual(members, [ 'x', 'y' ], name);
1088         next(name);
1089     });
1090 };
1091
1092 tests.SMOVE = function () {
1093     var name = "SMOVE";
1094
1095     client.del('foo');
1096     client.del('bar');
1097
1098     client.sadd('foo', 'x', require_number(1, name));
1099     client.smove('foo', 'bar', 'x', require_number(1, name));
1100     client.sismember('foo', 'x', require_number(0, name));
1101     client.sismember('bar', 'x', require_number(1, name));
1102     client.smove('foo', 'bar', 'x', last(name, require_number(0, name)));
1103 };
1104
1105 tests.SINTER = function () {
1106     var name = "SINTER";
1107
1108     client.del('sa');
1109     client.del('sb');
1110     client.del('sc');
1111
1112     client.sadd('sa', 'a', require_number(1, name));
1113     client.sadd('sa', 'b', require_number(1, name));
1114     client.sadd('sa', 'c', require_number(1, name));
1115
1116     client.sadd('sb', 'b', require_number(1, name));
1117     client.sadd('sb', 'c', require_number(1, name));
1118     client.sadd('sb', 'd', require_number(1, name));
1119
1120     client.sadd('sc', 'c', require_number(1, name));
1121     client.sadd('sc', 'd', require_number(1, name));
1122     client.sadd('sc', 'e', require_number(1, name));
1123
1124     client.sinter('sa', 'sb', function (err, intersection) {
1125         if (err) {
1126             assert.fail(err, name);
1127         }
1128         assert.equal(intersection.length, 2, name);
1129         assert.deepEqual(buffers_to_strings(intersection).sort(), [ 'b', 'c' ], name);
1130     });
1131
1132     client.sinter('sb', 'sc', function (err, intersection) {
1133         if (err) {
1134             assert.fail(err, name);
1135         }
1136         assert.equal(intersection.length, 2, name);
1137         assert.deepEqual(buffers_to_strings(intersection).sort(), [ 'c', 'd' ], name);
1138     });
1139
1140     client.sinter('sa', 'sc', function (err, intersection) {
1141         if (err) {
1142             assert.fail(err, name);
1143         }
1144         assert.equal(intersection.length, 1, name);
1145         assert.equal(intersection[0], 'c', name);
1146     });
1147
1148     // 3-way
1149
1150     client.sinter('sa', 'sb', 'sc', function (err, intersection) {
1151         if (err) {
1152             assert.fail(err, name);
1153         }
1154         assert.equal(intersection.length, 1, name);
1155         assert.equal(intersection[0], 'c', name);
1156         next(name);
1157     });
1158 };
1159
1160 tests.SINTERSTORE = function () {
1161     var name = "SINTERSTORE";
1162
1163     client.del('sa');
1164     client.del('sb');
1165     client.del('sc');
1166     client.del('foo');
1167
1168     client.sadd('sa', 'a', require_number(1, name));
1169     client.sadd('sa', 'b', require_number(1, name));
1170     client.sadd('sa', 'c', require_number(1, name));
1171
1172     client.sadd('sb', 'b', require_number(1, name));
1173     client.sadd('sb', 'c', require_number(1, name));
1174     client.sadd('sb', 'd', require_number(1, name));
1175
1176     client.sadd('sc', 'c', require_number(1, name));
1177     client.sadd('sc', 'd', require_number(1, name));
1178     client.sadd('sc', 'e', require_number(1, name));
1179
1180     client.sinterstore('foo', 'sa', 'sb', 'sc', require_number(1, name));
1181
1182     client.smembers('foo', function (err, members) {
1183         if (err) {
1184             assert.fail(err, name);
1185         }
1186         assert.deepEqual(buffers_to_strings(members), [ 'c' ], name);
1187         next(name);
1188     });
1189 };
1190
1191 tests.SUNION = function () {
1192     var name = "SUNION";
1193
1194     client.del('sa');
1195     client.del('sb');
1196     client.del('sc');
1197
1198     client.sadd('sa', 'a', require_number(1, name));
1199     client.sadd('sa', 'b', require_number(1, name));
1200     client.sadd('sa', 'c', require_number(1, name));
1201
1202     client.sadd('sb', 'b', require_number(1, name));
1203     client.sadd('sb', 'c', require_number(1, name));
1204     client.sadd('sb', 'd', require_number(1, name));
1205
1206     client.sadd('sc', 'c', require_number(1, name));
1207     client.sadd('sc', 'd', require_number(1, name));
1208     client.sadd('sc', 'e', require_number(1, name));
1209
1210     client.sunion('sa', 'sb', 'sc', function (err, union) {
1211         if (err) {
1212             assert.fail(err, name);
1213         }
1214         assert.deepEqual(buffers_to_strings(union).sort(), ['a', 'b', 'c', 'd', 'e'], name);
1215         next(name);
1216     });
1217 };
1218
1219 tests.SUNIONSTORE = function () {
1220     var name = "SUNIONSTORE";
1221
1222     client.del('sa');
1223     client.del('sb');
1224     client.del('sc');
1225     client.del('foo');
1226
1227     client.sadd('sa', 'a', require_number(1, name));
1228     client.sadd('sa', 'b', require_number(1, name));
1229     client.sadd('sa', 'c', require_number(1, name));
1230
1231     client.sadd('sb', 'b', require_number(1, name));
1232     client.sadd('sb', 'c', require_number(1, name));
1233     client.sadd('sb', 'd', require_number(1, name));
1234
1235     client.sadd('sc', 'c', require_number(1, name));
1236     client.sadd('sc', 'd', require_number(1, name));
1237     client.sadd('sc', 'e', require_number(1, name));
1238
1239     client.sunionstore('foo', 'sa', 'sb', 'sc', function (err, cardinality) {
1240         if (err) {
1241             assert.fail(err, name);
1242         }
1243         assert.equal(cardinality, 5, name);
1244     });
1245
1246     client.smembers('foo', function (err, members) {
1247         if (err) {
1248             assert.fail(err, name);
1249         }
1250         assert.equal(members.length, 5, name);
1251         assert.deepEqual(buffers_to_strings(members).sort(), ['a', 'b', 'c', 'd', 'e'], name);
1252         next(name);
1253     });
1254 };
1255
1256 // SORT test adapted from Brian Hammond's redis-node-client.js, which has a comprehensive test suite
1257
1258 tests.SORT = function () {
1259     var name = "SORT";
1260
1261     client.del('y');
1262     client.del('x');
1263
1264     client.rpush('y', 'd', require_number(1, name));
1265     client.rpush('y', 'b', require_number(2, name));
1266     client.rpush('y', 'a', require_number(3, name));
1267     client.rpush('y', 'c', require_number(4, name));
1268
1269     client.rpush('x', '3', require_number(1, name));
1270     client.rpush('x', '9', require_number(2, name));
1271     client.rpush('x', '2', require_number(3, name));
1272     client.rpush('x', '4', require_number(4, name));
1273
1274     client.set('w3', '4', require_string("OK", name));
1275     client.set('w9', '5', require_string("OK", name));
1276     client.set('w2', '12', require_string("OK", name));
1277     client.set('w4', '6', require_string("OK", name));
1278
1279     client.set('o2', 'buz', require_string("OK", name));
1280     client.set('o3', 'foo', require_string("OK", name));
1281     client.set('o4', 'baz', require_string("OK", name));
1282     client.set('o9', 'bar', require_string("OK", name));
1283
1284     client.set('p2', 'qux', require_string("OK", name));
1285     client.set('p3', 'bux', require_string("OK", name));
1286     client.set('p4', 'lux', require_string("OK", name));
1287     client.set('p9', 'tux', require_string("OK", name));
1288
1289     // Now the data has been setup, we can test.
1290
1291     // But first, test basic sorting.
1292
1293     // y = [ d b a c ]
1294     // sort y ascending = [ a b c d ]
1295     // sort y descending = [ d c b a ]
1296
1297     client.sort('y', 'asc', 'alpha', function (err, sorted) {
1298         if (err) {
1299             assert.fail(err, name);
1300         }
1301         assert.deepEqual(buffers_to_strings(sorted), ['a', 'b', 'c', 'd'], name);
1302     });
1303
1304     client.sort('y', 'desc', 'alpha', function (err, sorted) {
1305         if (err) {
1306             assert.fail(err, name);
1307         }
1308         assert.deepEqual(buffers_to_strings(sorted), ['d', 'c', 'b', 'a'], name);
1309     });
1310
1311     // Now try sorting numbers in a list.
1312     // x = [ 3, 9, 2, 4 ]
1313
1314     client.sort('x', 'asc', function (err, sorted) {
1315         if (err) {
1316             assert.fail(err, name);
1317         }
1318         assert.deepEqual(buffers_to_strings(sorted), [2, 3, 4, 9], name);
1319     });
1320
1321     client.sort('x', 'desc', function (err, sorted) {
1322         if (err) {
1323             assert.fail(err, name);
1324         }
1325         assert.deepEqual(buffers_to_strings(sorted), [9, 4, 3, 2], name);
1326     });
1327
1328     // Try sorting with a 'by' pattern.
1329
1330     client.sort('x', 'by', 'w*', 'asc', function (err, sorted) {
1331         if (err) {
1332             assert.fail(err, name);
1333         }
1334         assert.deepEqual(buffers_to_strings(sorted), [3, 9, 4, 2], name);
1335     });
1336
1337     // Try sorting with a 'by' pattern and 1 'get' pattern.
1338
1339     client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', function (err, sorted) {
1340         if (err) {
1341             assert.fail(err, name);
1342         }
1343         assert.deepEqual(buffers_to_strings(sorted), ['foo', 'bar', 'baz', 'buz'], name);
1344     });
1345
1346     // Try sorting with a 'by' pattern and 2 'get' patterns.
1347
1348     client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', 'get', 'p*', function (err, sorted) {
1349         if (err) {
1350             assert.fail(err, name);
1351         }
1352         assert.deepEqual(buffers_to_strings(sorted), ['foo', 'bux', 'bar', 'tux', 'baz', 'lux', 'buz', 'qux'], name);
1353     });
1354
1355     // Try sorting with a 'by' pattern and 2 'get' patterns.
1356     // Instead of getting back the sorted set/list, store the values to a list.
1357     // Then check that the values are there in the expected order.
1358
1359     client.sort('x', 'by', 'w*', 'asc', 'get', 'o*', 'get', 'p*', 'store', 'bacon', function (err) {
1360         if (err) {
1361             assert.fail(err, name);
1362         }
1363     });
1364
1365     client.lrange('bacon', 0, -1, function (err, values) {
1366         if (err) {
1367             assert.fail(err, name);
1368         }
1369         assert.deepEqual(buffers_to_strings(values), ['foo', 'bux', 'bar', 'tux', 'baz', 'lux', 'buz', 'qux'], name);
1370         next(name);
1371     });
1372
1373     // TODO - sort by hash value
1374 };
1375
1376 tests.MONITOR = function () {
1377     var name = "MONITOR", responses = [], monitor_client;
1378
1379     monitor_client = redis.createClient();
1380     monitor_client.monitor(function (err, res) {
1381         client.mget("some", "keys", "foo", "bar");
1382         client.set("json", JSON.stringify({
1383             foo: "123",
1384             bar: "sdflkdfsjk",
1385             another: false
1386         }));
1387     });
1388     monitor_client.on("monitor", function (time, args) {
1389         // skip monitor command for Redis <= 2.4.16
1390         if (args[0] === "monitor") return;
1391
1392         responses.push(args);
1393         if (responses.length === 2) {
1394             assert.strictEqual(5, responses[0].length);
1395             assert.strictEqual("mget", responses[0][0]);
1396             assert.strictEqual("some", responses[0][1]);
1397             assert.strictEqual("keys", responses[0][2]);
1398             assert.strictEqual("foo", responses[0][3]);
1399             assert.strictEqual("bar", responses[0][4]);
1400             assert.strictEqual(3, responses[1].length);
1401             assert.strictEqual("set", responses[1][0]);
1402             assert.strictEqual("json", responses[1][1]);
1403             assert.strictEqual('{"foo":"123","bar":"sdflkdfsjk","another":false}', responses[1][2]);
1404             monitor_client.quit(function (err, res) {
1405                 next(name);
1406             });
1407         }
1408     });
1409 };
1410
1411 tests.BLPOP = function () {
1412     var name = "BLPOP";
1413
1414     client.rpush("blocking list", "initial value", function (err, res) {
1415         client2.BLPOP("blocking list", 0, function (err, res) {
1416             assert.strictEqual("blocking list", res[0].toString());
1417             assert.strictEqual("initial value", res[1].toString());
1418
1419             client.rpush("blocking list", "wait for this value");
1420         });
1421         client2.BLPOP("blocking list", 0, function (err, res) {
1422             assert.strictEqual("blocking list", res[0].toString());
1423             assert.strictEqual("wait for this value", res[1].toString());
1424             next(name);
1425         });
1426     });
1427 };
1428
1429 tests.BLPOP_TIMEOUT = function () {
1430     var name = "BLPOP_TIMEOUT";
1431
1432     // try to BLPOP the list again, which should be empty.  This should timeout and return null.
1433     client2.BLPOP("blocking list", 1, function (err, res) {
1434         if (err) {
1435             throw err;
1436         }
1437
1438         assert.strictEqual(res, null);
1439         next(name);
1440     });
1441 };
1442
1443 tests.EXPIRE = function () {
1444     var name = "EXPIRE";
1445     client.set(['expiry key', 'bar'], require_string("OK", name));
1446     client.EXPIRE(["expiry key", "1"], require_number_pos(name));
1447     setTimeout(function () {
1448         client.exists(["expiry key"], last(name, require_number(0, name)));
1449     }, 2000);
1450 };
1451
1452 tests.TTL = function () {
1453     var name = "TTL";
1454     client.set(["ttl key", "ttl val"], require_string("OK", name));
1455     client.expire(["ttl key", "100"], require_number_pos(name));
1456     setTimeout(function () {
1457         client.TTL(["ttl key"], last(name, require_number_pos(0, name)));
1458     }, 500);
1459 };
1460
1461 tests.OPTIONAL_CALLBACK = function () {
1462     var name = "OPTIONAL_CALLBACK";
1463     client.del("op_cb1");
1464     client.set("op_cb1", "x");
1465     client.get("op_cb1", last(name, require_string("x", name)));
1466 };
1467
1468 tests.OPTIONAL_CALLBACK_UNDEFINED = function () {
1469     var name = "OPTIONAL_CALLBACK_UNDEFINED";
1470     client.del("op_cb2");
1471     client.set("op_cb2", "y", undefined);
1472     client.get("op_cb2", last(name, require_string("y", name)));
1473 };
1474
1475 tests.HMSET_THROWS_ON_NON_STRINGS = function () {
1476     var name = "HMSET_THROWS_ON_NON_STRINGS";
1477     var hash = name;
1478     var data = { "a": [ "this is not a string" ] };
1479
1480     client.hmset(hash, data, cb);
1481     function cb(e, r) {
1482         assert(e); // should be an error!
1483     }
1484
1485     // alternative way it throws
1486     function thrower() {
1487         client.hmset(hash, data);
1488     }
1489     assert.throws(thrower);
1490     next(name);
1491 };
1492
1493 tests.ENABLE_OFFLINE_QUEUE_TRUE = function () {
1494     var name = "ENABLE_OFFLINE_QUEUE_TRUE";
1495     var cli = redis.createClient(9999, null, {
1496         max_attempts: 1
1497         // default :)
1498         // enable_offline_queue: true
1499     });
1500     cli.on('error', function(e) {
1501         // ignore, b/c expecting a "can't connect" error
1502     });
1503     return setTimeout(function() {
1504         cli.set(name, name, function(err, result) {
1505             assert.ifError(err);
1506         });
1507
1508         return setTimeout(function(){
1509             assert.strictEqual(cli.offline_queue.length, 1);
1510             return next(name);
1511         }, 25);
1512     }, 50);
1513 };
1514
1515 tests.ENABLE_OFFLINE_QUEUE_FALSE = function () {
1516     var name = "ENABLE_OFFLINE_QUEUE_FALSE";
1517     var cli = redis.createClient(9999, null, {
1518         max_attempts: 1,
1519         enable_offline_queue: false
1520     });
1521     cli.on('error', function() {
1522         // ignore, see above
1523     });
1524     assert.throws(function () {
1525         cli.set(name, name)
1526     })
1527     assert.doesNotThrow(function () {
1528         cli.set(name, name, function (err) {
1529             // should callback with an error
1530             assert.ok(err);
1531             setTimeout(function () {
1532                 next(name);
1533             }, 50);
1534         });
1535     });
1536 };
1537
1538 // TODO - need a better way to test auth, maybe auto-config a local Redis server or something.
1539 // Yes, this is the real password.  Please be nice, thanks.
1540 tests.auth = function () {
1541     var name = "AUTH", client4, ready_count = 0;
1542
1543     client4 = redis.createClient(9006, "filefish.redistogo.com");
1544     client4.auth("664b1b6aaf134e1ec281945a8de702a9", function (err, res) {
1545         assert.strictEqual(null, err, name);
1546         assert.strictEqual("OK", res.toString(), name);
1547     });
1548
1549     // test auth, then kill the connection so it'll auto-reconnect and auto-re-auth
1550     client4.on("ready", function () {
1551         ready_count++;
1552         if (ready_count === 1) {
1553             client4.stream.destroy();
1554         } else {
1555             client4.quit(function (err, res) {
1556                 next(name);
1557             });
1558         }
1559     });
1560 };
1561
1562 all_tests = Object.keys(tests);
1563 all_start = new Date();
1564 test_count = 0;
1565
1566 run_next_test = function run_next_test() {
1567     var test_name = all_tests.shift();
1568     if (typeof tests[test_name] === "function") {
1569         util.print('- \x1b[1m' + test_name.toLowerCase() + '\x1b[0m:');
1570         cur_start = new Date();
1571         test_count += 1;
1572         tests[test_name]();
1573     } else {
1574         console.log('\n  completed \x1b[32m%d\x1b[0m tests in \x1b[33m%d\x1b[0m ms\n', test_count, new Date() - all_start);
1575         client.quit();
1576         client2.quit();
1577     }
1578 };
1579
1580 client.once("ready", function start_tests() {
1581     console.log("Connected to " + client.host + ":" + client.port + ", Redis server version " + client.server_info.redis_version + "\n");
1582     console.log("Using reply parser " + client.reply_parser.name);
1583
1584     run_next_test();
1585
1586     connected = true;
1587 });
1588
1589 client.on('end', function () {
1590     ended = true;
1591 });
1592
1593 // Exit immediately on connection failure, which triggers "exit", below, which fails the test
1594 client.on("error", function (err) {
1595     console.error("client: " + err.stack);
1596     process.exit();
1597 });
1598 client2.on("error", function (err) {
1599     console.error("client2: " + err.stack);
1600     process.exit();
1601 });
1602 client3.on("error", function (err) {
1603     console.error("client3: " + err.stack);
1604     process.exit();
1605 });
1606 client.on("reconnecting", function (params) {
1607     console.log("reconnecting: " + util.inspect(params));
1608 });
1609
1610 process.on('uncaughtException', function (err) {
1611     console.error("Uncaught exception: " + err.stack);
1612     process.exit(1);
1613 });
1614
1615 process.on('exit', function (code) {
1616     assert.equal(true, connected);
1617     assert.equal(true, ended);
1618 });