mongoose
Version:
Mongoose MongoDB ODM
289 lines (243 loc) • 8.59 kB
JavaScript
var start = require('./common')
, assert = require('assert')
, random = require('../lib/utils').random
, mongoose = start.mongoose
, Mongoose = mongoose.Mongoose
, Schema = mongoose.Schema;
var uri = process.env.MONGOOSE_SHARD_TEST_URI;
if (!uri) {
console.log('\033[31m', '\n', 'You\'re not testing shards!'
, '\n', 'Please set the MONGOOSE_SHARD_TEST_URI env variable.', '\n'
, 'e.g: `mongodb://localhost:27017/database', '\n'
, 'Sharding must already be enabled on your database'
, '\033[39m');
// let expresso shut down this test
exports.r = function expressoHack(){}
return;
}
var schema = new Schema({
name: String
, age: Number
, likes: [String]
}, { shardkey: { name: 1, age: 1 }});
var collection = 'shardperson_' + random();
mongoose.model('ShardPerson', schema, collection);
var version;
var greaterThan20x;
var db;
describe('shard', function(){
before(function (done) {
db = start({ uri: uri });
db.on('error', function (err) {
if (/failed to connect/.test(err)) {
err.message = 'Shard test error: '
+ err.message
+ '\n'
+ ' Are you sure there is a db running at '
+ uri + ' ?'
+ '\n'
}
// let expresso shut down this test
throw err;
});
db.on('open', function () {
// set up a sharded test collection
var P = db.model('ShardPerson', collection);
var cmd = {};
cmd.shardcollection = db.name + '.' + collection;
cmd.key = P.schema.options.shardkey;
P.db.db.executeDbAdminCommand(cmd,function (err, res) {
db.close();
assert.ifError(err);
if (!(res && res.documents && res.documents[0] && res.documents[0].ok)) {
throw new Error('could not shard test collection '
+ collection + '\n'
+ res.documents[0].errmsg);
}
db.db.admin(function (err, admin) {
assert.ifError(err);
admin.serverStatus(function (err, info) {
assert.ifError(err);
version = info.version.split('.').map(function(n){return parseInt(n, 10) });
greaterThan20x = 2 < version[0] || 2==version[0] && 0<version[0];
done();
});
});
});
});
});
it('can read and write to a shard', function (done) {
var db = start({ uri: uri })
var P = db.model('ShardPerson', collection);
P.create({ name: 'ryu', age: 25, likes: ['street fighting']}, function (err, ryu) {
assert.ifError(err);
P.findById(ryu._id, function (err, doc) {
db.close();
assert.ifError(err);
assert.equal(doc.id,ryu.id);
done();
});
});
})
it('save() and remove() works with shard keys transparently', function (done) {
var db = start({ uri: uri })
var P = db.model('ShardPerson', collection);
var zangief = new P({ name: 'Zangief', age: 33 });
zangief.save(function (err) {
assert.ifError(err);
assert.equal(zangief._shardval.name, 'Zangief');
assert.equal(zangief._shardval.age, 33);
P.findById(zangief._id, function (err, zang) {
assert.ifError(err);
assert.equal(zang._shardval.name, 'Zangief');
assert.equal(zang._shardval.age, 33);
zang.likes = ['spinning', 'laughing'];
zang.save(function (err) {
assert.ifError(err);
assert.equal(zang._shardval.name, 'Zangief');
assert.equal(zang._shardval.age, 33);
zang.likes.addToSet('winning');
zang.save(function (err) {
assert.ifError(err);
assert.equal(zang._shardval.name, 'Zangief');
assert.equal(zang._shardval.age, 33);
zang.remove(function (err) {
db.close();
assert.ifError(err);
done();
});
});
});
});
});
})
it('inserting to a sharded collection without the full shard key fails', function (done) {
var db = start({ uri: uri })
var P = db.model('ShardPerson', collection);
var pending = 6;
P.create({ name: 'ryu', likes: ['street fighting']}, function (err, ryu) {
assert.ok(err);
assert.ok(/tried to insert object with no valid shard key/.test(err.message));
if (!--pending) {
db.close();
done();
}
});
P.create({ likes: ['street fighting']}, function (err, ryu) { assert.ok(err);
assert.ok(err);
assert.ok(/tried to insert object with no valid shard key/.test(err.message));
if (!--pending) {
db.close();
done();
}
});
P.create({ name: 'ryu' }, function (err, ryu) { assert.ok(err);
assert.ok(err);
assert.ok(/tried to insert object with no valid shard key/.test(err.message));
if (!--pending) {
db.close();
done();
}
});
P.create({ age: 49 }, function (err, ryu) { assert.ok(err);
assert.ok(err);
assert.ok(/tried to insert object with no valid shard key/.test(err.message));
if (!--pending) {
db.close();
done();
}
});
P.create({ likes: ['street fighting'], age: 8 }, function (err, ryu) {
assert.ok(err);
assert.ok(/tried to insert object with no valid shard key/.test(err.message))
if (!--pending) {
db.close();
done();
}
});
var p = new P;
p.save(function (err) {
assert.ok(err);
assert.ok(/tried to insert object with no valid shard key/.test(err.message));
if (!--pending) {
db.close();
done();
}
});
});
it('updating a sharded collection without the full shard key fails', function (done) {
var db = start({ uri: uri })
var P = db.model('ShardPerson', collection);
P.create({ name: 'ken', age: 27 }, function (err, ken) {
assert.ifError(err);
P.update({ name: 'ken' }, { likes: ['kicking', 'punching'] }, function (err) {
assert.ok(/shard key/.test(err.message));
P.update({ _id: ken._id, name: 'ken' }, { likes: ['kicking', 'punching'] }, function (err) {
// mongo 2.0.x returns: can't do non-multi update with query that doesn't have a valid shard key
if (greaterThan20x) {
assert.ok(!err, err);
} else {
assert.ok(/shard key/.test(err.message));
}
P.update({ _id: ken._id, age: 27 }, { likes: ['kicking', 'punching'] }, function (err) {
// mongo 2.0.x returns: can't do non-multi update with query that doesn't have a valid shard key
if (greaterThan20x) {
assert.ok(!err, err);
} else {
assert.ok(/shard key/.test(err.message));
}
P.update({ age: 27 }, { likes: ['kicking', 'punching'] }, function (err) {
db.close();
assert.ok(err);
done();
});
});
});
});
});
})
it('updating shard key values fails', function (done) {
var db = start({ uri: uri })
var P = db.model('ShardPerson', collection);
P.create({ name: 'chun li', age: 19, likes: ['street fighting']}, function (err, chunli) {
assert.ifError(err);
assert.equal(chunli._shardval.name, 'chun li');
assert.equal(chunli._shardval.age, 19);
chunli.age = 20;
chunli.save(function (err) {
assert.ok(/^Can't modify shard key's value/.test(err.message));
assert.equal(chunli._shardval.name, 'chun li');
assert.equal(chunli._shardval.age, 19);
P.findById(chunli._id, function (err, chunli) {
assert.ifError(err);
assert.equal(chunli._shardval.name, 'chun li');
assert.equal(chunli._shardval.age, 19);
chunli.name='chuuuun liiiii';
chunli.save(function (err) {
db.close();
assert.ok(/^Can't modify shard key's value/.test(err.message));
done();
});
});
});
});
});
it('allows null shard key values', function (done) {
var db = start({ uri: uri })
var P = db.model('ShardPerson', collection);
P.create({ name: null, age: 27 }, function (err, ken) {
assert.ifError(err);
P.findById(ken, function (err, ken) {
assert.ifError(err);
done();
});
});
});
after(function (done) {
var db = start({ uri: uri })
var P = db.model('ShardPerson', collection);
P.collection.drop(function (err) {
done();
});
});
})