You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-09 00:22:08 +03:00
This is not necessary as the command itself is only used from inside the code and as they are (now) all lower case it is safe to remove the toLowerCase
244 lines
11 KiB
JavaScript
244 lines
11 KiB
JavaScript
'use strict';
|
|
|
|
var assert = require('assert');
|
|
var config = require("../lib/config");
|
|
var helper = require('../helper');
|
|
var redis = config.redis;
|
|
var uuid = require('uuid');
|
|
|
|
describe("The 'multi' method", function () {
|
|
|
|
helper.allTests(function(parser, ip, args) {
|
|
|
|
describe("using " + parser + " and " + ip, function () {
|
|
var key, value;
|
|
|
|
beforeEach(function () {
|
|
key = uuid.v4();
|
|
value = uuid.v4();
|
|
});
|
|
|
|
describe("when not connected", function () {
|
|
var client;
|
|
|
|
beforeEach(function (done) {
|
|
client = redis.createClient.apply(redis.createClient, args);
|
|
client.once("error", done);
|
|
client.once("connect", function () {
|
|
client.quit();
|
|
});
|
|
client.on('end', function () {
|
|
return done();
|
|
});
|
|
});
|
|
|
|
it("reports an error", function (done) {
|
|
client.multi();
|
|
client.exec(function (err, res) {
|
|
assert.equal(err.message, 'Redis connection gone from end event.');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("when connected", function () {
|
|
var client;
|
|
|
|
beforeEach(function (done) {
|
|
client = redis.createClient.apply(redis.createClient, args);
|
|
client.once("error", done);
|
|
client.once("connect", function () {
|
|
client.flushdb(function (err) {
|
|
return done(err);
|
|
});
|
|
});
|
|
});
|
|
|
|
afterEach(function () {
|
|
client.end();
|
|
});
|
|
|
|
it('roles back a transaction when one command in a sequence of commands fails', function (done) {
|
|
var multi1, multi2;
|
|
|
|
// Provoke an error at queue time
|
|
multi1 = client.MULTI();
|
|
multi1.mset("multifoo", "10", "multibar", "20", helper.isString("OK"));
|
|
multi1.set("foo2", helper.isError());
|
|
multi1.incr("multifoo", helper.isNumber(11));
|
|
multi1.incr("multibar", helper.isNumber(21));
|
|
multi1.exec(function () {
|
|
// Redis 2.6.5+ will abort transactions with errors
|
|
// see: http://redis.io/topics/transactions
|
|
var multibar_expected = 22;
|
|
var multifoo_expected = 12;
|
|
if (helper.serverVersionAtLeast(client, [2, 6, 5])) {
|
|
multibar_expected = 1;
|
|
multifoo_expected = 1;
|
|
}
|
|
|
|
// Confirm that the previous command, while containing an error, still worked.
|
|
multi2 = client.multi();
|
|
multi2.incr("multibar", helper.isNumber(multibar_expected));
|
|
multi2.incr("multifoo", helper.isNumber(multifoo_expected));
|
|
multi2.exec(function (err, replies) {
|
|
assert.strictEqual(multibar_expected, replies[0]);
|
|
assert.strictEqual(multifoo_expected, replies[1]);
|
|
return done();
|
|
});
|
|
});
|
|
});
|
|
|
|
// I'm unclear as to the difference between this test in the test above,
|
|
// perhaps @mranney can clarify?
|
|
it('roles back a transaction when an error was provoked at queue time', function (done) {
|
|
var multi1 = client.multi();
|
|
multi1.mset("multifoo_8", "10", "multibar_8", "20", helper.isString("OK"));
|
|
multi1.set("foo2", helper.isError());
|
|
multi1.set("foo3", helper.isError());
|
|
multi1.incr("multifoo_8", helper.isNumber(11));
|
|
multi1.incr("multibar_8", helper.isNumber(21));
|
|
multi1.exec(function () {
|
|
// Redis 2.6.5+ will abort transactions with errors
|
|
// see: http://redis.io/topics/transactions
|
|
var multibar_expected = 22;
|
|
var multifoo_expected = 12;
|
|
if (helper.serverVersionAtLeast(client, [2, 6, 5])) {
|
|
multibar_expected = 1;
|
|
multifoo_expected = 1;
|
|
}
|
|
|
|
// Confirm that the previous command, while containing an error, still worked.
|
|
var multi2 = client.multi();
|
|
multi2.incr("multibar_8", helper.isNumber(multibar_expected));
|
|
multi2.incr("multifoo_8", helper.isNumber(multifoo_expected));
|
|
multi2.exec(function (err, replies) {
|
|
assert.strictEqual(multibar_expected, replies[0]);
|
|
assert.strictEqual(multifoo_expected, replies[1]);
|
|
return done();
|
|
});
|
|
});
|
|
});
|
|
|
|
it('roles back a transaction when one command in an array of commands fails', function (done) {
|
|
// test nested multi-bulk replies
|
|
client.multi([
|
|
["mget", "multifoo", "multibar", function (err, res) {
|
|
assert.strictEqual(2, res.length);
|
|
assert.strictEqual("0", res[0].toString());
|
|
assert.strictEqual("0", res[1].toString());
|
|
}],
|
|
["set", "foo2", helper.isError()],
|
|
["incr", "multifoo", helper.isNumber(1)],
|
|
["incr", "multibar", helper.isNumber(1)]
|
|
]).exec(function (err, replies) {
|
|
if (helper.serverVersionAtLeast(client, [2, 6, 5])) {
|
|
assert.notEqual(err, null);
|
|
assert.equal(replies, undefined);
|
|
} else {
|
|
assert.strictEqual(2, replies[0].length);
|
|
assert.strictEqual("0", replies[0][0].toString());
|
|
assert.strictEqual("0", replies[0][1].toString());
|
|
|
|
assert.strictEqual("1", replies[1].toString());
|
|
assert.strictEqual("1", replies[2].toString());
|
|
}
|
|
|
|
return done();
|
|
});
|
|
});
|
|
|
|
it('handles multiple operations being applied to a set', function (done) {
|
|
client.sadd("some set", "mem 1");
|
|
client.sadd("some set", "mem 2");
|
|
client.sadd("some set", "mem 3");
|
|
client.sadd("some set", "mem 4");
|
|
|
|
// make sure empty mb reply works
|
|
client.del("some missing set");
|
|
client.smembers("some missing set", function (err, reply) {
|
|
// make sure empty mb reply works
|
|
assert.strictEqual(0, reply.length);
|
|
});
|
|
|
|
// test nested multi-bulk replies with empty mb elements.
|
|
client.multi([
|
|
["smembers", "some set"],
|
|
["del", "some set"],
|
|
["smembers", "some set"]
|
|
])
|
|
.scard("some set")
|
|
.exec(function (err, replies) {
|
|
assert.strictEqual(4, replies[0].length);
|
|
assert.strictEqual(0, replies[2].length);
|
|
return done();
|
|
});
|
|
});
|
|
|
|
it('allows multiple operations to be performed using a chaining API', function (done) {
|
|
client.multi()
|
|
.mset('some', '10', 'keys', '20')
|
|
.incr('some')
|
|
.incr('keys')
|
|
.mget('some', 'keys')
|
|
.exec(function (err, replies) {
|
|
assert.strictEqual(null, err);
|
|
assert.equal('OK', replies[0]);
|
|
assert.equal(11, replies[1]);
|
|
assert.equal(21, replies[2]);
|
|
assert.equal(11, replies[3][0].toString());
|
|
assert.equal(21, replies[3][1].toString());
|
|
return done();
|
|
});
|
|
});
|
|
|
|
it('allows an array to be provided indicating multiple operations to perform', function (done) {
|
|
// test nested multi-bulk replies with nulls.
|
|
client.multi([
|
|
["mget", ["multifoo", "some", "random value", "keys"]],
|
|
["incr", "multifoo"]
|
|
])
|
|
.exec(function (err, replies) {
|
|
assert.strictEqual(replies.length, 2);
|
|
assert.strictEqual(replies[0].length, 4);
|
|
return done();
|
|
});
|
|
});
|
|
|
|
it('allows multiple operations to be performed on a hash', function (done) {
|
|
client.multi()
|
|
.hmset("multihash", "a", "foo", "b", 1)
|
|
.hmset("multihash", {
|
|
extra: "fancy",
|
|
things: "here"
|
|
})
|
|
.hgetall("multihash")
|
|
.exec(function (err, replies) {
|
|
assert.strictEqual(null, err);
|
|
assert.equal("OK", replies[0]);
|
|
assert.equal(Object.keys(replies[2]).length, 4);
|
|
assert.equal("foo", replies[2].a);
|
|
assert.equal("1", replies[2].b);
|
|
assert.equal("fancy", replies[2].extra);
|
|
assert.equal("here", replies[2].things);
|
|
return done();
|
|
});
|
|
});
|
|
|
|
it('reports multiple exceptions when they occur', function (done) {
|
|
if (!helper.serverVersionAtLeast(client, [2, 6, 5])) return done();
|
|
|
|
client.multi().set("foo").exec(function (err, reply) {
|
|
assert(Array.isArray(err), "err should be an array");
|
|
assert.equal(2, err.length, "err should have 2 items");
|
|
assert(err[0].message.match(/ERR/), "First error message should contain ERR");
|
|
assert(err[1].message.match(/EXECABORT/), "First error message should contain EXECABORT");
|
|
return done();
|
|
});
|
|
});
|
|
|
|
});
|
|
});
|
|
});
|
|
});
|