summaryrefslogtreecommitdiff
path: root/buildscripts/resmokelib
diff options
context:
space:
mode:
Diffstat (limited to 'buildscripts/resmokelib')
-rw-r--r--buildscripts/resmokelib/testing/fixtures/interface.py10
-rw-r--r--buildscripts/resmokelib/testing/fixtures/replicaset.py6
-rw-r--r--buildscripts/resmokelib/testing/fixtures/shardedcluster.py12
-rw-r--r--buildscripts/resmokelib/testing/fixtures/standalone.py8
-rw-r--r--buildscripts/resmokelib/testing/fixtures/yesfixture.py4
-rw-r--r--buildscripts/resmokelib/testing/testcases/fixture.py24
6 files changed, 45 insertions, 19 deletions
diff --git a/buildscripts/resmokelib/testing/fixtures/interface.py b/buildscripts/resmokelib/testing/fixtures/interface.py
index b9b92a57a71..7eebc5071b4 100644
--- a/buildscripts/resmokelib/testing/fixtures/interface.py
+++ b/buildscripts/resmokelib/testing/fixtures/interface.py
@@ -65,7 +65,7 @@ class Fixture(object, metaclass=registry.make_registry_metaclass(_FIXTURES)):
"""Block until the fixture can be used for testing."""
pass
- def teardown(self, finished=False): # noqa
+ def teardown(self, finished=False, kill=False): # noqa
"""Destroy the fixture.
The fixture's logging handlers are closed if 'finished' is true,
@@ -76,7 +76,7 @@ class Fixture(object, metaclass=registry.make_registry_metaclass(_FIXTURES)):
"""
try:
- self._do_teardown()
+ self._do_teardown(kill=kill)
finally:
if finished:
for handler in self.logger.handlers:
@@ -84,7 +84,7 @@ class Fixture(object, metaclass=registry.make_registry_metaclass(_FIXTURES)):
# want the logs to eventually get flushed.
logging.flush.close_later(handler)
- def _do_teardown(self): # noqa
+ def _do_teardown(self, kill=False): # noqa
"""Destroy the fixture.
This method must be implemented by subclasses.
@@ -243,7 +243,7 @@ class FixtureTeardownHandler(object):
"""
return self._message
- def teardown(self, fixture, name): # noqa: D406,D407,D411,D413
+ def teardown(self, fixture, name, kill=False): # noqa: D406,D407,D411,D413
"""Tear down the given fixture and log errors instead of raising a ServerFailure exception.
Args:
@@ -254,7 +254,7 @@ class FixtureTeardownHandler(object):
"""
try:
self._logger.info("Stopping %s...", name)
- fixture.teardown()
+ fixture.teardown(kill=kill)
self._logger.info("Successfully stopped %s.", name)
return True
except errors.ServerFailure as err:
diff --git a/buildscripts/resmokelib/testing/fixtures/replicaset.py b/buildscripts/resmokelib/testing/fixtures/replicaset.py
index 8c93ada0b24..7f4851128a2 100644
--- a/buildscripts/resmokelib/testing/fixtures/replicaset.py
+++ b/buildscripts/resmokelib/testing/fixtures/replicaset.py
@@ -400,7 +400,7 @@ class ReplicaSetFixture(interface.ReplFixture): # pylint: disable=too-many-inst
for node in self.nodes:
node.mongo_client().admin.command(cmd)
- def _do_teardown(self):
+ def _do_teardown(self, kill=False):
self.logger.info("Stopping all members of the replica set...")
running_at_start = self.is_running()
@@ -411,11 +411,11 @@ class ReplicaSetFixture(interface.ReplFixture): # pylint: disable=too-many-inst
teardown_handler = interface.FixtureTeardownHandler(self.logger)
if self.initial_sync_node:
- teardown_handler.teardown(self.initial_sync_node, "initial sync node")
+ teardown_handler.teardown(self.initial_sync_node, "initial sync node", kill=kill)
# Terminate the secondaries first to reduce noise in the logs.
for node in reversed(self.nodes):
- teardown_handler.teardown(node, "replica set member on port %d" % node.port)
+ teardown_handler.teardown(node, "replica set member on port %d" % node.port, kill=kill)
if teardown_handler.was_successful():
self.logger.info("Successfully stopped all members of the replica set.")
diff --git a/buildscripts/resmokelib/testing/fixtures/shardedcluster.py b/buildscripts/resmokelib/testing/fixtures/shardedcluster.py
index edefdf11f9f..0c927304232 100644
--- a/buildscripts/resmokelib/testing/fixtures/shardedcluster.py
+++ b/buildscripts/resmokelib/testing/fixtures/shardedcluster.py
@@ -191,7 +191,7 @@ class ShardedClusterFixture(interface.Fixture): # pylint: disable=too-many-inst
client.admin.command({"balancerStart": 1}, maxTimeMS=timeout_ms)
self.logger.info("Started the balancer")
- def _do_teardown(self):
+ def _do_teardown(self, kill=False):
"""Shut down the sharded cluster."""
self.logger.info("Stopping all members of the sharded cluster...")
@@ -206,13 +206,13 @@ class ShardedClusterFixture(interface.Fixture): # pylint: disable=too-many-inst
teardown_handler = interface.FixtureTeardownHandler(self.logger)
if self.configsvr is not None:
- teardown_handler.teardown(self.configsvr, "config server")
+ teardown_handler.teardown(self.configsvr, "config server", kill=kill)
for mongos in self.mongos:
- teardown_handler.teardown(mongos, "mongos")
+ teardown_handler.teardown(mongos, "mongos", kill=kill)
for shard in self.shards:
- teardown_handler.teardown(shard, "shard")
+ teardown_handler.teardown(shard, "shard", kill=kill)
if teardown_handler.was_successful():
self.logger.info("Successfully stopped all members of the sharded cluster.")
@@ -429,7 +429,7 @@ class _MongoSFixture(interface.Fixture):
self.logger.info("Successfully contacted the mongos on port %d.", self.port)
- def _do_teardown(self):
+ def _do_teardown(self, kill=False):
if self.mongos is None:
self.logger.warning("The mongos fixture has not been set up yet.")
return # Teardown is still a success even if nothing is running.
@@ -442,7 +442,7 @@ class _MongoSFixture(interface.Fixture):
self.logger.warning(msg)
raise errors.ServerFailure(msg)
- self.mongos.stop()
+ self.mongos.stop(kill=kill)
exit_code = self.mongos.wait()
if exit_code == 0:
diff --git a/buildscripts/resmokelib/testing/fixtures/standalone.py b/buildscripts/resmokelib/testing/fixtures/standalone.py
index 686d360fb36..3c54f41f689 100644
--- a/buildscripts/resmokelib/testing/fixtures/standalone.py
+++ b/buildscripts/resmokelib/testing/fixtures/standalone.py
@@ -111,7 +111,7 @@ class MongoDFixture(interface.Fixture):
self.logger.info("Successfully contacted the mongod on port %d.", self.port)
- def _do_teardown(self):
+ def _do_teardown(self, kill=False):
if self.mongod is None:
self.logger.warning("The mongod fixture has not been set up yet.")
return # Still a success even if nothing is running.
@@ -124,10 +124,12 @@ class MongoDFixture(interface.Fixture):
self.logger.warning(msg)
raise errors.ServerFailure(msg)
- self.mongod.stop()
+ self.mongod.stop(kill)
exit_code = self.mongod.wait()
- if exit_code == 0:
+ # SIGKILL has an exit code of 9 and Python's subprocess module returns
+ # negative versions of system calls.
+ if exit_code == 0 or (exit_code == -9 and kill):
self.logger.info("Successfully stopped the mongod on port {:d}.".format(self.port))
else:
self.logger.warning("Stopped the mongod on port {:d}. "
diff --git a/buildscripts/resmokelib/testing/fixtures/yesfixture.py b/buildscripts/resmokelib/testing/fixtures/yesfixture.py
index defdffb4058..310bd8c34b1 100644
--- a/buildscripts/resmokelib/testing/fixtures/yesfixture.py
+++ b/buildscripts/resmokelib/testing/fixtures/yesfixture.py
@@ -35,7 +35,7 @@ class YesFixture(interface.Fixture): # pylint: disable=abstract-method
logger = self.logger.new_fixture_node_logger("yes{:d}".format(index))
return programs.generic_program(logger, ["yes", self.__message])
- def _do_teardown(self):
+ def _do_teardown(self, kill=False):
running_at_start = self.is_running()
success = True # Still a success even if nothing is running.
@@ -49,7 +49,7 @@ class YesFixture(interface.Fixture): # pylint: disable=abstract-method
if process is not None:
if running_at_start:
self.logger.info("Stopping yes process with pid %d...", process.pid)
- process.stop()
+ process.stop(kill)
exit_code = process.wait()
success = (exit_code == -signal.SIGTERM) and success
diff --git a/buildscripts/resmokelib/testing/testcases/fixture.py b/buildscripts/resmokelib/testing/testcases/fixture.py
index dee7757c3d8..fb074fd050b 100644
--- a/buildscripts/resmokelib/testing/testcases/fixture.py
+++ b/buildscripts/resmokelib/testing/testcases/fixture.py
@@ -70,3 +70,27 @@ class FixtureTeardownTestCase(FixtureTestCase):
except:
self.logger.exception("An error occurred during the teardown of %s.", self.fixture)
raise
+
+
+class FixtureKillTestCase(FixtureTestCase):
+ """TestCase for killing a fixture. Intended for use before archiving a failed test."""
+
+ REGISTERED_NAME = registry.LEAVE_UNREGISTERED
+ PHASE = "kill"
+
+ def __init__(self, logger, fixture, job_name):
+ """Initialize the FixtureKillTestCase."""
+ FixtureTestCase.__init__(self, logger, job_name, self.PHASE)
+ self.fixture = fixture
+
+ def run_test(self):
+ """Tear down the fixture."""
+ try:
+ self.return_code = 2 # Test return code of 2 is used for fixture failures.
+ self.logger.info("Killing the fixture %s.", self.fixture)
+ self.fixture.teardown(finished=False, kill=True)
+ self.logger.info("Finished killing %s.", self.fixture)
+ self.return_code = 0
+ except:
+ self.logger.exception("An error occurred while killing %s.", self.fixture)
+ raise