/** * Tests the validateDBMetaData commands with various input parameters. * @tags: [ * requires_fcv_49 * ] */ (function() { "use strict"; load("jstests/libs/fixture_helpers.js"); // For FixtureHelpers. load("jstests/core/timeseries/libs/timeseries.js"); // For TimeseriesTest. const dbName = jsTestName(); const testDB = db.getSiblingDB(dbName); assert.commandWorked(testDB.dropDatabase()); const coll1 = testDB.coll1; // Drop all the unstable data that the other tests might have created. This will ensure that the // validateDBMetadata command is validating only the data generated by this test. (function dropAllUnstableData() { const listDBRes = assert.commandWorked(db.adminCommand({listDatabases: 1, nameOnly: true})); for (let listDBOutput of listDBRes.databases) { // Skip non-user databases. if (Array.contains(["admin", "config", "local", "$external"], listDBOutput.name)) { continue; } const currentDB = db.getSiblingDB(listDBOutput.name); for (let collInfo of currentDB.getCollectionInfos()) { if (collInfo.type == "collection" && !collInfo.name.startsWith("system")) { assert.commandWorked( currentDB.runCommand({dropIndexes: collInfo.name, index: "*"})); } } } })(); // Verify that the 'apiParameters' field is required. const res = assert.commandFailedWithCode(testDB.runCommand({validateDBMetadata: 1}), 40414); function validate({dbName, coll, apiStrict, error}) { dbName = dbName ? dbName : null; coll = coll ? coll : null; const res = assert.commandWorked(testDB.runCommand({ validateDBMetadata: 1, db: dbName, collection: coll, apiParameters: {version: "1", strict: apiStrict} })); assert(res.apiVersionErrors); const foundError = res.apiVersionErrors.length > 0; // Verify that 'apiVersionErrors' is not empty when 'error' is true, and vice versa. assert((!error && !foundError) || (error && foundError), res); if (error) { for (let apiError of res.apiVersionErrors) { assert(apiError.ns); if (error.code) { assert.eq(apiError.code, error.code); } if (FixtureHelpers.isMongos(testDB)) { // Check that every error has an additional 'shard' field on sharded clusters. assert(apiError.shard); } } } } // // Tests for indexes. // assert.commandWorked(coll1.createIndex({p: "text"})); validate({apiStrict: false}); // All dbs but different collection name. validate({coll: "coll2", apiStrict: true}); // Different db, and collection which has unstable index should not error. validate({dbName: "new", coll: "coll1", apiStrict: true}); validate({ dbName: "new", apiStrict: true, }); // Cases where the command returns an error. validate({apiStrict: true, error: true}); validate({coll: "coll1", apiStrict: true, error: true}); validate({ dbName: testDB.getName(), coll: "coll1", apiStrict: true, error: {code: ErrorCodes.APIStrictError} }); validate({dbName: testDB.getName(), apiStrict: true, error: true}); // // Tests for views. // assert.commandWorked(coll1.dropIndexes()); validate({apiStrict: true}); // Create a view which uses unstable expression and verify that validateDBMetadata commands throws // an assertion. const view = testDB.createView("view1", "coll2", [{$project: {v: {$_testApiVersion: {unstable: true}}}}]); validate({apiStrict: true, error: true}); validate({dbName: dbName, apiStrict: true, error: true}); validate({dbName: "otherDB", apiStrict: true}); validate({dbName: dbName, coll: "coll", apiStrict: true}); // With view name in the input. validate({coll: "view1", apiStrict: true, error: {code: ErrorCodes.APIStrictError}}); validate( {dbName: dbName, coll: "view1", apiStrict: true, error: {code: ErrorCodes.APIStrictError}}); validate({dbName: "new", coll: "view1", apiStrict: true}); // Collection named same as the view name in another db. const testDB2 = db.getSiblingDB("testDB2"); const collWithViewName = testDB2.view1; validate({coll: "view1", apiStrict: true, error: {code: ErrorCodes.APIStrictError}}); // // Tests for validator. // assert.commandWorked(testDB.dropDatabase()); assert.commandWorked(testDB.createCollection( "validatorColl", {validator: {$expr: {$_testApiVersion: {unstable: true}}}})); validate({apiStrict: true, error: true}); // Drop the collection with validation rules. By not using the 'coll.drop()' shell helper, we can // avoid implicit collection creation in certain passthrough suites. This should increase the // coverage of this test on sharded clusters. assert.commandWorked(testDB.runCommand({drop: "validatorColl"})); // // Validates the metadata across all the databases and collections after creating a time-series // collection if time-series collection feature flag is enabled. // (function maybeValidateWithTimeseriesCollection() { if (!TimeseriesTest.timeseriesCollectionsEnabled(db.getMongo())) { jsTestLog("Cannot validate metadata with timeseries collection, feature flag is disabled"); return; } const coll = "timeseriesCollectionMetaDataValidation"; assert.commandWorked( testDB.createCollection(coll, {timeseries: {timeField: "time", metaField: "meta"}})); validate({apiStrict: true}); }()); }());