You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-07 13:22:56 +03:00
Fix some minor issues and add more tests
Do not mutate the options object and add some more tests
This commit is contained in:
@@ -31,7 +31,7 @@ describe("The 'expire' method", function () {
|
||||
client.EXPIRE(["expiry key", "1"], helper.isNumber(1));
|
||||
setTimeout(function () {
|
||||
client.exists(["expiry key"], helper.isNumber(0, done));
|
||||
}, 3000);
|
||||
}, 1100);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
@@ -37,6 +37,12 @@ describe("The 'get' method", function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("reports an error promisified", function () {
|
||||
return client.getAsync(key).then(assert, function (err) {
|
||||
assert(err.message.match(/The connection has already been closed/));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when connected", function () {
|
||||
@@ -76,7 +82,7 @@ describe("The 'get' method", function () {
|
||||
}]);
|
||||
});
|
||||
|
||||
it("should not throw on a get without callback (even if it's not useful", function (done) {
|
||||
it("should not throw on a get without callback (even if it's not useful)", function (done) {
|
||||
client.GET(key);
|
||||
client.on('error', function(err) {
|
||||
throw err;
|
||||
|
@@ -67,6 +67,50 @@ describe("The 'multi' method", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("when connection is broken", function () {
|
||||
var client;
|
||||
|
||||
afterEach(function () {
|
||||
client.end();
|
||||
});
|
||||
|
||||
it("return an error even if connection is in broken mode if callback is present", function (done) {
|
||||
client = redis.createClient({
|
||||
host: 'somewhere',
|
||||
port: 6379,
|
||||
max_attempts: 1
|
||||
});
|
||||
|
||||
client.on('error', function(err) {
|
||||
if (/Redis connection in broken state/.test(err.message)) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
client.multi([['set', 'foo', 'bar'], ['get', 'foo']]).exec(function (err, res) {
|
||||
assert(/Redis connection in broken state/.test(err.message));
|
||||
assert.strictEqual(err.errors.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
it("does not emit an error twice if connection is in broken mode with no callback", function (done) {
|
||||
client = redis.createClient({
|
||||
host: 'somewhere',
|
||||
port: 6379,
|
||||
max_attempts: 1
|
||||
});
|
||||
|
||||
client.on('error', function(err) {
|
||||
// Results in multiple done calls if test fails
|
||||
if (/Redis connection in broken state/.test(err.message)) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
client.multi([['set', 'foo', 'bar'], ['get', 'foo']]).exec();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when ready", function () {
|
||||
var client;
|
||||
|
||||
@@ -481,6 +525,18 @@ describe("The 'multi' method", function () {
|
||||
assert(!test);
|
||||
});
|
||||
|
||||
it("do not mutate arguments in the multi constructor", function (done) {
|
||||
helper.serverVersionAtLeast.call(this, client, [2, 6, 5]);
|
||||
|
||||
var input = [['set', 'foo', 'bar'], ['get', 'foo']];
|
||||
client.multi(input).exec(function (err, res) {
|
||||
assert.strictEqual(input.length, 2);
|
||||
assert.strictEqual(input[0].length, 3);
|
||||
assert.strictEqual(input[1].length, 2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -5,106 +5,247 @@ var config = require("./lib/config");
|
||||
var helper = require('./helper');
|
||||
var redis = config.redis;
|
||||
|
||||
describe("on lost connection", function () {
|
||||
describe("connection tests", function () {
|
||||
helper.allTests(function(parser, ip, args) {
|
||||
|
||||
describe("using " + parser + " and " + ip, function () {
|
||||
|
||||
it("emit an error after max retry attempts and do not try to reconnect afterwards", function (done) {
|
||||
var max_attempts = 4;
|
||||
var client = redis.createClient({
|
||||
parser: parser,
|
||||
max_attempts: max_attempts
|
||||
});
|
||||
var calls = 0;
|
||||
var client;
|
||||
|
||||
client.once('ready', function() {
|
||||
helper.killConnection(client);
|
||||
});
|
||||
|
||||
client.on("reconnecting", function (params) {
|
||||
calls++;
|
||||
});
|
||||
|
||||
client.on('error', function(err) {
|
||||
if (/Redis connection in broken state: maximum connection attempts.*?exceeded./.test(err.message)) {
|
||||
setTimeout(function () {
|
||||
assert.strictEqual(calls, max_attempts - 1);
|
||||
done();
|
||||
}, 1500);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("emit an error after max retry timeout and do not try to reconnect afterwards", function (done) {
|
||||
var connect_timeout = 1000; // in ms
|
||||
var client = redis.createClient({
|
||||
parser: parser,
|
||||
connect_timeout: connect_timeout
|
||||
});
|
||||
var time = 0;
|
||||
|
||||
client.once('ready', function() {
|
||||
helper.killConnection(client);
|
||||
});
|
||||
|
||||
client.on("reconnecting", function (params) {
|
||||
time += params.delay;
|
||||
});
|
||||
|
||||
client.on('error', function(err) {
|
||||
if (/Redis connection in broken state: connection timeout.*?exceeded./.test(err.message)) {
|
||||
setTimeout(function () {
|
||||
assert(time === connect_timeout);
|
||||
done();
|
||||
}, 1500);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("end connection while retry is still ongoing", function (done) {
|
||||
var connect_timeout = 1000; // in ms
|
||||
var client = redis.createClient({
|
||||
parser: parser,
|
||||
connect_timeout: connect_timeout
|
||||
});
|
||||
|
||||
client.once('ready', function() {
|
||||
helper.killConnection(client);
|
||||
});
|
||||
|
||||
client.on("reconnecting", function (params) {
|
||||
afterEach(function () {
|
||||
if (client) {
|
||||
client.end();
|
||||
setTimeout(done, 100);
|
||||
}
|
||||
});
|
||||
|
||||
describe("on lost connection", function () {
|
||||
it("emit an error after max retry attempts and do not try to reconnect afterwards", function (done) {
|
||||
var max_attempts = 4;
|
||||
var options = {
|
||||
parser: parser,
|
||||
max_attempts: max_attempts
|
||||
};
|
||||
client = redis.createClient(options);
|
||||
assert.strictEqual(Object.keys(options).length, 2);
|
||||
var calls = 0;
|
||||
|
||||
client.once('ready', function() {
|
||||
helper.killConnection(client);
|
||||
});
|
||||
|
||||
client.on("reconnecting", function (params) {
|
||||
calls++;
|
||||
});
|
||||
|
||||
client.on('error', function(err) {
|
||||
if (/Redis connection in broken state: maximum connection attempts.*?exceeded./.test(err.message)) {
|
||||
setTimeout(function () {
|
||||
assert.strictEqual(calls, max_attempts - 1);
|
||||
done();
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("emit an error after max retry timeout and do not try to reconnect afterwards", function (done) {
|
||||
var connect_timeout = 500; // in ms
|
||||
client = redis.createClient({
|
||||
parser: parser,
|
||||
connect_timeout: connect_timeout
|
||||
});
|
||||
var time = 0;
|
||||
|
||||
client.once('ready', function() {
|
||||
helper.killConnection(client);
|
||||
});
|
||||
|
||||
client.on("reconnecting", function (params) {
|
||||
time += params.delay;
|
||||
});
|
||||
|
||||
client.on('error', function(err) {
|
||||
if (/Redis connection in broken state: connection timeout.*?exceeded./.test(err.message)) {
|
||||
setTimeout(function () {
|
||||
assert(time === connect_timeout);
|
||||
done();
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("end connection while retry is still ongoing", function (done) {
|
||||
var connect_timeout = 1000; // in ms
|
||||
client = redis.createClient({
|
||||
parser: parser,
|
||||
connect_timeout: connect_timeout
|
||||
});
|
||||
|
||||
client.once('ready', function() {
|
||||
helper.killConnection(client);
|
||||
});
|
||||
|
||||
client.on("reconnecting", function (params) {
|
||||
client.end();
|
||||
setTimeout(done, 100);
|
||||
});
|
||||
});
|
||||
|
||||
it("can not connect with wrong host / port in the options object", function (done) {
|
||||
var options = {
|
||||
host: 'somewhere',
|
||||
port: 6379,
|
||||
max_attempts: 1
|
||||
};
|
||||
client = redis.createClient(options);
|
||||
assert.strictEqual(Object.keys(options).length, 3);
|
||||
var end = helper.callFuncAfter(done, 2);
|
||||
|
||||
client.on('error', function (err) {
|
||||
assert(/CONNECTION_BROKEN|ENOTFOUND|EAI_AGAIN/.test(err.code));
|
||||
end();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it("can not connect with wrong host / port in the options object", function (done) {
|
||||
var client = redis.createClient({
|
||||
host: 'somewhere',
|
||||
port: 6379,
|
||||
max_attempts: 1
|
||||
});
|
||||
var end = helper.callFuncAfter(done, 2);
|
||||
describe("when not connected", function () {
|
||||
|
||||
client.on('error', function (err) {
|
||||
assert(/CONNECTION_BROKEN|ENOTFOUND|EAI_AGAIN/.test(err.code));
|
||||
end();
|
||||
it("connect with host and port provided in the options object", function (done) {
|
||||
client = redis.createClient({
|
||||
host: 'localhost',
|
||||
port: '6379',
|
||||
parser: parser,
|
||||
connect_timeout: 1000
|
||||
});
|
||||
|
||||
client.once('ready', function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
it("connects correctly with args", function (done) {
|
||||
client = redis.createClient.apply(redis.createClient, args);
|
||||
client.on("error", done);
|
||||
|
||||
it("connect with host and port provided in the options object", function (done) {
|
||||
var client = redis.createClient({
|
||||
host: 'localhost',
|
||||
port: '6379',
|
||||
parser: parser,
|
||||
connect_timeout: 1000
|
||||
client.once("ready", function () {
|
||||
client.removeListener("error", done);
|
||||
client.get("recon 1", function (err, res) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
client.once('ready', function() {
|
||||
done();
|
||||
it("connects correctly with default values", function (done) {
|
||||
client = redis.createClient();
|
||||
client.on("error", done);
|
||||
|
||||
client.once("ready", function () {
|
||||
client.removeListener("error", done);
|
||||
client.get("recon 1", function (err, res) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("connects with a port only", function (done) {
|
||||
client = redis.createClient(6379);
|
||||
client.on("error", done);
|
||||
|
||||
client.once("ready", function () {
|
||||
client.removeListener("error", done);
|
||||
client.get("recon 1", function (err, res) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("connects correctly to localhost", function (done) {
|
||||
client = redis.createClient(null, null);
|
||||
client.on("error", done);
|
||||
|
||||
client.once("ready", function () {
|
||||
client.removeListener("error", done);
|
||||
client.get("recon 1", function (err, res) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("connects correctly to localhost and no ready check", function (done) {
|
||||
client = redis.createClient(undefined, undefined, {
|
||||
no_ready_check: true
|
||||
});
|
||||
client.on("error", done);
|
||||
|
||||
client.once("ready", function () {
|
||||
client.set('foo', 'bar');
|
||||
client.get('foo', function(err, res) {
|
||||
assert.strictEqual(res, 'bar');
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("buffer commands and flush them after ", function (done) {
|
||||
client = redis.createClient(9999, null, {
|
||||
parser: parser
|
||||
});
|
||||
|
||||
client.on('error', function(e) {
|
||||
// ignore, b/c expecting a "can't connect" error
|
||||
});
|
||||
|
||||
return setTimeout(function() {
|
||||
client.set('foo', 'bar', function(err, result) {
|
||||
// This should never be called
|
||||
return done(err);
|
||||
});
|
||||
|
||||
return setTimeout(function() {
|
||||
assert.strictEqual(client.offline_queue.length, 1);
|
||||
return done();
|
||||
}, 25);
|
||||
}, 50);
|
||||
});
|
||||
|
||||
it("throws on strange connection info", function () {
|
||||
try {
|
||||
redis.createClient(true);
|
||||
throw new Error('failed');
|
||||
} catch (err) {
|
||||
assert.equal(err.message, 'Unknown type of connection in createClient()');
|
||||
}
|
||||
});
|
||||
|
||||
if (ip === 'IPv4') {
|
||||
it('allows connecting with the redis url and the default port', function (done) {
|
||||
client = redis.createClient('redis://foo:porkchopsandwiches@' + config.HOST[ip]);
|
||||
client.on("ready", function () {
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('allows connecting with the redis url and no auth and options as second parameter', function (done) {
|
||||
var options = {
|
||||
detect_buffers: false
|
||||
};
|
||||
client = redis.createClient('redis://' + config.HOST[ip] + ':' + config.PORT, options);
|
||||
assert.strictEqual(Object.keys(options).length, 1);
|
||||
client.on("ready", function () {
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('allows connecting with the redis url and no auth and options as third parameter', function (done) {
|
||||
client = redis.createClient('redis://' + config.HOST[ip] + ':' + config.PORT, null, {
|
||||
detect_buffers: false
|
||||
});
|
||||
client.on("ready", function () {
|
||||
return done();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -122,9 +122,9 @@ module.exports = {
|
||||
}
|
||||
var options = [{
|
||||
detect_buffers: true
|
||||
// Somehow we need a undefined here - otherwise the parsers return_buffers value is always true
|
||||
// Investigate this further
|
||||
}, undefined];
|
||||
}, {
|
||||
detect_buffers: false
|
||||
}];
|
||||
options.forEach(function (options) {
|
||||
var strOptions = '';
|
||||
var key;
|
||||
|
@@ -8,132 +8,41 @@ var redis = config.redis;
|
||||
|
||||
describe("The node_redis client", function () {
|
||||
|
||||
describe("testing parser existence", function () {
|
||||
it('throws on non-existence', function (done) {
|
||||
var mochaListener = helper.removeMochaListener();
|
||||
|
||||
process.once('uncaughtException', function (err) {
|
||||
process.on('uncaughtException', mochaListener);
|
||||
assert.equal(err.message, 'Couldn\'t find named parser nonExistingParser on this system');
|
||||
return done();
|
||||
});
|
||||
|
||||
redis.createClient({
|
||||
parser: 'nonExistingParser'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
helper.allTests({
|
||||
allConnections: true
|
||||
}, function(parser, ip, args) {
|
||||
|
||||
if (args[2]) { // skip if options are undefined
|
||||
describe("testing parser existence", function () {
|
||||
it('throws on non-existence', function (done) {
|
||||
var mochaListener = helper.removeMochaListener();
|
||||
|
||||
process.once('uncaughtException', function (err) {
|
||||
process.on('uncaughtException', mochaListener);
|
||||
assert.equal(err.message, 'Couldn\'t find named parser nonExistingParser on this system');
|
||||
return done();
|
||||
});
|
||||
|
||||
// Don't pollute the args for the other connections
|
||||
var tmp = JSON.parse(JSON.stringify(args));
|
||||
tmp[2].parser = 'nonExistingParser';
|
||||
redis.createClient.apply(redis.createClient, tmp);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe("using " + parser + " and " + ip, function () {
|
||||
var client;
|
||||
|
||||
describe("when not connected", function () {
|
||||
afterEach(function () {
|
||||
if (client) {
|
||||
client.end();
|
||||
}
|
||||
});
|
||||
|
||||
it("connects correctly with args", function (done) {
|
||||
client = redis.createClient.apply(redis.createClient, args);
|
||||
client.on("error", done);
|
||||
|
||||
client.once("ready", function () {
|
||||
client.removeListener("error", done);
|
||||
client.get("recon 1", function (err, res) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("connects correctly with default values", function (done) {
|
||||
client = redis.createClient();
|
||||
client.on("error", done);
|
||||
|
||||
client.once("ready", function () {
|
||||
client.removeListener("error", done);
|
||||
client.get("recon 1", function (err, res) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("connects correctly to localhost", function (done) {
|
||||
client = redis.createClient(null, null);
|
||||
client.on("error", done);
|
||||
|
||||
client.once("ready", function () {
|
||||
client.removeListener("error", done);
|
||||
client.get("recon 1", function (err, res) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("connects correctly to localhost and no ready check", function (done) {
|
||||
client = redis.createClient(undefined, undefined, {
|
||||
no_ready_check: true
|
||||
});
|
||||
client.on("error", done);
|
||||
|
||||
client.once("ready", function () {
|
||||
client.set('foo', 'bar');
|
||||
client.get('foo', function(err, res) {
|
||||
assert.strictEqual(res, 'bar');
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("throws on strange connection info", function () {
|
||||
try {
|
||||
redis.createClient(true);
|
||||
throw new Error('failed');
|
||||
} catch (err) {
|
||||
assert.equal(err.message, 'Unknown type of connection in createClient()');
|
||||
}
|
||||
});
|
||||
|
||||
if (ip === 'IPv4') {
|
||||
it('allows connecting with the redis url and the default port', function (done) {
|
||||
client = redis.createClient('redis://foo:porkchopsandwiches@' + config.HOST[ip]);
|
||||
client.on("ready", function () {
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('allows connecting with the redis url and no auth', function (done) {
|
||||
client = redis.createClient('redis://' + config.HOST[ip] + ':' + config.PORT, {
|
||||
detect_buffers: false
|
||||
});
|
||||
client.on("ready", function () {
|
||||
return done();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
afterEach(function () {
|
||||
client.end();
|
||||
});
|
||||
|
||||
describe("when connected", function () {
|
||||
beforeEach(function (done) {
|
||||
client = redis.createClient.apply(redis.createClient, args);
|
||||
client.once("error", done);
|
||||
client.once("connect", function () {
|
||||
client.flushdb(done);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
client.end();
|
||||
});
|
||||
|
||||
describe("send_command", function () {
|
||||
|
||||
it("omitting args should be fine in some cases", function (done) {
|
||||
@@ -211,7 +120,9 @@ describe("The node_redis client", function () {
|
||||
it("return an error in the callback", function (done) {
|
||||
if (helper.redisProcess().spawnFailed()) this.skip();
|
||||
|
||||
var client = redis.createClient();
|
||||
// TODO: Investigate why this test is failing hard and killing mocha if the client is created with .apply
|
||||
// Seems like something is wrong while passing a socket connection to create client! args[1]
|
||||
client = redis.createClient();
|
||||
client.quit(function() {
|
||||
client.get("foo", function(err, res) {
|
||||
assert(err.message.indexOf('Redis connection gone') !== -1);
|
||||
@@ -224,7 +135,6 @@ describe("The node_redis client", function () {
|
||||
it("return an error in the callback version two", function (done) {
|
||||
if (helper.redisProcess().spawnFailed()) this.skip();
|
||||
|
||||
var client = redis.createClient();
|
||||
client.quit();
|
||||
setTimeout(function() {
|
||||
client.get("foo", function(err, res) {
|
||||
@@ -239,7 +149,6 @@ describe("The node_redis client", function () {
|
||||
it("emit an error", function (done) {
|
||||
if (helper.redisProcess().spawnFailed()) this.skip();
|
||||
|
||||
var client = redis.createClient();
|
||||
client.quit();
|
||||
client.on('error', function(err) {
|
||||
assert.strictEqual(err.message, 'SET can\'t be processed. The connection has already been closed.');
|
||||
@@ -339,20 +248,19 @@ describe("The node_redis client", function () {
|
||||
return done();
|
||||
}
|
||||
|
||||
if (domain) {
|
||||
domain.run(function () {
|
||||
client.set('domain', 'value', function (err, res) {
|
||||
assert.ok(process.domain);
|
||||
throw new Error('ohhhh noooo');
|
||||
});
|
||||
domain.run(function () {
|
||||
client.set('domain', 'value', function (err, res) {
|
||||
assert.ok(process.domain);
|
||||
throw new Error('ohhhh noooo');
|
||||
});
|
||||
});
|
||||
|
||||
// this is the expected and desired behavior
|
||||
domain.on('error', function (err) {
|
||||
domain.exit();
|
||||
return done();
|
||||
});
|
||||
}
|
||||
// this is the expected and desired behavior
|
||||
domain.on('error', function (err) {
|
||||
assert.strictEqual(err.message, 'ohhhh noooo');
|
||||
domain.exit();
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -435,7 +343,6 @@ describe("The node_redis client", function () {
|
||||
|
||||
describe('socket_nodelay', function () {
|
||||
describe('true', function () {
|
||||
var client;
|
||||
var args = config.configureClient(parser, ip, {
|
||||
socket_nodelay: true
|
||||
});
|
||||
@@ -470,7 +377,6 @@ describe("The node_redis client", function () {
|
||||
});
|
||||
|
||||
describe('false', function () {
|
||||
var client;
|
||||
var args = config.configureClient(parser, ip, {
|
||||
socket_nodelay: false
|
||||
});
|
||||
@@ -505,7 +411,6 @@ describe("The node_redis client", function () {
|
||||
});
|
||||
|
||||
describe('defaults to true', function () {
|
||||
var client;
|
||||
|
||||
it("fires client.on('ready')", function (done) {
|
||||
client = redis.createClient.apply(redis.createClient, args);
|
||||
@@ -538,7 +443,6 @@ describe("The node_redis client", function () {
|
||||
});
|
||||
|
||||
describe('retry_max_delay', function () {
|
||||
var client;
|
||||
var args = config.configureClient(parser, ip, {
|
||||
retry_max_delay: 1 // ms
|
||||
});
|
||||
@@ -566,8 +470,36 @@ describe("The node_redis client", function () {
|
||||
|
||||
describe('enable_offline_queue', function () {
|
||||
describe('true', function () {
|
||||
it("should emit drain after info command and nothing to buffer", function (done) {
|
||||
client = redis.createClient({
|
||||
parser: parser
|
||||
});
|
||||
client.set('foo', 'bar');
|
||||
client.get('foo', function () {
|
||||
assert(!client.should_buffer);
|
||||
setTimeout(done, 25);
|
||||
});
|
||||
client.on('drain', function() {
|
||||
assert(client.offline_queue.length === 2);
|
||||
});
|
||||
});
|
||||
|
||||
it("should emit drain if offline queue is flushed and nothing to buffer", function (done) {
|
||||
client = redis.createClient({
|
||||
parser: parser,
|
||||
no_ready_check: true
|
||||
});
|
||||
var end = helper.callFuncAfter(done, 2);
|
||||
client.set('foo', 'bar');
|
||||
client.get('foo', end);
|
||||
client.on('drain', function() {
|
||||
assert(client.offline_queue.length === 0);
|
||||
end();
|
||||
});
|
||||
});
|
||||
|
||||
it("does not return an error and enqueues operation", function (done) {
|
||||
var client = redis.createClient(9999, null, {
|
||||
client = redis.createClient(9999, null, {
|
||||
max_attempts: 0,
|
||||
parser: parser
|
||||
});
|
||||
@@ -578,10 +510,8 @@ describe("The node_redis client", function () {
|
||||
|
||||
return setTimeout(function() {
|
||||
client.set('foo', 'bar', function(err, result) {
|
||||
// TODO: figure out why we emit an error on
|
||||
// even though we've enabled the offline queue.
|
||||
if (process.platform === 'win32') return;
|
||||
if (err) return done(err);
|
||||
// This should never be called
|
||||
return done(err);
|
||||
});
|
||||
|
||||
return setTimeout(function() {
|
||||
@@ -592,7 +522,7 @@ describe("The node_redis client", function () {
|
||||
});
|
||||
|
||||
it("enqueues operation and keep the queue while trying to reconnect", function (done) {
|
||||
var client = redis.createClient(9999, null, {
|
||||
client = redis.createClient(9999, null, {
|
||||
max_attempts: 4,
|
||||
parser: parser
|
||||
});
|
||||
@@ -627,8 +557,23 @@ describe("The node_redis client", function () {
|
||||
});
|
||||
|
||||
describe('false', function () {
|
||||
|
||||
it('stream not writable', function(done) {
|
||||
client = redis.createClient({
|
||||
parser: parser,
|
||||
enable_offline_queue: false
|
||||
});
|
||||
client.on('ready', function () {
|
||||
client.stream.writable = false;
|
||||
client.set('foo', 'bar', function (err, res) {
|
||||
assert.strictEqual(err.message, "SET can't be processed. Stream not writeable.");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("emit an error and does not enqueues operation", function (done) {
|
||||
var client = redis.createClient(9999, null, {
|
||||
client = redis.createClient(9999, null, {
|
||||
parser: parser,
|
||||
max_attempts: 0,
|
||||
enable_offline_queue: false
|
||||
@@ -636,7 +581,7 @@ describe("The node_redis client", function () {
|
||||
var end = helper.callFuncAfter(done, 3);
|
||||
|
||||
client.on('error', function(err) {
|
||||
assert(/Stream not writeable|ECONNREFUSED/.test(err.message));
|
||||
assert(/offline queue is deactivated|ECONNREFUSED/.test(err.message));
|
||||
assert.equal(client.command_queue.length, 0);
|
||||
end();
|
||||
});
|
||||
@@ -653,7 +598,7 @@ describe("The node_redis client", function () {
|
||||
});
|
||||
|
||||
it("flushes the command queue connection if in broken connection mode", function (done) {
|
||||
var client = redis.createClient({
|
||||
client = redis.createClient({
|
||||
parser: parser,
|
||||
max_attempts: 2,
|
||||
enable_offline_queue: false
|
||||
|
113
test/parser.spec.js
Normal file
113
test/parser.spec.js
Normal file
@@ -0,0 +1,113 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var config = require("./lib/config");
|
||||
var utils = require("../lib/utils");
|
||||
var redis = config.redis;
|
||||
var parsers = [
|
||||
require("../lib/parsers/javascript").Parser
|
||||
];
|
||||
try {
|
||||
// Test the hiredis parser if available
|
||||
parsers.push(require("../lib/parsers/hiredis").Parser);
|
||||
} catch (e) {}
|
||||
|
||||
describe('parsers', function () {
|
||||
|
||||
parsers.forEach(function (Parser) {
|
||||
|
||||
describe(Parser.name, function () {
|
||||
|
||||
it('handles multi-bulk reply', function (done) {
|
||||
var parser = new Parser();
|
||||
var reply_count = 0;
|
||||
function check_reply(reply) {
|
||||
reply = utils.reply_to_strings(reply);
|
||||
assert.deepEqual(reply, [['a']], "Expecting multi-bulk reply of [['a']]");
|
||||
reply_count++;
|
||||
}
|
||||
parser.send_reply = check_reply;
|
||||
|
||||
parser.execute(new Buffer('*1\r\n*1\r\n$1\r\na\r\n'));
|
||||
|
||||
parser.execute(new Buffer('*1\r\n*1\r'));
|
||||
parser.execute(new Buffer('\n$1\r\na\r\n'));
|
||||
|
||||
parser.execute(new Buffer('*1\r\n*1\r\n'));
|
||||
parser.execute(new Buffer('$1\r\na\r\n'));
|
||||
|
||||
assert.equal(reply_count, 3, "check reply should have been called three times");
|
||||
return done();
|
||||
});
|
||||
|
||||
it('parser error', function (done) {
|
||||
var parser = new Parser();
|
||||
var reply_count = 0;
|
||||
function check_reply(reply) {
|
||||
assert.strictEqual(reply.message, 'Protocol error, got "a" as reply type byte');
|
||||
reply_count++;
|
||||
}
|
||||
parser.send_error = check_reply;
|
||||
|
||||
parser.execute(new Buffer('a*1\r*1\r$1`zasd\r\na'));
|
||||
|
||||
assert.equal(reply_count, 1, "check reply should have been called one time");
|
||||
return done();
|
||||
});
|
||||
|
||||
it('line breaks in the beginning', function (done) {
|
||||
var parser = new Parser();
|
||||
var reply_count = 0;
|
||||
function check_reply(reply) {
|
||||
reply = utils.reply_to_strings(reply);
|
||||
assert.deepEqual(reply, [['a']], "Expecting multi-bulk reply of [['a']]");
|
||||
reply_count++;
|
||||
}
|
||||
parser.send_reply = check_reply;
|
||||
|
||||
parser.execute(new Buffer('*1\r\n*1\r\n$1\r\na'));
|
||||
|
||||
parser.execute(new Buffer('\r\n*1\r\n*1\r'));
|
||||
parser.execute(new Buffer('\n$1\r\na\r\n'));
|
||||
|
||||
parser.execute(new Buffer('*1\r\n*1\r\n'));
|
||||
parser.execute(new Buffer('$1\r\na\r\n'));
|
||||
|
||||
assert.equal(reply_count, 3, "check reply should have been called three times");
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Activate this if you want to fry your cpu / memory
|
||||
describe.skip("test out of memory", function () {
|
||||
var args = config.configureClient('javascript', '127.0.0.1');
|
||||
var clients = new Array(300).join(" ").split(" ");
|
||||
var client;
|
||||
beforeEach(function (done) {
|
||||
client = redis.createClient.apply(redis.createClient, args);
|
||||
client.once("connect", function () {
|
||||
client.flushdb(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('reach limit and wait for further data', function (done) {
|
||||
setTimeout(done, 5000);
|
||||
clients.forEach(function(entry, a) {
|
||||
var max = 0;
|
||||
var client = redis.createClient.apply(redis.createClient, args);
|
||||
client.on('ready', function() {
|
||||
while (++max < 50) {
|
||||
var item = [];
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
item.push('aaa' + (Math.random() * 1000000 | 0));
|
||||
}
|
||||
client.del('foo' + a);
|
||||
client.lpush('foo' + a, item);
|
||||
client.lrange('foo' + a, 0, 99);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@@ -1,63 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var Parser = require("../../lib/parsers/javascript").Parser;
|
||||
var config = require("../lib/config");
|
||||
var utils = require("../../lib/utils");
|
||||
var redis = config.redis;
|
||||
|
||||
describe('javascript parser', function () {
|
||||
it('handles multi-bulk reply', function (done) {
|
||||
var parser = new Parser();
|
||||
var reply_count = 0;
|
||||
function check_reply(reply) {
|
||||
reply = utils.reply_to_strings(reply);
|
||||
assert.deepEqual(reply, [['a']], "Expecting multi-bulk reply of [['a']]");
|
||||
reply_count++;
|
||||
}
|
||||
parser.send_reply = check_reply;
|
||||
|
||||
parser.execute(new Buffer('*1\r\n*1\r\n$1\r\na\r\n'));
|
||||
|
||||
parser.execute(new Buffer('*1\r\n*1\r'));
|
||||
parser.execute(new Buffer('\n$1\r\na\r\n'));
|
||||
|
||||
parser.execute(new Buffer('*1\r\n*1\r\n'));
|
||||
parser.execute(new Buffer('$1\r\na\r\n'));
|
||||
|
||||
assert.equal(reply_count, 3, "check reply should have been called three times");
|
||||
return done();
|
||||
});
|
||||
|
||||
// Activate this if you want to fry your cpu / memory
|
||||
describe.skip("test out of memory", function () {
|
||||
var args = config.configureClient('javascript', '127.0.0.1');
|
||||
var clients = new Array(300).join(" ").split(" ");
|
||||
var client;
|
||||
beforeEach(function (done) {
|
||||
client = redis.createClient.apply(redis.createClient, args);
|
||||
client.once("connect", function () {
|
||||
client.flushdb(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('reach limit and wait for further data', function (done) {
|
||||
setTimeout(done, 5000);
|
||||
clients.forEach(function(entry, a) {
|
||||
var max = 0;
|
||||
var client = redis.createClient.apply(redis.createClient, args);
|
||||
client.on('ready', function() {
|
||||
while (++max < 50) {
|
||||
var item = [];
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
item.push('aaa' + (Math.random() * 1000000 | 0));
|
||||
}
|
||||
client.del('foo' + a);
|
||||
client.lpush('foo' + a, item);
|
||||
client.lrange('foo' + a, 0, 99);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@@ -242,8 +242,12 @@ describe("publish/subscribe", function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('does not complain when unsubscribe is called and there are no subscriptions', function () {
|
||||
sub.unsubscribe();
|
||||
it('does not complain when unsubscribe is called and there are no subscriptions', function (done) {
|
||||
sub.unsubscribe(function (err, res) {
|
||||
assert.strictEqual(err, null);
|
||||
assert.strictEqual(res, null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('executes callback when unsubscribe is called and there are no subscriptions', function (done) {
|
||||
@@ -285,6 +289,34 @@ describe("publish/subscribe", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('fail for other commands while in pub sub mode', function () {
|
||||
it('return error if only pub sub commands are allowed', function (done) {
|
||||
sub.subscribe('channel');
|
||||
// Ping is allowed even if not listed as such!
|
||||
sub.ping(function (err, res) {
|
||||
assert.strictEqual(err, null);
|
||||
assert.strictEqual(res[0], 'pong');
|
||||
});
|
||||
// Get is forbidden
|
||||
sub.get('foo', function (err, res) {
|
||||
assert.strictEqual(err.message, 'ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context');
|
||||
assert.strictEqual(err.command, 'GET');
|
||||
});
|
||||
// Quit is allowed
|
||||
sub.quit(done);
|
||||
});
|
||||
|
||||
it('emit error if only pub sub commands are allowed without callback', function (done) {
|
||||
sub.subscribe('channel');
|
||||
sub.on('error', function (err) {
|
||||
assert.strictEqual(err.message, 'ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context');
|
||||
assert.strictEqual(err.command, 'GET');
|
||||
done();
|
||||
});
|
||||
sub.get('foo');
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Fix pub sub
|
||||
// And there's more than just those two issues
|
||||
describe.skip('FIXME: broken pub sub', function () {
|
||||
@@ -297,7 +329,7 @@ describe("publish/subscribe", function () {
|
||||
pub.on('message', function (msg) {
|
||||
done(new Error('This message should not have been published: ' + msg));
|
||||
});
|
||||
setTimeout(done, 500);
|
||||
setTimeout(done, 200);
|
||||
});
|
||||
|
||||
it("should not publish a message multiple times per command", function (done) {
|
||||
@@ -325,8 +357,8 @@ describe("publish/subscribe", function () {
|
||||
sub.unsubscribe();
|
||||
setTimeout(function () {
|
||||
subscribe('world');
|
||||
}, 400);
|
||||
}, 400);
|
||||
}, 40);
|
||||
}, 40);
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -19,6 +19,8 @@ describe("return_buffers", function () {
|
||||
beforeEach(function (done) {
|
||||
client = redis.createClient.apply(redis.createClient, args);
|
||||
if (args[2].detect_buffers) {
|
||||
// Test if detect_buffer option was deactivated
|
||||
assert.strictEqual(client.options.detect_buffers, false);
|
||||
args[2].detect_buffers = false;
|
||||
}
|
||||
client.once("error", done);
|
||||
|
Reference in New Issue
Block a user