Files
mongo/jstests/core/list_collections1.js
2016-07-19 10:10:43 -04:00

259 lines
9.5 KiB
JavaScript

// Basic functional tests for the listCollections command.
//
// Note that storage engines are allowed to advertise internal collections to the user (in
// particular, the MMAPv1 storage engine currently advertises the "system.indexes" collection).
// Hence, this test suite does not test for a particular number of collections returned in
// listCollections output, but rather tests for existence or absence of particular collections in
// listCollections output.
(function() {
"use strict";
var mydb = db.getSiblingDB("list_collections1");
var cursor;
var res;
var collObj;
//
// Test basic command output.
//
assert.commandWorked(mydb.dropDatabase());
assert.commandWorked(mydb.createCollection("foo"));
res = mydb.runCommand("listCollections");
assert.commandWorked(res);
assert.eq('object', typeof(res.cursor));
assert.eq(0, res.cursor.id);
assert.eq('string', typeof(res.cursor.ns));
collObj = res.cursor.firstBatch.filter(function(c) {
return c.name === "foo";
})[0];
assert(collObj);
assert.eq('object', typeof(collObj.options));
assert.eq('collection', collObj.type, tojson(collObj));
assert.eq(false, collObj.info.readOnly, tojson(collObj));
//
// Test basic usage with DBCommandCursor.
//
var getListCollectionsCursor = function(options, subsequentBatchSize) {
return new DBCommandCursor(
mydb.getMongo(), mydb.runCommand("listCollections", options), subsequentBatchSize);
};
var cursorCountMatching = function(cursor, pred) {
return cursor.toArray().filter(pred).length;
};
assert.commandWorked(mydb.dropDatabase());
assert.commandWorked(mydb.createCollection("foo"));
assert.eq(1, cursorCountMatching(getListCollectionsCursor(), function(c) {
return c.name === "foo";
}));
//
// Test that the collection metadata object is returned correctly.
//
assert.commandWorked(mydb.dropDatabase());
assert.commandWorked(mydb.createCollection("foo"));
assert.commandWorked(mydb.createCollection("bar", {temp: true}));
assert.eq(1, cursorCountMatching(getListCollectionsCursor(), function(c) {
return c.name === "foo" && c.options.temp === undefined;
}));
assert.eq(1, cursorCountMatching(getListCollectionsCursor(), function(c) {
return c.name === "bar" && c.options.temp === true;
}));
//
// Test basic usage of "filter" option.
//
assert.commandWorked(mydb.dropDatabase());
assert.commandWorked(mydb.createCollection("foo"));
assert.commandWorked(mydb.createCollection("bar", {temp: true}));
assert.eq(2, cursorCountMatching(getListCollectionsCursor({filter: {}}), function(c) {
return c.name === "foo" || c.name === "bar";
}));
assert.eq(2, getListCollectionsCursor({filter: {name: {$in: ["foo", "bar"]}}}).itcount());
assert.eq(1, getListCollectionsCursor({filter: {name: /^foo$/}}).itcount());
assert.eq(1, getListCollectionsCursor({filter: {"options.temp": true}}).itcount());
mydb.foo.drop();
assert.eq(1, cursorCountMatching(getListCollectionsCursor({filter: {}}), function(c) {
return c.name === "foo" || c.name === "bar";
}));
assert.eq(1, getListCollectionsCursor({filter: {name: {$in: ["foo", "bar"]}}}).itcount());
assert.eq(0, getListCollectionsCursor({filter: {name: /^foo$/}}).itcount());
assert.eq(1, getListCollectionsCursor({filter: {"options.temp": true}}).itcount());
mydb.bar.drop();
assert.eq(0, cursorCountMatching(getListCollectionsCursor({filter: {}}), function(c) {
return c.name === "foo" || c.name === "bar";
}));
assert.eq(0, getListCollectionsCursor({filter: {name: {$in: ["foo", "bar"]}}}).itcount());
assert.eq(0, getListCollectionsCursor({filter: {name: /^foo$/}}).itcount());
assert.eq(0, getListCollectionsCursor({filter: {"options.temp": true}}).itcount());
//
// Test for invalid values of "filter".
//
assert.throws(function() {
getListCollectionsCursor({filter: {$invalid: 1}});
});
assert.throws(function() {
getListCollectionsCursor({filter: 0});
});
assert.throws(function() {
getListCollectionsCursor({filter: 'x'});
});
assert.throws(function() {
getListCollectionsCursor({filter: []});
});
//
// Test basic usage of "cursor.batchSize" option.
//
assert.commandWorked(mydb.dropDatabase());
assert.commandWorked(mydb.createCollection("foo"));
assert.commandWorked(mydb.createCollection("bar"));
cursor = getListCollectionsCursor({cursor: {batchSize: 2}});
assert.eq(2, cursor.objsLeftInBatch());
assert.eq(2, cursorCountMatching(cursor, function(c) {
return c.name === "foo" || c.name === "bar";
}));
cursor = getListCollectionsCursor({cursor: {batchSize: 1}});
assert.eq(1, cursor.objsLeftInBatch());
assert.eq(2, cursorCountMatching(cursor, function(c) {
return c.name === "foo" || c.name === "bar";
}));
cursor = getListCollectionsCursor({cursor: {batchSize: 0}});
assert.eq(0, cursor.objsLeftInBatch());
assert.eq(2, cursorCountMatching(cursor, function(c) {
return c.name === "foo" || c.name === "bar";
}));
cursor = getListCollectionsCursor({cursor: {batchSize: NumberInt(2)}});
assert.eq(2, cursor.objsLeftInBatch());
assert.eq(2, cursorCountMatching(cursor, function(c) {
return c.name === "foo" || c.name === "bar";
}));
cursor = getListCollectionsCursor({cursor: {batchSize: NumberLong(2)}});
assert.eq(2, cursor.objsLeftInBatch());
assert.eq(2, cursorCountMatching(cursor, function(c) {
return c.name === "foo" || c.name === "bar";
}));
// Test a large batch size, and assert that at least 2 results are returned in the initial
// batch.
cursor = getListCollectionsCursor({cursor: {batchSize: Math.pow(2, 62)}});
assert.lte(2, cursor.objsLeftInBatch());
assert.eq(2, cursorCountMatching(cursor, function(c) {
return c.name === "foo" || c.name === "bar";
}));
// Ensure that the server accepts an empty object for "cursor". This is equivalent to not
// specifying "cursor" at all.
//
// We do not test for objsLeftInBatch() here, since the default batch size for this command
// is not specified.
cursor = getListCollectionsCursor({cursor: {}});
assert.eq(2, cursorCountMatching(cursor, function(c) {
return c.name === "foo" || c.name === "bar";
}));
//
// Test for invalid values of "cursor" and "cursor.batchSize".
//
assert.throws(function() {
getListCollectionsCursor({cursor: 0});
});
assert.throws(function() {
getListCollectionsCursor({cursor: 'x'});
});
assert.throws(function() {
getListCollectionsCursor({cursor: []});
});
assert.throws(function() {
getListCollectionsCursor({cursor: {foo: 1}});
});
assert.throws(function() {
getListCollectionsCursor({cursor: {batchSize: -1}});
});
assert.throws(function() {
getListCollectionsCursor({cursor: {batchSize: 'x'}});
});
assert.throws(function() {
getListCollectionsCursor({cursor: {batchSize: {}}});
});
assert.throws(function() {
getListCollectionsCursor({cursor: {batchSize: 2, foo: 1}});
});
//
// Test more than 2 batches of results.
//
assert.commandWorked(mydb.dropDatabase());
assert.commandWorked(mydb.createCollection("foo"));
assert.commandWorked(mydb.createCollection("bar"));
assert.commandWorked(mydb.createCollection("baz"));
assert.commandWorked(mydb.createCollection("quux"));
cursor = getListCollectionsCursor({cursor: {batchSize: 0}}, 2);
assert.eq(0, cursor.objsLeftInBatch());
assert(cursor.hasNext());
assert.eq(2, cursor.objsLeftInBatch());
cursor.next();
assert(cursor.hasNext());
assert.eq(1, cursor.objsLeftInBatch());
cursor.next();
assert(cursor.hasNext());
assert.eq(2, cursor.objsLeftInBatch());
cursor.next();
assert(cursor.hasNext());
assert.eq(1, cursor.objsLeftInBatch());
//
// Test on non-existent database.
//
assert.commandWorked(mydb.dropDatabase());
cursor = getListCollectionsCursor();
assert.eq(0, cursorCountMatching(cursor, function(c) {
return c.name === "foo";
}));
//
// Test on empty database.
//
assert.commandWorked(mydb.dropDatabase());
assert.commandWorked(mydb.createCollection("foo"));
mydb.foo.drop();
cursor = getListCollectionsCursor();
assert.eq(0, cursorCountMatching(cursor, function(c) {
return c.name === "foo";
}));
//
// Test killCursors against a listCollections cursor.
//
assert.commandWorked(mydb.dropDatabase());
assert.commandWorked(mydb.createCollection("foo"));
assert.commandWorked(mydb.createCollection("bar"));
assert.commandWorked(mydb.createCollection("baz"));
assert.commandWorked(mydb.createCollection("quux"));
res = mydb.runCommand("listCollections", {cursor: {batchSize: 0}});
cursor = new DBCommandCursor(mydb.getMongo(), res, 2);
cursor = null;
gc(); // Shell will send a killCursors message when cleaning up underlying cursor.
cursor = new DBCommandCursor(mydb.getMongo(), res, 2);
assert.throws(function() {
cursor.hasNext();
});
}());