Files
mongo/buildscripts/resmokelib/testing/fixtures/interface.py
Max Hirschhorn e54239b3b9 SERVER-32691 Add write_concern_majority_passthrough.yml test suite.
Reverts to emulating the write concern to work around how prior to
MongoDB 3.4, operations that did writes didn't necessarily accept a
writeConcern object.

Also limits the usage of replica set connection strings to only the
write_concern_majority_passthrough.yml test suite to work around the
lack of complete support of MongoURI parsing in versions of the mongo
shell prior to MongoDB 3.4.

(cherry picked from commit 264d971842)
2018-02-24 02:07:16 -05:00

131 lines
3.8 KiB
Python

"""
Interface of the different fixtures for executing JSTests against.
"""
from __future__ import absolute_import
import time
import pymongo
from ... import errors
from ... import logging
class Fixture(object):
"""
Base class for all fixtures.
"""
def __init__(self, logger, job_num):
"""
Initializes the fixtures with a logger instance.
"""
if not isinstance(logger, logging.Logger):
raise TypeError("logger must be a Logger instance")
if not isinstance(job_num, int):
raise TypeError("job_num must be an integer")
elif job_num < 0:
raise ValueError("job_num must be a nonnegative integer")
self.logger = logger
self.job_num = job_num
self.port = None # Port that the mongo shell should connect to.
def setup(self):
"""
Creates the fixture.
"""
pass
def await_ready(self):
"""
Blocks until the fixture can be used for testing.
"""
pass
def teardown(self):
"""
Destroys the fixture. Return true if was successful, and false otherwise.
"""
return True
def is_running(self):
"""
Returns true if the fixture is still operating and more tests
can be run, and false otherwise.
"""
return True
def get_internal_connection_string(self):
"""
Returns the connection string for this fixture. This is NOT a
driver connection string, but a connection string of the format
expected by the mongo::ConnectionString class.
"""
raise NotImplementedError(
"get_internal_connection_string must be implemented by Fixture subclasses")
def get_driver_connection_url(self):
"""
Return the mongodb connection string as defined here:
https://docs.mongodb.com/manual/reference/connection-string/
"""
raise NotImplementedError(
"get_driver_connection_url must be implemented by Fixture subclasses")
def __str__(self):
return "%s (Job #%d)" % (self.__class__.__name__, self.job_num)
def __repr__(self):
return "%r(%r, %r)" % (self.__class__.__name__, self.logger, self.job_num)
class ReplFixture(Fixture):
"""
Base class for all fixtures that support replication.
"""
AWAIT_REPL_TIMEOUT_MINS = 5
def get_primary(self):
"""
Returns the primary of a replica set, or the master of a
master-slave deployment.
"""
raise NotImplementedError("get_primary must be implemented by ReplFixture subclasses")
def get_secondaries(self):
"""
Returns a list containing the secondaries of a replica set, or
the slave of a master-slave deployment.
"""
raise NotImplementedError("get_secondaries must be implemented by ReplFixture subclasses")
def retry_until_wtimeout(self, insert_fn):
"""
Given a callback function representing an insert operation on
the primary, handle any connection failures, and keep retrying
the operation for up to 'AWAIT_REPL_TIMEOUT_MINS' minutes.
The insert operation callback should take an argument for the
number of remaining seconds to provide as the timeout for the
operation.
"""
deadline = time.time() + ReplFixture.AWAIT_REPL_TIMEOUT_MINS * 60
while True:
try:
remaining = deadline - time.time()
insert_fn(remaining)
break
except pymongo.errors.ConnectionFailure:
remaining = deadline - time.time()
if remaining <= 0.0:
raise errors.ServerFailure("Failed to connect to the primary on port %d" %
self.port)