summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2017-08-29 11:29:24 -0400
committerBenety Goh <benety@mongodb.com>2017-09-05 20:21:26 -0400
commit27b73dd0616a7e6c4956989f753b3ade4291cdd6 (patch)
treedc403b73d8e9ed12efddb9c5c8a4a97f261efd93
parent5b0bf41d2305f684386332ee96d6a96a77f70e7f (diff)
downloadmongo-27b73dd0616a7e6c4956989f753b3ade4291cdd6.tar.gz
SERVER-30371 added js tests for renaming a collection across databases
-rw-r--r--jstests/multiVersion/rename_across_dbs_last_stable_primary.js13
-rw-r--r--jstests/multiVersion/rename_across_dbs_last_stable_primary_drop_target.js14
-rw-r--r--jstests/multiVersion/rename_across_dbs_last_stable_secondary.js13
-rw-r--r--jstests/multiVersion/rename_across_dbs_last_stable_secondary_drop_target.js14
-rw-r--r--jstests/replsets/libs/rename_across_dbs.js163
-rw-r--r--jstests/replsets/rename_across_dbs.js7
-rw-r--r--jstests/replsets/rename_across_dbs_drop_target.js8
7 files changed, 232 insertions, 0 deletions
diff --git a/jstests/multiVersion/rename_across_dbs_last_stable_primary.js b/jstests/multiVersion/rename_across_dbs_last_stable_primary.js
new file mode 100644
index 00000000000..cc2bbeaf137
--- /dev/null
+++ b/jstests/multiVersion/rename_across_dbs_last_stable_primary.js
@@ -0,0 +1,13 @@
+(function() {
+ 'use strict';
+
+ load("jstests/replsets/libs/rename_across_dbs.js");
+
+ const nodes = [{binVersion: 'last-stable'}, {binVersion: 'latest'}, {}];
+ const options = {
+ nodes: nodes,
+ setFeatureCompatibilityVersion: '3.4',
+ };
+
+ new RenameAcrossDatabasesTest(options).run();
+}());
diff --git a/jstests/multiVersion/rename_across_dbs_last_stable_primary_drop_target.js b/jstests/multiVersion/rename_across_dbs_last_stable_primary_drop_target.js
new file mode 100644
index 00000000000..7922e4d074f
--- /dev/null
+++ b/jstests/multiVersion/rename_across_dbs_last_stable_primary_drop_target.js
@@ -0,0 +1,14 @@
+(function() {
+ 'use strict';
+
+ load("jstests/replsets/libs/rename_across_dbs.js");
+
+ const nodes = [{binVersion: 'last-stable'}, {binVersion: 'latest'}, {}];
+ const options = {
+ nodes: nodes,
+ setFeatureCompatibilityVersion: '3.4',
+ dropTarget: true,
+ };
+
+ new RenameAcrossDatabasesTest(options).run();
+}());
diff --git a/jstests/multiVersion/rename_across_dbs_last_stable_secondary.js b/jstests/multiVersion/rename_across_dbs_last_stable_secondary.js
new file mode 100644
index 00000000000..4d26a24ade1
--- /dev/null
+++ b/jstests/multiVersion/rename_across_dbs_last_stable_secondary.js
@@ -0,0 +1,13 @@
+(function() {
+ 'use strict';
+
+ load("jstests/replsets/libs/rename_across_dbs.js");
+
+ const nodes = [{binVersion: 'latest'}, {binVersion: 'last-stable'}, {}];
+ const options = {
+ nodes: nodes,
+ setFeatureCompatibilityVersion: '3.4',
+ };
+
+ new RenameAcrossDatabasesTest(options).run();
+}());
diff --git a/jstests/multiVersion/rename_across_dbs_last_stable_secondary_drop_target.js b/jstests/multiVersion/rename_across_dbs_last_stable_secondary_drop_target.js
new file mode 100644
index 00000000000..b848f991ceb
--- /dev/null
+++ b/jstests/multiVersion/rename_across_dbs_last_stable_secondary_drop_target.js
@@ -0,0 +1,14 @@
+(function() {
+ 'use strict';
+
+ load("jstests/replsets/libs/rename_across_dbs.js");
+
+ const nodes = [{binVersion: 'latest'}, {binVersion: 'last-stable'}, {}];
+ const options = {
+ nodes: nodes,
+ setFeatureCompatibilityVersion: '3.4',
+ dropTarget: true,
+ };
+
+ new RenameAcrossDatabasesTest(options).run();
+}());
diff --git a/jstests/replsets/libs/rename_across_dbs.js b/jstests/replsets/libs/rename_across_dbs.js
new file mode 100644
index 00000000000..9b0298740a0
--- /dev/null
+++ b/jstests/replsets/libs/rename_across_dbs.js
@@ -0,0 +1,163 @@
+/**
+ * Sets up a test for renaming a collection across different databases in a replica set.
+ * 'options' format:
+ * {
+ * nodes: <list of binary versions for nodes in replica set. optional>,
+ * setFeatureCompatibilityVersion: <FCV. optional>,
+ * dropTarget: <if true, creates target collection that will be dropped. Default: false>,
+ * }
+ */
+var RenameAcrossDatabasesTest = function(options) {
+ 'use strict';
+
+ if (!(this instanceof RenameAcrossDatabasesTest)) {
+ return new RenameAcrossDatabasesTest(options);
+ }
+
+ // Capture the 'this' reference
+ var self = this;
+
+ self.options = options || {};
+
+ /**
+ * Log a message for 'RenameAcrossDatabasesTest'.
+ */
+ function _testLog(msg) {
+ jsTestLog('[RenameAcrossDatabasesTest] ' + msg);
+ }
+
+ /**
+ * Runs the test.
+ */
+ this.run = function() {
+ const options = this.options;
+
+ load('jstests/replsets/rslib.js');
+
+ let nodes = [{}, {}, {}];
+ if (options.nodes) {
+ assert.eq(nodes.length, options.nodes.length);
+ for (let i = 0; i < options.nodes.length; ++i) {
+ nodes[i] = Object.merge(nodes[i], options.nodes[i]);
+ }
+ }
+ _testLog('replica set node options: ' + tojson(nodes));
+
+ const replTest = new ReplSetTest({nodes: [nodes[0]], oplogSize: 1000});
+ const testName = replTest.name;
+ replTest.startSet();
+ replTest.initiate();
+
+ // If provided in 'options', we set the featureCompatibilityVersion. We do this prior to
+ // adding any other members to the replica set.
+ if (options.setFeatureCompatibilityVersion) {
+ assert.commandWorked(replTest.getPrimary().adminCommand(
+ {setFeatureCompatibilityVersion: options.setFeatureCompatibilityVersion}));
+ }
+
+ for (let i = 1; i < nodes.length; ++i) {
+ replTest.add(nodes[i]);
+ }
+
+ const conns = replTest.nodes;
+ const hosts = replTest.nodeList();
+ const currentConfig = replTest.getReplSetConfigFromNode();
+ const nextVersion = currentConfig.version + 1;
+ const replSetConfig = {
+ _id: currentConfig._id,
+ members: [
+ {
+ _id: 0,
+ host: hosts[0],
+ },
+ {
+ _id: 1,
+ host: hosts[1],
+ priority: 0,
+ },
+ {
+ _id: 2,
+ host: hosts[2],
+ arbiterOnly: true,
+ },
+ ],
+ version: nextVersion,
+ };
+
+ reconfig(replTest, replSetConfig);
+
+ replTest.waitForState(replTest.nodes[0], ReplSetTest.State.PRIMARY);
+ replTest.awaitReplication();
+
+ const primary = replTest.getPrimary();
+ _testLog('Feature compatibility version: ' +
+ assert
+ .commandWorked(
+ primary.adminCommand({getParameter: 1, featureCompatibilityVersion: 1}))
+ .featureCompatibilityVersion);
+
+ // Rename a collection across databases that also drops the existing target collection.
+ const sourceColl = primary.getCollection('sourceDb.from');
+ const targetColl = primary.getCollection('targetDb.to');
+
+ // Create target collection that will be dropped during the rename operation if
+ // options.dropTarget is true.
+ const dropTarget = options.dropTarget || false;
+ if (dropTarget) {
+ assert.writeOK(targetColl.insert({_id: 1000, target: 1}));
+ assert.commandWorked(targetColl.createIndex({target: 1}));
+ }
+
+ // Populate the source collections and create indexes. Do the same for the target collection
+ // if we are testing dropTarget.
+ // Indexes are explicitly recreated during cross-database renames. We verify this by
+ // checking the number of indexes in the target collection after the rename.
+ const numDocs = 10;
+ _testLog('Inserting ' + numDocs + ' documents into source collection.');
+ for (let i = 0; i < numDocs; ++i) {
+ assert.writeOK(sourceColl.insert({_id: i, source: 1}));
+ }
+ const numNonIdIndexes = 3;
+ _testLog('Creating ' + numNonIdIndexes + ' indexes.');
+ for (let i = 0; i < numNonIdIndexes; ++i) {
+ let keys = {};
+ keys['x' + i] = 1;
+ assert.commandWorked(sourceColl.createIndex(Object.merge(keys, {'source': 1})));
+ }
+ replTest.awaitReplication();
+
+ _testLog('Collections and indexes created. About to rename source collection ' +
+ sourceColl.getFullName() + ' to ' + targetColl.getFullName() +
+ ' with dropTarget set to ' + dropTarget);
+ var results = assert.commandWorked(primary.adminCommand({
+ renameCollection: sourceColl.getFullName(),
+ to: targetColl.getFullName(),
+ dropTarget: dropTarget,
+ }));
+
+ assert.eq(0,
+ sourceColl.getDB()
+ .getCollectionInfos()
+ .filter(coll => coll.name === sourceColl.getFullName())
+ .length);
+ assert.eq(numDocs, targetColl.find().itcount());
+ assert.eq(numNonIdIndexes + 1, targetColl.getIndexes().length);
+ _testLog('Rename across databases successful.');
+
+ // Dump oplog entries. Do this before validating the server data because the verification
+ // logic inserts additional oplog entries into the oplog collection.
+ const numOplogEntriesToDump = 100;
+ _testLog('Dumping last ' + numOplogEntriesToDump + ' oplog entries.');
+ replTest.dumpOplog(primary, {op: {$ne: 'n'}}, numOplogEntriesToDump);
+
+ // Make sure oplogs & dbHashes match
+ _testLog('Checking oplogs and dbhashes after renaming collection.');
+ replTest.awaitReplication();
+ replTest.checkOplogs(testName);
+ replTest.checkReplicatedDataHashes(testName);
+
+ _testLog('Test completed. Stopping replica set.');
+ replTest.stopSet();
+ };
+
+};
diff --git a/jstests/replsets/rename_across_dbs.js b/jstests/replsets/rename_across_dbs.js
new file mode 100644
index 00000000000..7976eb65103
--- /dev/null
+++ b/jstests/replsets/rename_across_dbs.js
@@ -0,0 +1,7 @@
+(function() {
+ 'use strict';
+
+ load("jstests/replsets/libs/rename_across_dbs.js");
+
+ new RenameAcrossDatabasesTest().run();
+}());
diff --git a/jstests/replsets/rename_across_dbs_drop_target.js b/jstests/replsets/rename_across_dbs_drop_target.js
new file mode 100644
index 00000000000..8639f9caeff
--- /dev/null
+++ b/jstests/replsets/rename_across_dbs_drop_target.js
@@ -0,0 +1,8 @@
+(function() {
+ 'use strict';
+
+ load("jstests/replsets/libs/rename_across_dbs.js");
+
+ const options = {dropTarget: true};
+ new RenameAcrossDatabasesTest(options).run();
+}());