summaryrefslogtreecommitdiff
path: root/jstests/replsets/libs/tags.js
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2017-05-15 11:39:27 -0400
committerBenety Goh <benety@mongodb.com>2017-05-16 15:15:33 -0400
commitbcf3d946e680c2c5d8ba737bfb677af7bbc3eb3f (patch)
tree12deef101f999ce92b7802967d49624f87ff55eb /jstests/replsets/libs/tags.js
parent6ad4b7d44832a716a3319e8bfc2aa220b53cb07d (diff)
downloadmongo-bcf3d946e680c2c5d8ba737bfb677af7bbc3eb3f.tar.gz
SERVER-28100 moved common test code for all 3 tags.js tests into a test library under replsets/libs/
Diffstat (limited to 'jstests/replsets/libs/tags.js')
-rw-r--r--jstests/replsets/libs/tags.js282
1 files changed, 282 insertions, 0 deletions
diff --git a/jstests/replsets/libs/tags.js b/jstests/replsets/libs/tags.js
new file mode 100644
index 00000000000..e27e26fc18e
--- /dev/null
+++ b/jstests/replsets/libs/tags.js
@@ -0,0 +1,282 @@
+/**
+ * Sets up a test for replica set tags sets.
+ *
+ * https://docs.mongodb.com/v3.0/tutorial/configure-replica-set-tag-sets/
+ */
+var TagsTest = function(options) {
+ 'use strict';
+
+ if (!(this instanceof TagsTest)) {
+ return new TagsTest(options);
+ }
+
+ // Capture the 'this' reference
+ var self = this;
+
+ self.options = options;
+
+ /**
+ * Runs the test.
+ */
+ this.run = function() {
+ var options = this.options;
+
+ load('jstests/replsets/rslib.js');
+
+ let nodes = options.nodes;
+ var host = getHostName();
+ var name = 'tags';
+
+ var replTest = new ReplSetTest({name: name, nodes: {n0: nodes[0]}, useBridge: true});
+ 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. This effectively allows us to emulate
+ // upgrading some of our nodes to the latest version while performing write operations under
+ // different network partition scenarios.
+ 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;
+ nodes = replTest.nodeList();
+ var port = replTest.ports;
+ var nextVersion = replTest.getReplSetConfigFromNode().version + 1;
+ const replSetConfig = {
+ _id: name,
+ members: [
+ {
+ _id: 0,
+ host: nodes[0],
+ tags: {
+ server: '0',
+ dc: 'ny',
+ ny: '1',
+ rack: 'ny.rk1',
+ },
+ },
+ {
+ _id: 1,
+ host: nodes[1],
+ priority: 2,
+ tags: {
+ server: '1',
+ dc: 'ny',
+ ny: '2',
+ rack: 'ny.rk1',
+ },
+ },
+ {
+ _id: 2,
+ host: nodes[2],
+ priority: 3,
+ tags: {
+ server: '2',
+ dc: 'ny',
+ ny: '3',
+ rack: 'ny.rk2', 2: 'this',
+ },
+ },
+ {
+ _id: 3,
+ host: nodes[3],
+ tags: {
+ server: '3',
+ dc: 'sf',
+ sf: '1',
+ rack: 'sf.rk1',
+ },
+ },
+ {
+ _id: 4,
+ host: nodes[4],
+ tags: {
+ server: '4',
+ dc: 'sf',
+ sf: '2',
+ rack: 'sf.rk2',
+ },
+ },
+ ],
+ settings: {
+ getLastErrorModes: {
+ '2 dc and 3 server': {
+ dc: 2,
+ server: 3,
+ },
+ '1 and 2': {
+ 2: 1,
+ server: 1,
+ },
+ '2': {
+ 2: 1,
+ },
+ '3 and 4': {
+ sf: 2,
+ },
+ '3 or 4': {
+ sf: 1,
+ },
+ },
+ },
+ version: nextVersion,
+ };
+
+ reconfig(replTest, replSetConfig);
+
+ replTest.waitForState(replTest.nodes[2], ReplSetTest.State.PRIMARY);
+ replTest.awaitReplication();
+
+ // Create collection to guard against timeouts due to file allocation.
+ assert.commandWorked(replTest.getPrimary().getDB('foo').createCollection('bar'));
+ replTest.awaitReplication();
+
+ var ensurePrimary = function(nodeId, expectedWritableNodes) {
+ jsTestLog('Node ' + nodeId + ' (' + replTest.nodes[nodeId].host +
+ ') should be primary.');
+ replTest.waitForState(replTest.nodes[nodeId], ReplSetTest.State.PRIMARY, 60 * 1000);
+ primary = replTest.getPrimary();
+ if (options.forceWriteMode) {
+ primary.forceWriteMode(options.forceWriteMode);
+ }
+ var writeConcern = {writeConcern: {w: expectedWritableNodes, wtimeout: 30 * 1000}};
+ assert.writeOK(primary.getDB('foo').bar.insert({x: 100}, writeConcern));
+ return primary;
+ };
+
+ // 2 should eventually stage a priority takeover from the primary.
+ var primary = ensurePrimary(2, 3);
+
+ jsTestLog('primary is now 2');
+ var config = assert.commandWorked(primary.adminCommand({replSetGetConfig: 1})).config;
+ jsTestLog('test configuration = ' + tojson(config));
+
+ jsTestLog('Setting up partitions: [0-1-2] [3] [4]');
+ conns[0].disconnect(conns[3]);
+ conns[0].disconnect(conns[4]);
+ conns[1].disconnect(conns[3]);
+ conns[1].disconnect(conns[4]);
+ conns[2].disconnect(conns[3]);
+ conns[2].disconnect(conns[4]);
+ conns[3].disconnect(conns[4]);
+ jsTestLog('Done setting up partitions');
+
+ jsTestLog(
+ 'partitions: nodes with each set of brackets [N1, N2, N3] form a complete network.');
+ jsTestLog(
+ 'partitions: [0-1-2] [3] [4] (only nodes 0 and 1 can replicate from primary node 2');
+
+ var doc = {x: 1};
+
+ // This timeout should be shorter in duration than the server parameter
+ // maxSyncSourceLagSecs.
+ // Some writes are expected to block for this 'timeout' duration before failing.
+ // Depending on the order of heartbeats (containing last committed op time) received
+ // by a node, it might hang up on its sync source. This may cause some of the write concern
+ // tests to fail.
+ var timeout = 20 * 1000;
+
+ jsTestLog('test1');
+ primary = ensurePrimary(2, 3);
+
+ jsTestLog('Non-existent write concern should be rejected.');
+ options = {writeConcern: {w: 'blahblah', wtimeout: timeout}};
+ assert.writeOK(primary.getDB('foo').bar.insert(doc));
+ var result = assert.writeError(primary.getDB('foo').bar.insert(doc, options));
+ assert.neq(null, result.getWriteConcernError());
+ assert.eq(ErrorCodes.UnknownReplWriteConcern,
+ result.getWriteConcernError().code,
+ tojson(result.getWriteConcernError()));
+
+ jsTestLog('Write concern "3 or 4" should fail - 3 and 4 are not connected to the primary.');
+ var options = {writeConcern: {w: '3 or 4', wtimeout: timeout}};
+ assert.writeOK(primary.getDB('foo').bar.insert(doc));
+ result = primary.getDB('foo').bar.insert(doc, options);
+ assert.neq(null, result.getWriteConcernError());
+ assert(result.getWriteConcernError().errInfo.wtimeout);
+
+ conns[1].reconnect(conns[4]);
+ jsTestLog('partitions: [0-1-2] [1-4] [3] ' +
+ '(all nodes besides node 3 can replicate from primary node 2)');
+ primary = ensurePrimary(2, 4);
+
+ jsTestLog('Write concern "3 or 4" should work - 4 is now connected to the primary ' +
+ primary.host + ' via node 1 ' + replTest.nodes[1].host);
+ options = {writeConcern: {w: '3 or 4', wtimeout: timeout}};
+ assert.writeOK(primary.getDB('foo').bar.insert(doc));
+ assert.writeOK(primary.getDB('foo').bar.insert(doc, options));
+
+ jsTestLog('Write concern "3 and 4" should fail - 3 is not connected to the primary.');
+ options = {writeConcern: {w: '3 and 4', wtimeout: timeout}};
+ assert.writeOK(primary.getDB('foo').bar.insert(doc));
+ result = assert.writeError(primary.getDB('foo').bar.insert(doc, options));
+ assert.neq(null, result.getWriteConcernError());
+ assert(result.getWriteConcernError().errInfo.wtimeout,
+ tojson(result.getWriteConcernError()));
+
+ conns[3].reconnect(conns[4]);
+ jsTestLog('partitions: [0-1-2] [1-4] [3-4] ' +
+ '(all secondaries can replicate from primary node 2)');
+ primary = ensurePrimary(2, 5);
+
+ jsTestLog('Write concern "3 and 4" should work - ' +
+ 'nodes 3 and 4 are connected to primary via node 1.');
+ options = {writeConcern: {w: '3 and 4', wtimeout: timeout}};
+ assert.writeOK(primary.getDB('foo').bar.insert(doc));
+ assert.writeOK(primary.getDB('foo').bar.insert(doc, options));
+
+ jsTestLog('Write concern "2" - writes to primary only.');
+ options = {writeConcern: {w: '2', wtimeout: 0}};
+ assert.writeOK(primary.getDB('foo').bar.insert(doc));
+ assert.writeOK(primary.getDB('foo').bar.insert(doc, options));
+
+ jsTestLog('Write concern "1 and 2"');
+ options = {writeConcern: {w: '1 and 2', wtimeout: 0}};
+ assert.writeOK(primary.getDB('foo').bar.insert(doc));
+ assert.writeOK(primary.getDB('foo').bar.insert(doc, options));
+
+ jsTestLog('Write concern "2 dc and 3 server"');
+ primary = ensurePrimary(2, 5);
+ options = {writeConcern: {w: '2 dc and 3 server', wtimeout: timeout}};
+ assert.writeOK(primary.getDB('foo').bar.insert(doc));
+ assert.writeOK(primary.getDB('foo').bar.insert(doc, options));
+
+ jsTestLog('Bringing down current primary node 2 ' + primary.host +
+ ' to allow next higher priority node 1 ' + replTest.nodes[1].host +
+ ' to become primary.');
+
+ conns[1].reconnect(conns[3]);
+ conns[2].disconnect(conns[0]);
+ conns[2].disconnect(conns[1]);
+ jsTestLog('partitions: [0-1] [2] [1-3-4] ' +
+ '(all secondaries except down node 2 can replicate from new primary node 1)');
+
+ // Node 1 with slightly higher priority will take over.
+ jsTestLog('1 must become primary here because otherwise the other members will take too ' +
+ 'long timing out their old sync threads');
+ primary = ensurePrimary(1, 4);
+
+ jsTestLog('Write concern "3 and 4" should still work with new primary node 1 ' +
+ primary.host);
+ options = {writeConcern: {w: '3 and 4', wtimeout: timeout}};
+ assert.writeOK(primary.getDB('foo').bar.insert(doc));
+ assert.writeOK(primary.getDB('foo').bar.insert(doc, options));
+
+ jsTestLog('Write concern "2" should fail because node 2 ' + replTest.nodes[2].host +
+ ' is down.');
+ options = {writeConcern: {w: '2', wtimeout: timeout}};
+ assert.writeOK(primary.getDB('foo').bar.insert(doc));
+ result = assert.writeError(primary.getDB('foo').bar.insert(doc, options));
+ assert.neq(null, result.getWriteConcernError());
+ assert(result.getWriteConcernError().errInfo.wtimeout);
+
+ replTest.stopSet();
+ };
+
+};