mirror of https://github.com/mongodb/mongo
204 lines
7.7 KiB
JavaScript
204 lines
7.7 KiB
JavaScript
/*
|
|
* Test to validate the $_internalAllCollectionStats stage for storageStats.
|
|
*
|
|
* @tags: [
|
|
* requires_fcv_60,
|
|
* ]
|
|
*/
|
|
|
|
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
|
|
|
function checkResults(aggregationPipeline, checksToDo) {
|
|
assert.soon(() => {
|
|
const results = adminDb.aggregate(aggregationPipeline).toArray();
|
|
assert.lte(numCollections, results.length);
|
|
|
|
for (let i = 0; i < numCollections; i++) {
|
|
try {
|
|
const coll = "coll" + i;
|
|
|
|
// To check that the data retrieve from $_internalAllCollectionStats is correct we
|
|
// will call $collStats for each namespace to retrieve its storage stats and compare
|
|
// the two outputs.
|
|
const expectedResults = testDb
|
|
.getCollection(coll)
|
|
.aggregate([{$collStats: {storageStats: {}}}])
|
|
.toArray();
|
|
assert.neq(null, expectedResults);
|
|
assert.eq(1, expectedResults.length);
|
|
|
|
let exists = false;
|
|
for (const data of results) {
|
|
const ns = data.ns;
|
|
if (dbName + "." + coll === ns) {
|
|
checksToDo(data, expectedResults);
|
|
exists = true;
|
|
break;
|
|
}
|
|
}
|
|
assert(exists, "Expected to have $_internalAllCollectionStats results for coll" + i);
|
|
} catch (e) {
|
|
// As we perform two logical executions of $collStats they might return different
|
|
// storageSizes since WT may have rewritten the file during a checkpoint or
|
|
// background compaction. We retry the operation as it is a transient error.
|
|
jsTest.log(e);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
});
|
|
}
|
|
|
|
// Configure initial sharding cluster
|
|
const st = new ShardingTest({shards: 2});
|
|
const mongos = st.s;
|
|
|
|
const dbName = "test";
|
|
const testDb = mongos.getDB(dbName);
|
|
const adminDb = mongos.getDB("admin");
|
|
const numCollections = 4;
|
|
|
|
// Insert sharded collections to validate the aggregation stage
|
|
for (let i = 0; i < numCollections / 2; i++) {
|
|
const coll = "coll" + i;
|
|
assert(st.adminCommand({shardcollection: dbName + "." + coll, key: {skey: 1}}));
|
|
assert.commandWorked(testDb.getCollection(coll).insert({skey: i}));
|
|
}
|
|
|
|
// Insert some unsharded collections to validate the aggregation stage
|
|
for (let i = numCollections / 2; i < numCollections; i++) {
|
|
const coll = "coll" + i;
|
|
assert.commandWorked(testDb.getCollection(coll).insert({skey: i}));
|
|
}
|
|
|
|
// Testing for comparing each collection returned from $_internalAllCollectionStats to $collStats
|
|
(function testInternalAllCollectionStats() {
|
|
const aggregationPipeline = [{$_internalAllCollectionStats: {stats: {storageStats: {}}}}];
|
|
|
|
const checksToDo = (left, right) => {
|
|
const msg = "Expected same output from $_internalAllCollectionStats and $collStats " + "for same namespace";
|
|
assert.eq(left.host, right[0].host, msg);
|
|
assert.eq(left.shard, right[0].shard, msg);
|
|
assert.eq(left.storageStats.size, right[0].storageStats.size, msg);
|
|
assert.eq(left.storageStats.count, right[0].storageStats.count, msg);
|
|
assert.eq(left.storageStats.avgObjSize, right[0].storageStats.avgObjSize, msg);
|
|
assert.eq(left.storageStats.storageSize, right[0].storageStats.storageSize, msg);
|
|
assert.eq(left.storageStats.freeStorageSize, right[0].storageStats.freeStorageSize, msg);
|
|
assert.eq(left.storageStats.nindexes, right[0].storageStats.nindexes, msg);
|
|
assert.eq(left.storageStats.totalIndexSize, right[0].storageStats.totalIndexSize, msg);
|
|
assert.eq(left.storageStats.totalSize, right[0].storageStats.totalSize, msg);
|
|
};
|
|
checkResults(aggregationPipeline, checksToDo);
|
|
})();
|
|
|
|
// Tests to check the correct behaviour of a $project stage after $_internalAllCollectionStats
|
|
(function testNumOrphanDocsFieldProject() {
|
|
const aggregationPipeline = [
|
|
{$_internalAllCollectionStats: {stats: {storageStats: {}}}},
|
|
{$project: {"ns": 1, "storageStats.numOrphanDocs": 1}},
|
|
];
|
|
|
|
const checksToDo = (left, right) => {
|
|
assert.eq(
|
|
left.storageStats.numOrphanDocs,
|
|
right[0].storageStats.numOrphanDocs,
|
|
"Expected same output after a projection with storageStats.numOrphanDocs field",
|
|
);
|
|
};
|
|
checkResults(aggregationPipeline, checksToDo);
|
|
})();
|
|
|
|
(function testStorageSizeFieldProject() {
|
|
const aggregationPipeline = [
|
|
{$_internalAllCollectionStats: {stats: {storageStats: {}}}},
|
|
{$project: {"ns": 1, "storageStats.storageSize": 1}},
|
|
];
|
|
|
|
const checksToDo = (left, right) => {
|
|
assert.eq(
|
|
left.storageStats.storageSize,
|
|
right[0].storageStats.storageSize,
|
|
"Expected same output after a projection with storageStats.storageSize field",
|
|
);
|
|
};
|
|
checkResults(aggregationPipeline, checksToDo);
|
|
})();
|
|
|
|
(function testNIndexesFieldProject() {
|
|
const aggregationPipeline = [
|
|
{$_internalAllCollectionStats: {stats: {storageStats: {}}}},
|
|
{$project: {"ns": 1, "storageStats.nindexes": 1}},
|
|
];
|
|
|
|
const checksToDo = (left, right) => {
|
|
assert.eq(
|
|
left.storageStats.nindexes,
|
|
right[0].storageStats.nindexes,
|
|
"Expected same output after a projection with storageStats.nindexes field",
|
|
);
|
|
};
|
|
checkResults(aggregationPipeline, checksToDo);
|
|
})();
|
|
|
|
(function testTotalSizeFieldProject() {
|
|
const aggregationPipeline = [
|
|
{$_internalAllCollectionStats: {stats: {storageStats: {}}}},
|
|
{$project: {"ns": 1, "storageStats.totalSize": 1}},
|
|
];
|
|
|
|
const checksToDo = (left, right) => {
|
|
assert.eq(
|
|
left.storageStats.totalSize,
|
|
right[0].storageStats.totalSize,
|
|
"Expected same output after a projection with storageStats.totalSize field",
|
|
);
|
|
};
|
|
checkResults(aggregationPipeline, checksToDo);
|
|
})();
|
|
|
|
(function testProjectingDifferentFields() {
|
|
const aggregationPipeline = [
|
|
{$_internalAllCollectionStats: {stats: {storageStats: {}}}},
|
|
{
|
|
$project: {
|
|
"ns": 1,
|
|
"storageStats.numOrphanDocs": 1,
|
|
"storageStats.storageSize": 1,
|
|
"storageStats.nindexes": 1,
|
|
"storageStats.totalSize": 1,
|
|
},
|
|
},
|
|
];
|
|
|
|
const checksToDo = (left, right) => {
|
|
const msg = "Expected same output after a projection with fields from different storage " + "stats groups";
|
|
assert.eq(left.storageStats.numOrphanDocs, right[0].storageStats.numOrphanDocs, msg);
|
|
assert.eq(left.storageStats.storageSize, right[0].storageStats.storageSize, msg);
|
|
assert.eq(left.storageStats.nindexes, right[0].storageStats.nindexes, msg);
|
|
assert.eq(left.storageStats.totalSize, right[0].storageStats.totalSize, msg);
|
|
};
|
|
checkResults(aggregationPipeline, checksToDo);
|
|
})();
|
|
|
|
// Test valid query with empty specification
|
|
assert.commandWorked(adminDb.runCommand({aggregate: 1, pipeline: [{$_internalAllCollectionStats: {}}], cursor: {}}));
|
|
|
|
// Test invalid queries/values.
|
|
assert.commandFailedWithCode(
|
|
adminDb.runCommand({aggregate: 1, pipeline: [{$_internalAllCollectionStats: 3}], cursor: {}}),
|
|
6789103,
|
|
);
|
|
|
|
const response = assert.commandFailedWithCode(
|
|
testDb.runCommand({
|
|
aggregate: "foo",
|
|
pipeline: [{$_internalAllCollectionStats: {stats: {storageStats: {}}}}],
|
|
cursor: {},
|
|
}),
|
|
6789104,
|
|
);
|
|
assert.neq(-1, response.errmsg.indexOf("$_internalAllCollectionStats"), response.errmsg);
|
|
assert.neq(-1, response.errmsg.indexOf("admin database"), response.errmsg);
|
|
|
|
st.stop();
|