summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Samuels <richard.l.samuels@gmail.com>2020-09-30 17:48:10 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-10-08 16:32:28 +0000
commit70efbd4fbad2183ec1f503efef2669e5698bada3 (patch)
tree6889e6917bcb312b02d62676aeb4541b25ad7f77
parent57518001ea06a589db892971a365bb3779f74aba (diff)
downloadmongo-70efbd4fbad2183ec1f503efef2669e5698bada3.tar.gz
SERVER-45551 Add assertions to ensure test commands are enabled when using mongobridge functions that require it
-rw-r--r--jstests/noPassthrough/mongobridge.js36
-rw-r--r--jstests/noPassthrough/mongobridge_testcommands.js38
-rw-r--r--src/mongo/shell/bridge.js22
3 files changed, 96 insertions, 0 deletions
diff --git a/jstests/noPassthrough/mongobridge.js b/jstests/noPassthrough/mongobridge.js
new file mode 100644
index 00000000000..33e24bd571f
--- /dev/null
+++ b/jstests/noPassthrough/mongobridge.js
@@ -0,0 +1,36 @@
+/**
+ * Test that mongobridge's *From commands work
+ *
+ * @tags: [requires_replication,requires_sharding,live_record_incompatible]
+ */
+
+// mongobridge depends on test commands being enabled. Also EVERY repl/sharding
+// test depends on this. Think twice if you're thinking of changing the default.
+assert.eq(jsTest.options().enableTestCommands, true);
+
+// we expect this to work just fine given that enableTestCommands is true by default
+var st = new ShardingTest({shards: {rs0: {nodes: 2}}, mongos: 1, config: 1, useBridge: true});
+var wc = {writeConcern: {w: 2, wtimeout: 4000}};
+
+// delayMessages from should cause a write error on this insert
+st.rs0.getPrimary().delayMessagesFrom(st.rs0.getSecondary(), 13000);
+assert.commandFailed(st.s0.getCollection('testDB.cll').insert({test: 5}, wc));
+st.rs0.getPrimary().delayMessagesFrom(st.rs0.getSecondary(), 0);
+
+// discardMessages w/ a loss probabilty of 1 should also cause a write error
+st.rs0.getPrimary().discardMessagesFrom(st.rs0.getSecondary(), 1.0);
+assert.commandFailed(st.s0.getCollection('testDB.cll').insert({test: 5}, wc));
+st.rs0.getPrimary().discardMessagesFrom(st.rs0.getSecondary(), 0.0);
+
+// reject connections should make the write fail as well
+st.rs0.getPrimary().rejectConnectionsFrom(st.rs0.getSecondary());
+assert.commandFailed(st.s0.getCollection('testDB.cll').insert({test: 5}, wc));
+// but if we make mongobridge accept the connections, the write should now
+// succeed
+st.rs0.getPrimary().acceptConnectionsFrom(st.rs0.getSecondary());
+assert.commandWorked(st.s0.getCollection('testDB.cll').insert({test: 5}, wc));
+
+// None of the above commands prevent writes to the primary, so we still
+// expect to find 4 documents
+assert.eq(st.s0.getCollection('testDB.cll').find({test: 5}).length(), 4);
+st.stop();
diff --git a/jstests/noPassthrough/mongobridge_testcommands.js b/jstests/noPassthrough/mongobridge_testcommands.js
new file mode 100644
index 00000000000..fe03bfd0c02
--- /dev/null
+++ b/jstests/noPassthrough/mongobridge_testcommands.js
@@ -0,0 +1,38 @@
+/**
+ * Test that mongobridge's *From commands succeed when test commands are
+ * enabled, and fail when disabled.
+ *
+ * @tags: [requires_replication,requires_sharding,live_record_incompatible]
+ */
+
+// mongobridge depends on test commands being enabled. Also EVERY repl/sharding
+// test depends on this. Think twice if you're thinking of changing the default.
+assert.eq(jsTest.options().enableTestCommands, true);
+
+// we expect this to work just fine given that enableTestCommands is true by default
+var st = new ShardingTest({shards: {rs0: {nodes: 2}}, mongos: 1, config: 1, useBridge: true});
+
+// changing enableTestcommands should have no impact on the existing mongod/s/bridge instances,
+TestData.enableTestCommands = false;
+st.rs0.getSecondary().delayMessagesFrom(st.rs0.getPrimary(), 13000);
+st.rs0.getSecondary().discardMessagesFrom(st.rs0.getPrimary(), 1.0);
+st.rs0.getSecondary().acceptConnectionsFrom(st.rs0.getPrimary());
+st.rs0.getSecondary().rejectConnectionsFrom(st.rs0.getPrimary());
+st.stop();
+
+// Start another test, this time with enableTestCommands as false.
+// Repeating the above, we expect the commands to fail
+st = new ShardingTest({shards: {rs0: {nodes: 2}}, mongos: 1, config: 1, useBridge: true});
+assert.throws(() => {
+ st.rs0.getSecondary().delayMessagesFrom(st.rs0.getPrimary(), 13000);
+});
+assert.throws(() => {
+ st.rs0.getSecondary().discardMessagesFrom(st.rs0.getPrimary(), 1.0);
+});
+assert.throws(() => {
+ st.rs0.getSecondary().acceptConnectionsFrom(st.rs0.getPrimary());
+});
+assert.throws(() => {
+ st.rs0.getSecondary().rejectConnectionsFrom(st.rs0.getPrimary());
+});
+st.stop();
diff --git a/src/mongo/shell/bridge.js b/src/mongo/shell/bridge.js
index fa34809162b..73306c6a99b 100644
--- a/src/mongo/shell/bridge.js
+++ b/src/mongo/shell/bridge.js
@@ -31,6 +31,13 @@ function MongoBridge(options) {
// The connection used by a test for running commands against the mongod or mongos process.
var userConn;
+ // copy the enableTestCommands field from TestData since this can be
+ // changed in the middle of a test. This is the same value that
+ // will ultimately be used by MongoRunner, and determines if
+ // *From commands can be used during the lifetime of the MongoBridge
+ // instance.
+ this._testCommandsEnabledAtInit = jsTest.options().enableTestCommands;
+
// A separate (hidden) connection for configuring the mongobridge process.
var controlConn;
@@ -181,6 +188,17 @@ function MongoBridge(options) {
bridges.forEach(bridge => bridge.rejectConnectionsFrom(this));
};
+ // All *From functions require that test commands be enabled on the mongod
+ // instance (which populates the hostInfo field). Verify that they're
+ // enabled by sending isMaster
+ function checkTestCommandsEnabled(fn_name) {
+ return function(bridge) {
+ assert(bridge._testCommandsEnabledAtInit,
+ "testing commands have not been enabled. " + fn_name +
+ " will not work as expected");
+ };
+ }
+
/**
* Configures 'this' bridge to accept new connections from the 'dest' of each of the 'bridges'.
*
@@ -191,6 +209,7 @@ function MongoBridge(options) {
bridges = [bridges];
}
bridges.forEach(throwErrorIfNotMongoBridgeInstance);
+ bridges.forEach(checkTestCommandsEnabled("acceptConnectionsFrom"));
bridges.forEach(bridge => {
var res = runBridgeCommand(controlConn, 'acceptConnectionsFrom', {host: bridge.dest});
@@ -211,6 +230,7 @@ function MongoBridge(options) {
bridges = [bridges];
}
bridges.forEach(throwErrorIfNotMongoBridgeInstance);
+ bridges.forEach(checkTestCommandsEnabled("rejectConnectionsFrom"));
bridges.forEach(bridge => {
var res = runBridgeCommand(controlConn, 'rejectConnectionsFrom', {host: bridge.dest});
@@ -232,6 +252,7 @@ function MongoBridge(options) {
bridges = [bridges];
}
bridges.forEach(throwErrorIfNotMongoBridgeInstance);
+ bridges.forEach(checkTestCommandsEnabled("delayMessagesFrom"));
bridges.forEach(bridge => {
var res = runBridgeCommand(controlConn, 'delayMessagesFrom', {
@@ -257,6 +278,7 @@ function MongoBridge(options) {
bridges = [bridges];
}
bridges.forEach(throwErrorIfNotMongoBridgeInstance);
+ bridges.forEach(checkTestCommandsEnabled("discardMessagesFrom"));
bridges.forEach(bridge => {
var res = runBridgeCommand(controlConn, 'discardMessagesFrom', {