diff options
author | Richard Samuels <richard.l.samuels@gmail.com> | 2020-09-30 17:48:10 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-10-08 16:32:28 +0000 |
commit | 70efbd4fbad2183ec1f503efef2669e5698bada3 (patch) | |
tree | 6889e6917bcb312b02d62676aeb4541b25ad7f77 | |
parent | 57518001ea06a589db892971a365bb3779f74aba (diff) | |
download | mongo-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.js | 36 | ||||
-rw-r--r-- | jstests/noPassthrough/mongobridge_testcommands.js | 38 | ||||
-rw-r--r-- | src/mongo/shell/bridge.js | 22 |
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', { |