Files
mongo/jstests/core/list_collections1.js
Charlie Swanson 6abdb820a8 SERVER-18622 listCollections should special case filtering by name
Note that the listCollections command is no longer guaranteed to return the
collections in alphabetical order by name. The shell helper will still do so.
2015-10-13 17:13:22 -04:00

218 lines
9.8 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));
//
// 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(); });
}());