summaryrefslogtreecommitdiff
path: root/jstests/libs/clustered_collections
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/libs/clustered_collections')
-rw-r--r--jstests/libs/clustered_collections/clustered_capped_utils.js12
-rw-r--r--jstests/libs/clustered_collections/clustered_collection_bounded_scan_common.js159
-rw-r--r--jstests/libs/clustered_collections/clustered_collection_util.js10
3 files changed, 40 insertions, 141 deletions
diff --git a/jstests/libs/clustered_collections/clustered_capped_utils.js b/jstests/libs/clustered_collections/clustered_capped_utils.js
index e9c136f57fd..8e6ae836223 100644
--- a/jstests/libs/clustered_collections/clustered_capped_utils.js
+++ b/jstests/libs/clustered_collections/clustered_capped_utils.js
@@ -1,5 +1,3 @@
-load("jstests/libs/ttl_util.js");
-
var ClusteredCappedUtils = class {
// Validate TTL-based deletion on a clustered, capped collection.
static testClusteredCappedCollectionWithTTL(db, collName, clusterKeyField) {
@@ -41,8 +39,7 @@ var ClusteredCappedUtils = class {
}
assert.commandWorked(coll.insertMany(docs, {ordered: true}));
- // This test runs with default read concern 'local'.
- TTLUtil.waitForPass(db, /*waitForMajorityCommit=*/false);
+ ClusteredCollectionUtil.waitForTTL(db);
// Only the recent documents survived.
assert.eq(coll.find().itcount(), batchSize);
@@ -143,7 +140,7 @@ var ClusteredCappedUtils = class {
// TTL delete the two old documents.
assert.commandWorked(db.adminCommand({setParameter: 1, ttlMonitorEnabled: true}));
- TTLUtil.waitForPass(db, /*waitForMajorityCommit=*/isReplicated);
+ ClusteredCollectionUtil.waitForTTL(db);
assert.eq(2, db.getCollection(collName).find().itcount());
// Confirm that the tailable getMore can resume from where it was, since the document the
@@ -212,7 +209,7 @@ var ClusteredCappedUtils = class {
// TTL delete the two old documents, while the tailable cursor is still on the first one.
assert.commandWorked(db.adminCommand({setParameter: 1, ttlMonitorEnabled: true}));
- TTLUtil.waitForPass(db, /*waitForMajorityCommit=*/isReplicated);
+ ClusteredCollectionUtil.waitForTTL(db);
assert.eq(1, db.getCollection(collName).find().itcount());
// Confirm that the tailable cursor returns CappedPositionLost, as the document it was
@@ -295,8 +292,7 @@ var ClusteredCappedUtils = class {
// Expire the document.
assert.commandWorked(db.adminCommand({setParameter: 1, ttlMonitorEnabled: true}));
- // No need to wait for majority commit, as default 'local' read concern is used.
- TTLUtil.waitForPass(db, /*waitForMajorityCommit=*/false);
+ ClusteredCollectionUtil.waitForTTL(db);
assert.eq(0, db.getCollection(collName).find().itcount());
// The TTL deletion has been replicated to the oplog.
diff --git a/jstests/libs/clustered_collections/clustered_collection_bounded_scan_common.js b/jstests/libs/clustered_collections/clustered_collection_bounded_scan_common.js
index ff52e8f7a22..b81717c7552 100644
--- a/jstests/libs/clustered_collections/clustered_collection_bounded_scan_common.js
+++ b/jstests/libs/clustered_collections/clustered_collection_bounded_scan_common.js
@@ -20,44 +20,10 @@ const testClusteredCollectionBoundedScan = function(coll, clusterKey) {
for (let i = 0; i < batchSize; i++) {
bulk.insert({[clusterKeyFieldName]: i, a: -i});
}
-
assert.commandWorked(bulk.execute());
assert.eq(coll.find().itcount(), batchSize);
-
- // Now add additional documents with IDs of a different type.
- // Normal exprs should be type bracketed, and should never
- // see these documents.
- // Internal ops are not type bracketed, and will see these
- // documents.
- const extra = coll.initializeUnorderedBulkOp();
- // `null` should sort before ints.
- extra.insert({[clusterKeyFieldName]: null, a: null});
- // And strings should sort after.
- extra.insert({[clusterKeyFieldName]: "foo", a: "foo"});
- assert.commandWorked(extra.execute());
}
-
- // Checks that the number of docs examined matches the expected number. There are separate
- // expected args for Classic vs SBE because in Classic there is an extra cursor->next() call
- // beyond the end of the range if EOF has not been hit, but in SBE there is not. This function
- // also handles that this stat is in different places for the two engines:
- // Classic: executionStats.executionStages.docsExamined
- // SBE: executionStats.totalDocsExamined
- function assertDocsExamined(executionStats, expectedClassic, expectedSbe) {
- let sbe = false;
- let docsExamined = executionStats.executionStages.docsExamined;
- if (docsExamined == undefined) {
- sbe = true;
- docsExamined = executionStats.totalDocsExamined;
- }
- if (sbe) {
- assert.eq(expectedSbe, docsExamined);
- } else {
- assert.eq(expectedClassic, docsExamined);
- }
- }
-
- function testEq(op = "$eq") {
+ function testEq() {
initAndPopulate(coll, clusterKey);
const expl = assert.commandWorked(coll.getDB().runCommand({
@@ -74,12 +40,7 @@ const testClusteredCollectionBoundedScan = function(coll, clusterKey) {
// the range.
assert.eq(2, expl.executionStats.executionStages.docsExamined);
}
-
- function testLT(op,
- val,
- expectedNReturned,
- expectedDocsExaminedClassic,
- expectedDocsExaminedSbe = expectedDocsExaminedClassic - 1) {
+ function testLT(op, val, expectedNReturned, expectedDocsExamined) {
initAndPopulate(coll, clusterKey);
const expl = assert.commandWorked(coll.getDB().runCommand({
@@ -89,21 +50,12 @@ const testClusteredCollectionBoundedScan = function(coll, clusterKey) {
assert(getPlanStage(expl, "CLUSTERED_IXSCAN"));
assert(getPlanStage(expl, "CLUSTERED_IXSCAN").hasOwnProperty("maxRecord"));
- assert.eq(val, getPlanStage(expl, "CLUSTERED_IXSCAN").maxRecord);
-
- if (!op.startsWith("$_internal")) {
- // Internal ops do not do type bracketing, so min record would not
- // be expected for $_internalExprLt.
- assert(getPlanStage(expl, "CLUSTERED_IXSCAN").hasOwnProperty("minRecord"));
- assert.eq(NaN, getPlanStage(expl, "CLUSTERED_IXSCAN").minRecord);
- }
+ assert(getPlanStage(expl, "CLUSTERED_IXSCAN").hasOwnProperty("minRecord"));
+ assert.eq(10, getPlanStage(expl, "CLUSTERED_IXSCAN").maxRecord);
+ assert.eq(NaN, getPlanStage(expl, "CLUSTERED_IXSCAN").minRecord);
assert.eq(expectedNReturned, expl.executionStats.executionStages.nReturned);
-
- // In this case the scans do not hit EOF, so there is an extra cursor->next() call past the
- // end of the range in Classic, making SBE expect one fewer doc examined than Classic.
- assertDocsExamined(
- expl.executionStats, expectedDocsExaminedClassic, expectedDocsExaminedSbe);
+ assert.eq(expectedDocsExamined, expl.executionStats.executionStages.docsExamined);
}
function testGT(op, val, expectedNReturned, expectedDocsExamined) {
initAndPopulate(coll, clusterKey);
@@ -114,14 +66,10 @@ const testClusteredCollectionBoundedScan = function(coll, clusterKey) {
}));
assert(getPlanStage(expl, "CLUSTERED_IXSCAN"));
- if (!op.startsWith("$_internal")) {
- // Internal ops do not do type bracketing, so no max record would not
- // be expected for $_internalExprGt.
- assert(getPlanStage(expl, "CLUSTERED_IXSCAN").hasOwnProperty("maxRecord"));
- assert.eq(Infinity, getPlanStage(expl, "CLUSTERED_IXSCAN").maxRecord);
- }
+ assert(getPlanStage(expl, "CLUSTERED_IXSCAN").hasOwnProperty("maxRecord"));
assert(getPlanStage(expl, "CLUSTERED_IXSCAN").hasOwnProperty("minRecord"));
- assert.eq(val, getPlanStage(expl, "CLUSTERED_IXSCAN").minRecord);
+ assert.eq(Infinity, getPlanStage(expl, "CLUSTERED_IXSCAN").maxRecord);
+ assert.eq(89, getPlanStage(expl, "CLUSTERED_IXSCAN").minRecord);
assert.eq(expectedNReturned, expl.executionStats.executionStages.nReturned);
assert.eq(expectedDocsExamined, expl.executionStats.executionStages.docsExamined);
@@ -146,23 +94,6 @@ const testClusteredCollectionBoundedScan = function(coll, clusterKey) {
assert.eq(expectedNReturned, expl.executionStats.executionStages.nReturned);
assert.eq(expectedDocsExamined, expl.executionStats.executionStages.docsExamined);
}
- function testIn() {
- initAndPopulate(coll, clusterKey);
-
- const expl = assert.commandWorked(coll.getDB().runCommand({
- explain: {find: coll.getName(), filter: {[clusterKeyFieldName]: {$in: [10, 20, 30]}}},
- verbosity: "executionStats"
- }));
-
- assert(getPlanStage(expl, "CLUSTERED_IXSCAN"));
- assert.eq(10, getPlanStage(expl, "CLUSTERED_IXSCAN").minRecord);
- assert.eq(30, getPlanStage(expl, "CLUSTERED_IXSCAN").maxRecord);
-
- assert.eq(3, expl.executionStats.executionStages.nReturned);
- // The range scanned is 21 documents + 1 extra document by design - additional cursor
- // 'next' beyond the range.
- assert.eq(22, expl.executionStats.executionStages.docsExamined);
- }
function testNonClusterKeyScan() {
initAndPopulate(coll, clusterKey);
@@ -177,65 +108,27 @@ const testClusteredCollectionBoundedScan = function(coll, clusterKey) {
assert.eq(10, expl.executionStats.executionStages.nReturned);
}
- function testInternalExprBoundedScans(coll, clusterKey) {
- testEq("$_internalExprEq");
-
- // The IDs expected to be in the collection are:
- // null, 0-99, "foo"
- // Internal operations should not perform type bracketing, so should expect
- // to see the null and "foo" docs; the _non_ internal equivalents _do_
- // perform type bracketing, so should behave as if null and "foo" do not
- // exist.
- testLT("$_internalExprLt", 10, 11, 12);
- testLT("$_internalExprLte", 10, 12, 13);
- testGT("$_internalExprGt", 89, 11, 12, 11);
- testGT("$_internalExprGte", 89, 12, 12);
- testRange("$_internalExprGt", 20, "$_internalExprLt", 40, 19, 21, 19);
- testRange("$_internalExprGte", 20, "$_internalExprLt", 40, 20, 21, 20);
- testRange("$_internalExprGt", 20, "$_internalExprLte", 40, 20, 22, 20);
- testRange("$_internalExprGte", 20, "$_internalExprLte", 40, 21, 22, 21);
- }
-
function testBoundedScans(coll, clusterKey) {
testEq();
-
- // Expected set of IDs:
- // null, 0-99, "foo"
-
- // The last argument of the following calls, 'expectedDocsExaminedClassic', and the specific
- // comments, are for Classic engine. SBE does not have the additional cursor->next() call
- // beyond the range, so in calls to testLT() and testRange() its value will be one lower.
- // This is accounted for by delegations to the assertDocsExamined() helper function.
-
- // As of SERVER-75604, clustered collection scans can be inclusive or exclusive at either
- // end; the filter does not need to examine a record at the lower bound to then discard it.
- // Expect docsExamined == nReturned + 1 + 1 due to (not returned, due to type bracketing)
- // null id, and the by-design additional cursor 'next' beyond the range.
- testLT("$lt", 10, 10, 12, 10);
- // Expect docsExamined == nReturned + 1 + 1 due to (not returned, due to type bracketing)
- // null id, and the by-design additional cursor 'next' beyond the range.
- testLT("$lte", 10, 11, 13, 11);
- // Expect docsExamined == nReturned + 1 + 1 due to (not returned, due to type bracketing)
- // "foo" id. Note that unlike the 'testLT' cases, there's no additional cursor 'next' beyond
- // the range because we hit EOF. However, Classic needs to examine and discard the value
- // equal to bound, as this is an exclusive bound.
- testGT("$gt", 89, 10, 12, 10);
- // Expect docsExamined == nReturned + 1 due to (not returned, due to type bracketing)
- // "foo" id.
- testGT("$gte", 89, 11, 12, 11);
- // docsExamined reflects the fact that by design we do an additional cursor 'next' beyond
+ // Expect docsExamined == nReturned + 2 due to the collection scan bounds being always
+ // inclusive and due to the by-design additional cursor 'next' beyond the range.
+ testLT("$lt", 10, 10, 12);
+ // Expect docsExamined == nReturned + 1 due to the by-design additional cursor 'next' beyond
// the range.
- // In addition, Classic needs to examine and discard the value equal to bound,
- // while SBE's scan starts after the bound.
- testRange("$gt", 20, "$lt", 40, 19, 21, 19);
- testRange("$gte", 20, "$lt", 40, 20, 21, 20);
- // Again, Classic and SBE differ by 2 for the above reasons.
- testRange("$gt", 20, "$lte", 40, 20, 22, 20);
- testRange("$gte", 20, "$lte", 40, 21, 22, 21);
- testIn();
-
+ testLT("$lte", 10, 11, 12);
+ // Expect docsExamined == nReturned + 1 due to the collection scan bounds being always
+ // inclusive. Note that unlike the 'testLT' cases, there's no additional cursor 'next'
+ // beyond the range because we hit EOF.
+ testGT("$gt", 89, 10, 11);
+ // Expect docsExamined == nReturned.
+ testGT("$gte", 89, 11, 11);
+ // docsExamined reflects the fact that collection scan bounds are always exclusive and
+ // that by design we do an additional cursor 'next' beyond the range.
+ testRange("$gt", 20, "$lt", 40, 19, 22);
+ testRange("$gte", 20, "$lt", 40, 20, 22);
+ testRange("$gt", 20, "$lte", 40, 20, 22);
+ testRange("$gte", 20, "$lte", 40, 21, 22);
testNonClusterKeyScan();
- testInternalExprBoundedScans(coll, clusterKey);
}
return testBoundedScans(coll, clusterKey);
diff --git a/jstests/libs/clustered_collections/clustered_collection_util.js b/jstests/libs/clustered_collections/clustered_collection_util.js
index c63b5ce56e9..ad6c0111c8a 100644
--- a/jstests/libs/clustered_collections/clustered_collection_util.js
+++ b/jstests/libs/clustered_collections/clustered_collection_util.js
@@ -196,4 +196,14 @@ var ClusteredCollectionUtil = class {
assert.eq(1, coll.find({[clusterKey]: NumberLong("42")}).itcount());
coll.drop();
}
+
+ static waitForTTL(db) {
+ // The 'ttl.passes' metric is incremented when the TTL monitor starts processing the
+ // indexes, so we wait for it to be incremented twice to know that the TTL monitor finished
+ // processing the indexes at least once.
+ const ttlPasses = db.serverStatus().metrics.ttl.passes;
+ assert.soon(function() {
+ return db.serverStatus().metrics.ttl.passes > ttlPasses + 1;
+ });
+ }
};