Skip to content

Commit 4f3c4a2

Browse files
author
Ruben Bridgewater
committed
Add more tests
Add execution order tests Fix flaky test Add utils tests Improve other tests
1 parent 614e35a commit 4f3c4a2

File tree

7 files changed

+210
-12
lines changed

7 files changed

+210
-12
lines changed

test/batch.spec.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,16 @@ describe("The 'batch' method", function () {
6363
client.end(true);
6464
});
6565

66-
it("returns an empty array", function (done) {
66+
it("returns an empty array and keep the execution order in takt", function (done) {
67+
var called = false;
68+
client.set('foo', 'bar', function (err, res) {
69+
called = true;
70+
});
6771
var batch = client.batch();
6872
batch.exec(function (err, res) {
6973
assert.strictEqual(err, null);
7074
assert.strictEqual(res.length, 0);
75+
assert(called);
7176
done();
7277
});
7378
});
@@ -328,10 +333,11 @@ describe("The 'batch' method", function () {
328333
.exec(done);
329334
});
330335

331-
it("should work without any callback", function (done) {
336+
it("should work without any callback or arguments", function (done) {
332337
var batch = client.batch();
333338
batch.set("baz", "binary");
334339
batch.set("foo", "bar");
340+
batch.ping();
335341
batch.exec();
336342

337343
client.get('foo', helper.isString('bar', done));

test/commands/set.spec.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,21 @@ describe("The 'set' method", function () {
6666
});
6767
});
6868

69-
describe("with undefined 'key' and missing 'value' parameter", function () {
70-
it("reports an error", function (done) {
69+
describe("reports an error with invalid parameters", function () {
70+
it("undefined 'key' and missing 'value' parameter", function (done) {
7171
client.set(undefined, function (err, res) {
7272
helper.isError()(err, null);
7373
assert.equal(err.command, 'SET');
7474
done();
7575
});
7676
});
77+
78+
it("empty array as second parameter", function (done) {
79+
client.set('foo', [], function (err, res) {
80+
assert.strictEqual(err.message, "ERR wrong number of arguments for 'set' command");
81+
done();
82+
});
83+
});
7784
});
7885
});
7986

test/connection.spec.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,14 @@ describe("connection tests", function () {
136136
var time = Date.now();
137137
client = redis.createClient({
138138
parser: parser,
139-
host: '192.168.74.167', // Should be auto detected as ipv4
139+
// Auto detect ipv4 and use non routable ip to trigger the timeout
140+
host: '10.255.255.1',
140141
connect_timeout: connect_timeout
141142
});
142143
process.nextTick(function() {
143-
assert(client.stream._events.timeout);
144+
assert.strictEqual(client.stream.listeners('timeout').length, 1);
144145
});
145-
assert.strictEqual(client.address, '192.168.74.167:6379');
146+
assert.strictEqual(client.address, '10.255.255.1:6379');
146147
assert.strictEqual(client.connection_options.family, 4);
147148

148149
client.on("reconnecting", function (params) {
@@ -151,8 +152,8 @@ describe("connection tests", function () {
151152

152153
client.on('error', function(err) {
153154
assert(/Redis connection in broken state: connection timeout.*?exceeded./.test(err.message));
154-
assert(Date.now() - time < connect_timeout + 50);
155-
assert(Date.now() - time >= connect_timeout - 50); // Somehow this is triggered to early at times
155+
assert(Date.now() - time < connect_timeout + 25);
156+
assert(Date.now() - time >= connect_timeout - 3); // Timers sometimes trigger early (e.g. 1ms to early)
156157
done();
157158
});
158159
});
@@ -165,7 +166,7 @@ describe("connection tests", function () {
165166
assert.strictEqual(client.address, '2001:db8::ff00:42:8329:6379');
166167
assert.strictEqual(client.connection_options.family, 6);
167168
process.nextTick(function() {
168-
assert.strictEqual(client.stream._events.timeout, undefined);
169+
assert.strictEqual(client.stream.listeners('timeout').length, 0);
169170
});
170171
});
171172

@@ -179,7 +180,7 @@ describe("connection tests", function () {
179180
});
180181
client.on('connect', function () {
181182
assert.strictEqual(client.stream._idleTimeout, -1);
182-
assert.strictEqual(client.stream._events.timeout, undefined);
183+
assert.strictEqual(client.stream.listeners('timeout').length, 0);
183184
client.on('ready', done);
184185
});
185186
});

test/multi.spec.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ describe("The 'multi' method", function () {
241241
multi1.set("m1", "123");
242242
multi1.get('m1');
243243
multi2.get('m2');
244+
multi2.ping();
244245

245246
multi1.exec(end);
246247
multi2.exec(function(err, res) {
@@ -538,7 +539,7 @@ describe("The 'multi' method", function () {
538539
client.get('foo', helper.isString('bar', done));
539540
});
540541

541-
it("should not use a transaction with exec_atomic if only no command is used", function () {
542+
it("should not use a transaction with exec_atomic if no command is used", function () {
542543
var multi = client.multi();
543544
var test = false;
544545
multi.exec_batch = function () {

test/node_redis.spec.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,41 @@ describe("The node_redis client", function () {
423423
});
424424
});
425425

426+
describe('execution order / fire query while loading', function () {
427+
it('keep execution order for commands that may fire while redis is still loading', function (done) {
428+
client = redis.createClient.apply(null, args);
429+
var fired = false;
430+
client.set('foo', 'bar', function (err, res) {
431+
assert(fired === false);
432+
done();
433+
});
434+
client.info(function (err, res) {
435+
fired = true;
436+
});
437+
});
438+
439+
it('should fire early', function (done) {
440+
client = redis.createClient.apply(null, args);
441+
var fired = false;
442+
client.info(function (err, res) {
443+
fired = true;
444+
});
445+
client.set('foo', 'bar', function (err, res) {
446+
assert(fired);
447+
done();
448+
});
449+
assert.strictEqual(client.offline_queue.length, 1);
450+
assert.strictEqual(client.command_queue.length, 1);
451+
client.on('connect', function () {
452+
assert.strictEqual(client.offline_queue.length, 1);
453+
assert.strictEqual(client.command_queue.length, 1);
454+
});
455+
client.on('ready', function () {
456+
assert.strictEqual(client.offline_queue.length, 0);
457+
});
458+
});
459+
});
460+
426461
describe('socket_nodelay', function () {
427462
describe('true', function () {
428463
var args = config.configureClient(parser, ip, {

test/rename.spec.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,25 @@ describe("rename commands", function () {
109109
});
110110
});
111111

112+
it("should also work prefixed commands", function (done) {
113+
if (helper.redisProcess().spawnFailed()) this.skip();
114+
115+
client.end(true);
116+
client = redis.createClient({
117+
rename_commands: {
118+
set: '807081f5afa96845a02816a28b7258c3'
119+
},
120+
parser: parser,
121+
prefix: 'baz'
122+
});
123+
client.set('foo', 'bar');
124+
client.keys('*', function(err, reply) {
125+
assert.strictEqual(reply[0], 'bazfoo');
126+
assert.strictEqual(err, null);
127+
done();
128+
});
129+
});
130+
112131
});
113132
});
114133

test/utils.spec.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
'use strict';
2+
3+
var assert = require('assert');
4+
var Queue = require('double-ended-queue');
5+
var utils = require('../lib/utils');
6+
7+
describe('utils.js', function () {
8+
9+
describe('clone', function () {
10+
it('ignore the object prototype and clone a nested array / object', function () {
11+
var obj = {
12+
a: [null, 'foo', ['bar'], {
13+
"I'm special": true
14+
}],
15+
number: 5,
16+
fn: function noop () {}
17+
};
18+
var clone = utils.clone(obj);
19+
assert.deepEqual(clone, obj);
20+
assert.strictEqual(obj.fn, clone.fn);
21+
assert(typeof clone.fn === 'function');
22+
});
23+
24+
it('replace faulty values with an empty object as return value', function () {
25+
var a = utils.clone();
26+
var b = utils.clone(null);
27+
assert.strictEqual(Object.keys(a).length, 0);
28+
assert.strictEqual(Object.keys(b).length, 0);
29+
});
30+
31+
it('throws on circular data', function () {
32+
try {
33+
var a = {};
34+
a.b = a;
35+
utils.clone(a);
36+
throw new Error('failed');
37+
} catch (e) {
38+
assert(e.message !== 'failed');
39+
}
40+
});
41+
});
42+
43+
describe('reply_in_order', function () {
44+
45+
var err_count = 0;
46+
var res_count = 0;
47+
var emitted = false;
48+
var clientMock = {
49+
emit: function () { emitted = true; },
50+
offline_queue: new Queue(),
51+
command_queue: new Queue()
52+
};
53+
var create_command_obj = function () {
54+
return {
55+
callback: function (err, res) {
56+
if (err) err_count++;
57+
else res_count++;
58+
}
59+
};
60+
};
61+
62+
beforeEach(function () {
63+
clientMock.offline_queue.clear();
64+
clientMock.command_queue.clear();
65+
err_count = 0;
66+
res_count = 0;
67+
emitted = false;
68+
});
69+
70+
it('no elements in either queue. Reply in the next tick', function (done) {
71+
var called = false;
72+
utils.reply_in_order(clientMock, function () {
73+
called = true;
74+
done();
75+
}, null, null);
76+
assert(!called);
77+
});
78+
79+
it('no elements in either queue. Reply in the next tick', function (done) {
80+
assert(!emitted);
81+
utils.reply_in_order(clientMock, null, new Error('tada'));
82+
assert(!emitted);
83+
setTimeout(function () {
84+
assert(emitted);
85+
done();
86+
}, 1);
87+
});
88+
89+
it('elements in the offline queue. Reply after the offline queue is empty and respect the command_obj callback', function (done) {
90+
clientMock.offline_queue.push(create_command_obj(), create_command_obj());
91+
utils.reply_in_order(clientMock, function () {
92+
assert.strictEqual(clientMock.offline_queue.length, 0);
93+
assert.strictEqual(res_count, 2);
94+
done();
95+
}, null, null);
96+
while (clientMock.offline_queue.length) clientMock.offline_queue.shift().callback(null, 'foo');
97+
});
98+
99+
it('elements in the offline queue. Reply after the offline queue is empty and respect the command_obj error emit', function (done) {
100+
clientMock.command_queue.push({}, create_command_obj(), {});
101+
utils.reply_in_order(clientMock, function () {
102+
assert.strictEqual(clientMock.command_queue.length, 0);
103+
assert(emitted);
104+
assert.strictEqual(err_count, 1);
105+
assert.strictEqual(res_count, 0);
106+
done();
107+
}, null, null);
108+
while (clientMock.command_queue.length) {
109+
var command_obj = clientMock.command_queue.shift();
110+
if (command_obj.callback) {
111+
command_obj.callback(new Error('tada'));
112+
}
113+
}
114+
});
115+
116+
it('elements in the offline queue. Reply after the offline queue is empty and respect the command_obj', function (done) {
117+
clientMock.command_queue.push(create_command_obj(), {});
118+
utils.reply_in_order(clientMock, function () {
119+
assert.strictEqual(clientMock.command_queue.length, 0);
120+
assert(!emitted);
121+
assert.strictEqual(res_count, 1);
122+
done();
123+
}, null, null);
124+
while (clientMock.command_queue.length) {
125+
clientMock.command_queue.shift().callback(null, 'bar');
126+
}
127+
});
128+
});
129+
});

0 commit comments

Comments
 (0)