summaryrefslogtreecommitdiff
path: root/buildscripts
diff options
context:
space:
mode:
authorJudah Schvimer <judah@mongodb.com>2016-07-19 09:44:37 -0400
committerJudah Schvimer <judah@mongodb.com>2016-07-19 09:44:37 -0400
commit433ffe0574f19f879b16d195068ce81ee55ee681 (patch)
tree420b39857177c7f87039156b54ee69d39f9fecd3 /buildscripts
parent5f57ee740b1eaa188532363fc363f42234057748 (diff)
downloadmongo-433ffe0574f19f879b16d195068ce81ee55ee681.tar.gz
SERVER-24538 Add small_oplog_rs_initsync_static passthrough to include periodic initial sync members
Diffstat (limited to 'buildscripts')
-rw-r--r--buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml33
-rw-r--r--buildscripts/resmokelib/testing/fixtures/replicaset.py40
-rw-r--r--buildscripts/resmokelib/testing/hooks.py50
3 files changed, 120 insertions, 3 deletions
diff --git a/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml
new file mode 100644
index 00000000000..3963f9e16a3
--- /dev/null
+++ b/buildscripts/resmokeconfig/suites/core_small_oplog_rs_initsync_static.yml
@@ -0,0 +1,33 @@
+selector:
+ js_test:
+ roots:
+ - jstests/core/*.js
+ exclude_files:
+ # These tests are not expected to pass with replica-sets:
+ - jstests/core/dbadmin.js
+ - jstests/core/opcounters_write_cmd.js
+ - jstests/core/read_after_optime.js
+ - jstests/core/capped_update.js
+ # Blacklisted due to SERVER-25131
+ - jstests/core/bypass_doc_validation.js
+
+run_hook_interval: &run_hook_interval 20
+executor:
+ js_test:
+ config:
+ shell_options:
+ eval: "testingReplication = true;"
+ readMode: commands
+ hooks:
+ - class: IntermediateInitialSync
+ n: *run_hook_interval
+ - class: CleanEveryN
+ n: *run_hook_interval
+ fixture:
+ class: ReplicaSetFixture
+ mongod_options:
+ oplogSize: 511
+ set_parameters:
+ enableTestCommands: 1
+ num_nodes: 2
+ start_initial_sync_node: True
diff --git a/buildscripts/resmokelib/testing/fixtures/replicaset.py b/buildscripts/resmokelib/testing/fixtures/replicaset.py
index be24295ece7..338979585d7 100644
--- a/buildscripts/resmokelib/testing/fixtures/replicaset.py
+++ b/buildscripts/resmokelib/testing/fixtures/replicaset.py
@@ -29,6 +29,7 @@ class ReplicaSetFixture(interface.ReplFixture):
dbpath_prefix=None,
preserve_dbpath=False,
num_nodes=2,
+ start_initial_sync_node=False,
write_concern_majority_journal_default=None,
auth_options=None,
replset_config_options=None):
@@ -39,6 +40,7 @@ class ReplicaSetFixture(interface.ReplFixture):
self.mongod_options = utils.default_if_none(mongod_options, {})
self.preserve_dbpath = preserve_dbpath
self.num_nodes = num_nodes
+ self.start_initial_sync_node = start_initial_sync_node
self.write_concern_majority_journal_default = write_concern_majority_journal_default
self.auth_options = auth_options
self.replset_config_options = utils.default_if_none(replset_config_options, {})
@@ -58,6 +60,8 @@ class ReplicaSetFixture(interface.ReplFixture):
self.nodes = []
self.replset_name = None
+ self.initial_sync_node = None
+ self.initial_sync_node_idx = -1
def setup(self):
self.replset_name = self.mongod_options.get("replSet", "rs")
@@ -70,6 +74,14 @@ class ReplicaSetFixture(interface.ReplFixture):
for node in self.nodes:
node.setup()
+ if self.start_initial_sync_node:
+ if not self.initial_sync_node:
+ self.initial_sync_node_idx = len(self.nodes)
+ self.initial_sync_node = self._new_mongod(self.initial_sync_node_idx,
+ self.replset_name)
+ self.initial_sync_node.setup()
+ self.initial_sync_node.await_ready()
+
self.port = self.get_primary().port
# Call await_ready() on each of the nodes here because we want to start the election as
@@ -87,6 +99,13 @@ class ReplicaSetFixture(interface.ReplFixture):
# Only 7 nodes in a replica set can vote, so the other members must be non-voting.
member_info["votes"] = 0
members.append(member_info)
+ if self.initial_sync_node:
+ members.append({"_id": self.initial_sync_node_idx,
+ "host": self.initial_sync_node.get_connection_string(),
+ "priority": 0,
+ "hidden": 1,
+ "votes": 0})
+
initiate_cmd_obj = {"replSetInitiate": {"_id": self.replset_name, "members": members}}
if self.write_concern_majority_journal_default is not None:
@@ -136,6 +155,9 @@ class ReplicaSetFixture(interface.ReplFixture):
else:
self.logger.info("Stopping all members of the replica set...")
+ if self.initial_sync_node:
+ success = self.initial_sync_node.teardown() and success
+
# Terminate the secondaries first to reduce noise in the logs.
for node in reversed(self.nodes):
success = node.teardown() and success
@@ -146,7 +168,12 @@ class ReplicaSetFixture(interface.ReplFixture):
return success
def is_running(self):
- return all(node.is_running() for node in self.nodes)
+ running = all(node.is_running() for node in self.nodes)
+
+ if self.initial_sync_node:
+ running = self.initial_sync_node.is_running() or running
+
+ return running
def get_primary(self):
# The primary is always the first element of the 'nodes' list because all other members of
@@ -156,6 +183,9 @@ class ReplicaSetFixture(interface.ReplFixture):
def get_secondaries(self):
return self.nodes[1:]
+ def get_initial_sync_node(self):
+ return self.initial_sync_node
+
def _new_mongod(self, index, replset_name):
"""
Returns a standalone.MongoDFixture configured to be used as a
@@ -175,12 +205,14 @@ class ReplicaSetFixture(interface.ReplFixture):
def _get_logger_for_mongod(self, index):
"""
- Returns a new logging.Logger instance for use as the primary or
- secondary of a replica-set.
+ Returns a new logging.Logger instance for use as the primary, secondary, or initial
+ sync member of a replica-set.
"""
if index == 0:
logger_name = "%s:primary" % (self.logger.name)
+ elif index == self.initial_sync_node_idx:
+ logger_name = "%s:initsync" % (self.logger.name)
else:
suffix = str(index - 1) if self.num_nodes > 2 else ""
logger_name = "%s:secondary%s" % (self.logger.name, suffix)
@@ -192,4 +224,6 @@ class ReplicaSetFixture(interface.ReplFixture):
raise ValueError("Must call setup() before calling get_connection_string()")
conn_strs = [node.get_connection_string() for node in self.nodes]
+ if self.initial_sync_node:
+ conn_strs.append(self.initial_sync_node.get_connection_string())
return self.replset_name + "/" + ",".join(conn_strs)
diff --git a/buildscripts/resmokelib/testing/hooks.py b/buildscripts/resmokelib/testing/hooks.py
index 1a438cf0867..f845f0c7927 100644
--- a/buildscripts/resmokelib/testing/hooks.py
+++ b/buildscripts/resmokelib/testing/hooks.py
@@ -161,6 +161,55 @@ class JsCustomBehavior(CustomBehavior):
test_report.stopTest(self.hook_test_case)
+class IntermediateInitialSync(JsCustomBehavior):
+ """
+ This hook accepts a parameter 'n' that specifies a number of tests after which it will start up
+ a node to initial sync, wait for replication to finish, and then validate the data.
+
+ This requires the ReplicaSetFixture to be started with 'start_initial_sync_node=True'.
+ """
+
+ DEFAULT_N = CleanEveryN.DEFAULT_N
+
+ def __init__(self, logger, fixture, n=DEFAULT_N):
+ description = "Intermediate Initial Sync"
+ js_filename = os.path.join("jstests", "hooks", "run_initial_sync_node_validation.js")
+ JsCustomBehavior.__init__(self, logger, fixture, js_filename, description)
+
+ self.n = n
+ self.tests_run = 0
+
+ def after_test(self, test, test_report):
+ self.tests_run += 1
+ sync_node = self.fixture.get_initial_sync_node();
+ sync_node_conn = utils.new_mongo_client(port=sync_node.port)
+
+ if self.tests_run >= self.n:
+ self.tests_run = 0
+ teardown_success = sync_node.teardown()
+
+ self.logger.info("Starting the initial sync node back up again...")
+ sync_node.setup()
+ sync_node.await_ready()
+
+ # Do initial sync round.
+ self.logger.info("Waiting for initial sync node to go into SECONDARY state")
+ cmd = bson.SON([("replSetTest", 1),
+ ("waitForMemberState", 2),
+ ("timeoutMillis", 20 * 60 * 1000)])
+ try:
+ sync_node_conn.admin.command(cmd)
+ except self.hook_test_case.failureException as err:
+ self.logger.exception("{0} failed".format(description))
+ test_report.addFailure(self.hook_test_case, sys.exc_info())
+ raise errors.TestFailure(err.args[0])
+
+ # Run data validation and dbhash checking.
+ JsCustomBehavior.after_test(self, test, test_report)
+
+ if not teardown_success:
+ raise errors.TestFailure("%s did not exit cleanly" % (sync_node))
+
class ValidateCollections(JsCustomBehavior):
"""
Runs full validation on all collections in all databases on every stand-alone
@@ -215,4 +264,5 @@ _CUSTOM_BEHAVIORS = {
"CleanEveryN": CleanEveryN,
"CheckReplDBHash": CheckReplDBHash,
"ValidateCollections": ValidateCollections,
+ "IntermediateInitialSync": IntermediateInitialSync,
}