diff options
Diffstat (limited to 'jstests/core/ddl/collection_uuid_rename_collection.js')
-rw-r--r-- | jstests/core/ddl/collection_uuid_rename_collection.js | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/jstests/core/ddl/collection_uuid_rename_collection.js b/jstests/core/ddl/collection_uuid_rename_collection.js new file mode 100644 index 00000000000..bc294fd7aab --- /dev/null +++ b/jstests/core/ddl/collection_uuid_rename_collection.js @@ -0,0 +1,211 @@ +/** + * Tests the collectionUUID parameter of the renameCollection command. + * + * @tags: [ + * does_not_support_zones, + * requires_fcv_60, + * requires_non_retryable_commands, + * tenant_migration_incompatible, + * ] + */ +(function() { +'use strict'; + +const testDB = db.getSiblingDB(jsTestName()); +assert.commandWorked(testDB.dropDatabase()); + +const coll = testDB.coll; +const coll2 = testDB.coll_2; +const coll3 = testDB.coll_3; + +const resetColls = function() { + coll.drop(); + coll2.drop(); + coll3.drop(); + + assert.commandWorked(coll.insert({_id: 0})); + assert.commandWorked(coll2.insert({_id: 1})); +}; + +const uuid = function(coll) { + return assert.commandWorked(testDB.runCommand({listCollections: 1})) + .cursor.firstBatch.find(c => c.name === coll.getName()) + .info.uuid; +}; + +// The command succeeds when the correct UUID is provided. +resetColls(); +assert.commandWorked(testDB.adminCommand({ + renameCollection: coll.getFullName(), + to: coll3.getFullName(), + dropTarget: true, + collectionUUID: uuid(coll), +})); + +resetColls(); +assert.commandWorked(testDB.adminCommand({ + renameCollection: coll2.getFullName(), + to: coll.getFullName(), + dropTarget: uuid(coll), +})); + +resetColls(); +assert.commandWorked(testDB.adminCommand({ + renameCollection: coll2.getFullName(), + to: coll.getFullName(), + dropTarget: uuid(coll), + collectionUUID: uuid(coll2), +})); + +// The command fails when the provided UUID does not correspond to an existing collection. +resetColls(); +const nonexistentUUID = UUID(); +let res = assert.commandFailedWithCode(testDB.adminCommand({ + renameCollection: coll.getFullName(), + to: coll3.getFullName(), + dropTarget: true, + collectionUUID: nonexistentUUID, +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); +assert.eq(res.collectionUUID, nonexistentUUID); +assert.eq(res.expectedCollection, coll.getName()); +assert.eq(res.actualCollection, null); + +res = assert.commandFailedWithCode(testDB.adminCommand({ + renameCollection: coll2.getFullName(), + to: coll.getFullName(), + dropTarget: nonexistentUUID, +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); +assert.eq(res.collectionUUID, nonexistentUUID); +assert.eq(res.expectedCollection, coll.getName()); +assert.eq(res.actualCollection, null); + +// The command fails when the provided UUID corresponds to a different collection. +res = assert.commandFailedWithCode(testDB.adminCommand({ + renameCollection: coll2.getFullName(), + to: coll3.getFullName(), + dropTarget: true, + collectionUUID: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); + +res = assert.commandFailedWithCode(testDB.adminCommand({ + renameCollection: coll.getFullName(), + to: coll2.getFullName(), + dropTarget: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); + +res = assert.commandFailedWithCode(testDB.adminCommand({ + renameCollection: coll2.getFullName(), + to: coll3.getFullName(), + dropTarget: uuid(coll2), + collectionUUID: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); + +// Only collections in the same database are specified by actualCollection. +const otherDB = testDB.getSiblingDB(testDB.getName() + '_2'); +assert.commandWorked(otherDB.dropDatabase()); +const coll4 = otherDB['coll_4']; +const coll5 = otherDB['coll_5']; +assert.commandWorked(coll4.insert({_id: 2})); +res = assert.commandFailedWithCode(otherDB.adminCommand({ + renameCollection: coll4.getFullName(), + to: coll5.getFullName(), + dropTarget: true, + collectionUUID: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, coll4.getName()); +assert.eq(res.actualCollection, null); + +res = assert.commandFailedWithCode(otherDB.adminCommand({ + renameCollection: coll4.getFullName(), + to: coll5.getFullName(), + dropTarget: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, coll5.getName()); +assert.eq(res.actualCollection, null); + +res = assert.commandFailedWithCode(otherDB.adminCommand({ + renameCollection: coll4.getFullName(), + to: coll5.getFullName(), + dropTarget: uuid(coll2), + collectionUUID: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, coll4.getName()); +assert.eq(res.actualCollection, null); + +// The command fails when the provided UUID corresponds to a different collection, even if the +// provided source namespace does not exist. +assert.commandWorked(testDB.runCommand({drop: coll2.getName()})); +res = assert.commandFailedWithCode(testDB.adminCommand({ + renameCollection: coll2.getFullName(), + to: coll3.getFullName(), + dropTarget: true, + collectionUUID: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); +assert(!testDB.getCollectionNames().includes(coll2.getName())); + +// The command fails with CollectionUUIDMismatch even if the database does not exist. +const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent'); +res = assert.commandFailedWithCode(testDB.adminCommand({ + renameCollection: nonexistentDB.getName() + '.nonexistent', + to: nonexistentDB.getName() + '.nonexistent_2', + dropTarget: true, + collectionUUID: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, nonexistentDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, 'nonexistent'); +assert.eq(res.actualCollection, null); + +// The collectionUUID parameter cannot be provided when renaming a collection between databases. +const otherDBColl = db.getSiblingDB(jsTestName() + '_2').coll; +otherDBColl.drop(); +assert.commandWorked(otherDBColl.insert({_id: 3})); +assert.commandFailedWithCode(testDB.adminCommand({ + renameCollection: coll.getFullName(), + to: otherDBColl.getFullName(), + dropTarget: true, + collectionUUID: uuid(coll), +}), + [ErrorCodes.InvalidOptions, ErrorCodes.CommandFailed]); + +assert.commandFailedWithCode(testDB.adminCommand({ + renameCollection: coll.getFullName(), + to: otherDBColl.getFullName(), + dropTarget: uuid(coll), +}), + [ErrorCodes.InvalidOptions, ErrorCodes.CommandFailed]); +})(); |