diff --git a/.evergreen/run-tests.sh b/.evergreen/run-tests.sh index 50902d020..9987bd694 100755 --- a/.evergreen/run-tests.sh +++ b/.evergreen/run-tests.sh @@ -169,8 +169,7 @@ else fi # Don't download unittest-xml-reporting from pypi, which often fails. -HAVE_XMLRUNNER=$($PYTHON -c "import pkgutil, sys; sys.stdout.write('1' if pkgutil.find_loader('xmlrunner') else '0')") -if [ $HAVE_XMLRUNNER = "1" ]; then +if $PYTHON -c "import xmlrunner"; then # The xunit output dir must be a Python style absolute path. XUNIT_DIR="$(pwd)/xunit-results" if [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin diff --git a/test/__init__.py b/test/__init__.py index 73a91c0b2..2d7fdb6f8 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -27,7 +27,8 @@ import warnings try: from xmlrunner import XMLTestRunner HAVE_XML = True -except ImportError: +# ValueError is raised when version 3+ is installed on Jython 2.7. +except (ImportError, ValueError): HAVE_XML = False try: diff --git a/test/test_client.py b/test/test_client.py index be4bff0e1..6b4f23165 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -60,6 +60,7 @@ from pymongo.read_preferences import ReadPreference from pymongo.server_selectors import (any_server_selector, writable_server_selector) from pymongo.server_type import SERVER_TYPE +from pymongo.settings import TOPOLOGY_TYPE from pymongo.srv_resolver import _HAVE_DNSPYTHON from pymongo.write_concern import WriteConcern from test import (client_context, @@ -1552,6 +1553,25 @@ class TestClient(IntegrationTest): # Each ping command should not take more than 2 seconds self.assertLess(total, 2) + @client_context.require_replica_set + def test_direct_connection(self): + # direct_connection=True should result in Single topology. + client = rs_or_single_client(directConnection=True) + client.admin.command('ping') + self.assertEqual(len(client.nodes), 1) + self.assertEqual(client._topology_settings.get_topology_type(), + TOPOLOGY_TYPE.Single) + client.close() + + # direct_connection=False should result in RS topology. + client = rs_or_single_client(directConnection=False) + client.admin.command('ping') + self.assertGreaterEqual(len(client.nodes), 1) + self.assertIn(client._topology_settings.get_topology_type(), + [TOPOLOGY_TYPE.ReplicaSetNoPrimary, + TOPOLOGY_TYPE.ReplicaSetWithPrimary]) + client.close() + class TestExhaustCursor(IntegrationTest): """Test that clients properly handle errors from exhaust cursors.""" diff --git a/test/test_discovery_and_monitoring.py b/test/test_discovery_and_monitoring.py index 9062d7db5..4b17fc853 100644 --- a/test/test_discovery_and_monitoring.py +++ b/test/test_discovery_and_monitoring.py @@ -21,17 +21,19 @@ import threading sys.path[0:0] = [""] from bson import json_util, Timestamp -from pymongo import common, MongoClient +from pymongo import common from pymongo.errors import (AutoReconnect, ConfigurationError, NetworkTimeout, NotMasterError, OperationFailure) from pymongo.helpers import _check_command_response -from pymongo.topology import _ErrorContext -from pymongo.topology_description import TOPOLOGY_TYPE from pymongo.ismaster import IsMaster from pymongo.server_description import ServerDescription, SERVER_TYPE +from pymongo.settings import TopologySettings +from pymongo.topology import Topology, _ErrorContext +from pymongo.topology_description import TOPOLOGY_TYPE +from pymongo.uri_parser import parse_uri from test import unittest, IntegrationTest from test.utils import (assertion_context, Barrier, @@ -65,8 +67,23 @@ class MockMonitor(object): def create_mock_topology(uri, monitor_class=MockMonitor): - mc = MongoClient(uri, _monitor_class=monitor_class) - return mc._get_topology() + parsed_uri = parse_uri(uri) + replica_set_name = None + direct_connection = None + if 'replicaset' in parsed_uri['options']: + replica_set_name = parsed_uri['options']['replicaset'] + if 'directConnection' in parsed_uri['options']: + direct_connection = parsed_uri['options']['directConnection'] + + topology_settings = TopologySettings( + parsed_uri['nodelist'], + replica_set_name=replica_set_name, + monitor_class=monitor_class, + direct_connection=direct_connection) + + c = Topology(topology_settings) + c.open() + return c def got_ismaster(topology, server_address, ismaster_response): diff --git a/test/utils.py b/test/utils.py index 5f51b7f10..4e213d50b 100644 --- a/test/utils.py +++ b/test/utils.py @@ -427,12 +427,13 @@ def _connection_string(h, authenticate): return "mongodb://%s" % (str(h),) -def _mongo_client(host, port, authenticate=True, direct=False, **kwargs): +def _mongo_client(host, port, authenticate=True, directConnection=False, + **kwargs): """Create a new client over SSL/TLS if necessary.""" host = host or client_context.host port = port or client_context.port client_options = client_context.default_client_options.copy() - if client_context.replica_set_name and not direct: + if client_context.replica_set_name and not directConnection: client_options['replicaSet'] = client_context.replica_set_name client_options.update(kwargs) @@ -444,12 +445,13 @@ def _mongo_client(host, port, authenticate=True, direct=False, **kwargs): def single_client_noauth(h=None, p=None, **kwargs): """Make a direct connection. Don't authenticate.""" - return _mongo_client(h, p, authenticate=False, direct=True, **kwargs) + return _mongo_client(h, p, authenticate=False, + directConnection=True, **kwargs) def single_client(h=None, p=None, **kwargs): """Make a direct connection, and authenticate if necessary.""" - return _mongo_client(h, p, direct=True, **kwargs) + return _mongo_client(h, p, directConnection=True, **kwargs) def rs_client_noauth(h=None, p=None, **kwargs):