diff --git a/pymongo/database.py b/pymongo/database.py index 11d7e6c1d..95d0934e7 100644 --- a/pymongo/database.py +++ b/pymongo/database.py @@ -787,8 +787,9 @@ class Database(common.BaseObject): # users. if exc.code in common.COMMAND_NOT_FOUND_CODES: self._legacy_add_user(name, password, read_only, **kwargs) - # Unauthorized. MongoDB >= 2.7.1 has a narrow localhost exception, - # and we must add a user before sending commands. + return + # Unauthorized. Attempt to create the user in case of + # localhost exception. elif exc.code == 13: self._create_or_update_user( True, name, password, read_only, **kwargs) diff --git a/test/__init__.py b/test/__init__.py index 5fec799e5..69b50e187 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -45,6 +45,9 @@ port2 = int(os.environ.get("DB_PORT2", 27018)) host3 = _unicode(os.environ.get("DB_IP3", 'localhost')) port3 = int(os.environ.get("DB_PORT3", 27019)) +db_user = _unicode(os.environ.get("DB_USER", "user")) +db_pwd = _unicode(os.environ.get("DB_PASSWORD", "password")) + class ClientContext(object): @@ -70,12 +73,31 @@ class ClientContext(object): self.w = len(self.ismaster.get("hosts", [])) or 1 self.setname = self.ismaster.get('setName', '') self.rs_client = None + self.version = Version.from_client(self.client) if self.setname: self.rs_client = pymongo.MongoReplicaSetClient( pair, replicaSet=self.setname) - self.cmd_line = self.client.admin.command('getCmdLineOpts') - self.version = Version.from_client(self.client) - self.auth_enabled = self._server_started_with_auth() + try: + self.cmd_line = self.client.admin.command('getCmdLineOpts') + except pymongo.errors.OperationFailure as e: + if e.code == 13: + # Unauthorized. + self.auth_enabled = True + else: + raise + else: + self.auth_enabled = self._server_started_with_auth() + if self.auth_enabled: + roles = {} + if self.version.at_least(2, 5, 3, -1): + roles = {'roles': ['root']} + self.client.admin.add_user(db_user, db_pwd, **roles) + self.client.admin.authenticate(db_user, db_pwd) + if self.rs_client: + self.rs_client.admin.authenticate(db_user, db_pwd) + self.cmd_line = self.client.admin.command('getCmdLineOpts') + # May not have this if OperationFailure was raised earlier. + self.cmd_line = self.client.admin.command('getCmdLineOpts') self.test_commands_enabled = ('testCommandsEnabled=1' in self.cmd_line['argv']) self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid') @@ -143,6 +165,12 @@ class ClientContext(object): "Authentication is not enabled on the server", func=func)) + def require_no_auth(self, func): + """Run a test only if the server is running without auth enabled.""" + return self._require(not self.auth_enabled, + "Authentication must not be enabled on the server", + func=func) + def require_replica_set(self, func): """Run a test only if the client is connected to a replica set.""" return self._require(self.rs_client is not None, @@ -183,25 +211,27 @@ class IntegrationTest(unittest.TestCase): pass +def connection_string(seeds=[pair]): + if client_context.auth_enabled: + return "mongodb://%s:%s@%s" % (db_user, db_pwd, ','.join(seeds)) + return "mongodb://%s" % pair + + def setup(): warnings.resetwarnings() warnings.simplefilter("always") def teardown(): - try: - c = pymongo.MongoClient(host, port) - except pymongo.errors.ConnectionFailure: - # Tests where ssl=True can cause connection failures here. - # Ignore and continue. - return - + c = client_context.client c.drop_database("pymongo-pooling-tests") c.drop_database("pymongo_test") c.drop_database("pymongo_test1") c.drop_database("pymongo_test2") c.drop_database("pymongo_test_mike") c.drop_database("pymongo_test_bernie") + if client_context.auth_enabled: + c.admin.remove_user(db_user) class PymongoTestRunner(unittest.TextTestRunner): diff --git a/test/test_auth.py b/test/test_auth.py index 428aff823..a52565a7e 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -235,10 +235,11 @@ class TestAuthURIOptions(unittest.TestCase): client = MongoClient(host, port) response = client.admin.command('ismaster') self.set_name = str(response.get('setName', '')) - client.admin.add_user('admin', 'pass', roles=['userAdminAnyDatabase', - 'dbAdminAnyDatabase', - 'readWriteAnyDatabase', - 'clusterAdmin']) + client_context.client.admin.add_user('admin', 'pass', + roles=['userAdminAnyDatabase', + 'dbAdminAnyDatabase', + 'readWriteAnyDatabase', + 'clusterAdmin']) client.admin.authenticate('admin', 'pass') client.pymongo_test.add_user('user', 'pass', roles=['userAdmin', 'readWrite']) @@ -314,26 +315,14 @@ class TestDelegatedAuth(unittest.TestCase): @client_context.require_version_max(2, 5, 3) @client_context.require_version_min(2, 4, 0) def setUp(self): - self.client = MongoClient(host, port) - # Give admin all privileges. - self.client.admin.add_user('admin', 'pass', - roles=['readAnyDatabase', - 'readWriteAnyDatabase', - 'userAdminAnyDatabase', - 'dbAdminAnyDatabase', - 'clusterAdmin']) + self.client = client_context.client def tearDown(self): - self.client.admin.authenticate('admin', 'pass') self.client.pymongo_test.remove_user('user') self.client.pymongo_test2.remove_user('user') - self.client.pymongo_test2.foo.remove() - self.client.admin.remove_user('admin') - self.client.admin.logout() - self.client = None + self.client.pymongo_test2.foo.drop() def test_delegated_auth(self): - self.client.admin.authenticate('admin', 'pass') self.client.pymongo_test2.foo.remove() self.client.pymongo_test2.foo.insert({}) # User definition with no roles in pymongo_test. @@ -342,27 +331,27 @@ class TestDelegatedAuth(unittest.TestCase): self.client.pymongo_test2.add_user('user', userSource='pymongo_test', roles=['read']) - self.client.admin.logout() + auth_c = MongoClient(host, port) self.assertRaises(OperationFailure, - self.client.pymongo_test2.foo.find_one) + auth_c.pymongo_test2.foo.find_one) # Auth must occur on the db where the user is defined. self.assertRaises(OperationFailure, - self.client.pymongo_test2.authenticate, + auth_c.pymongo_test2.authenticate, 'user', 'pass') # Auth directly - self.assertTrue(self.client.pymongo_test.authenticate('user', 'pass')) - self.assertTrue(self.client.pymongo_test2.foo.find_one()) - self.client.pymongo_test.logout() + self.assertTrue(auth_c.pymongo_test.authenticate('user', 'pass')) + self.assertTrue(auth_c.pymongo_test2.foo.find_one()) + auth_c.pymongo_test.logout() self.assertRaises(OperationFailure, - self.client.pymongo_test2.foo.find_one) + auth_c.pymongo_test2.foo.find_one) # Auth using source - self.assertTrue(self.client.pymongo_test2.authenticate( + self.assertTrue(auth_c.pymongo_test2.authenticate( 'user', 'pass', source='pymongo_test')) - self.assertTrue(self.client.pymongo_test2.foo.find_one()) + self.assertTrue(auth_c.pymongo_test2.foo.find_one()) # Must logout from the db authenticate was called on. - self.client.pymongo_test2.logout() + auth_c.pymongo_test2.logout() self.assertRaises(OperationFailure, - self.client.pymongo_test2.foo.find_one) + auth_c.pymongo_test2.foo.find_one) if __name__ == "__main__": diff --git a/test/test_bulk.py b/test/test_bulk.py index fbb673bca..5cf070e64 100644 --- a/test/test_bulk.py +++ b/test/test_bulk.py @@ -20,8 +20,9 @@ sys.path[0:0] = [""] from bson import InvalidDocument, SON from bson.py3compat import string_type +from pymongo import MongoClient from pymongo.errors import BulkWriteError, InvalidOperation, OperationFailure -from test import client_context, unittest +from test import client_context, unittest, host, port from test.utils import oid_generated_on_client, remove_all_users @@ -1151,8 +1152,6 @@ class TestBulkAuthorization(BulkTestBase): super(TestBulkAuthorization, self).setUp() self.coll.remove() - self.db.add_user('dbOwner', 'pw', roles=['dbOwner']) - self.db.authenticate('dbOwner', 'pw') self.db.add_user('readonly', 'pw', roles=['read']) self.db.command( 'createRole', 'noremove', @@ -1163,31 +1162,30 @@ class TestBulkAuthorization(BulkTestBase): roles=[]) self.db.add_user('noremove', 'pw', roles=['noremove']) - self.db.logout() def tearDown(self): - self.db.logout() - self.db.authenticate('dbOwner', 'pw') self.db.command('dropRole', 'noremove') remove_all_users(self.db) - self.db.logout() - self.db.connection.disconnect() def test_readonly(self): # We test that an authorization failure aborts the batch and is raised # as OperationFailure. - db = client_context.client.pymongo_test + cli = MongoClient(host, port) + db = cli.pymongo_test + coll = db.test db.authenticate('readonly', 'pw') - bulk = self.coll.initialize_ordered_bulk_op() + bulk = coll.initialize_ordered_bulk_op() bulk.insert({'x': 1}) self.assertRaises(OperationFailure, bulk.execute) def test_no_remove(self): # We test that an authorization failure aborts the batch and is raised # as OperationFailure. - db = client_context.client.pymongo_test + cli = MongoClient(host, port) + db = cli.pymongo_test + coll = db.test db.authenticate('noremove', 'pw') - bulk = self.coll.initialize_ordered_bulk_op() + bulk = coll.initialize_ordered_bulk_op() bulk.insert({'x': 1}) bulk.find({'x': 2}).upsert().replace_one({'x': 2}) bulk.find({}).remove() # Prohibited. @@ -1195,6 +1193,5 @@ class TestBulkAuthorization(BulkTestBase): self.assertRaises(OperationFailure, bulk.execute) self.assertEqual(set([1, 2]), set(self.coll.distinct('x'))) - if __name__ == "__main__": unittest.main() diff --git a/test/test_client.py b/test/test_client.py index a4dd990bb..d6d559eae 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -29,7 +29,7 @@ from bson.tz_util import utc from pymongo.mongo_client import MongoClient from pymongo.database import Database from pymongo.pool import SocketInfo -from pymongo import thread_util, common +from pymongo import thread_util from pymongo.errors import (AutoReconnect, ConfigurationError, ConnectionFailure, @@ -37,6 +37,7 @@ from pymongo.errors import (AutoReconnect, OperationFailure, PyMongoError) from test import (client_context, + connection_string, host, pair, port, @@ -46,6 +47,7 @@ from test import (client_context, from test.pymongo_mocks import MockClient from test.utils import (assertRaisesExactly, delay, + get_client, remove_all_users, server_is_master_with_slave, TestRequestMixin, @@ -55,13 +57,7 @@ from test.utils import (assertRaisesExactly, get_pool) -def get_client(*args, **kwargs): - return MongoClient(host, port, *args, **kwargs) - - -class TestClientNoConnect(unittest.TestCase): - """MongoClient unit tests that don't require connecting to MongoDB.""" - +class TestClient(unittest.TestCase, TestRequestMixin): @classmethod def setUpClass(cls): cls.client = MongoClient(host, port, _connect=False) @@ -158,7 +154,7 @@ class TestClient(IntegrationTest, TestRequestMixin): self.assertEqual(None, c.host) self.assertEqual(None, c.port) - c.pymongo_test.test.find_one() # Auto-connect. + c.pymongo_test.command('ismaster') # Auto-connect. self.assertEqual(host, c.host) self.assertEqual(port, c.port) @@ -282,8 +278,8 @@ class TestClient(IntegrationTest, TestRequestMixin): c.end_request() self.assertFalse(c.in_request()) - c.copy_database("pymongo_test", "pymongo_test2", - "%s:%d" % (host, port)) + + c.copy_database("pymongo_test", "pymongo_test2") # copy_database() didn't accidentally restart the request self.assertFalse(c.in_request()) @@ -295,30 +291,30 @@ class TestClient(IntegrationTest, TestRequestMixin): c.drop_database("pymongo_test1") c.admin.add_user("admin", "password") - c.admin.authenticate("admin", "password") + auth_c = MongoClient(host, port) + auth_c.admin.authenticate("admin", "password") try: - c.pymongo_test.add_user("mike", "password") + auth_c.pymongo_test.add_user("mike", "password") - self.assertRaises(OperationFailure, c.copy_database, + self.assertRaises(OperationFailure, auth_c.copy_database, "pymongo_test", "pymongo_test1", username="foo", password="bar") - self.assertFalse("pymongo_test1" in c.database_names()) + self.assertFalse("pymongo_test1" in auth_c.database_names()) - self.assertRaises(OperationFailure, c.copy_database, + self.assertRaises(OperationFailure, auth_c.copy_database, "pymongo_test", "pymongo_test1", username="mike", password="bar") - self.assertFalse("pymongo_test1" in c.database_names()) + self.assertFalse("pymongo_test1" in auth_c.database_names()) - c.copy_database("pymongo_test", "pymongo_test1", - username="mike", password="password") - self.assertTrue("pymongo_test1" in c.database_names()) - self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"]) + auth_c.copy_database("pymongo_test", "pymongo_test1", + username="mike", password="password") + self.assertTrue("pymongo_test1" in auth_c.database_names()) + self.assertEqual("bar", + auth_c.pymongo_test1.test.find_one()["foo"]) finally: # Cleanup remove_all_users(c.pymongo_test) c.admin.remove_user("admin") - c.admin.logout() - c.disconnect() def test_disconnect(self): coll = self.client.pymongo_test.bar @@ -340,7 +336,6 @@ class TestClient(IntegrationTest, TestRequestMixin): @client_context.require_auth def test_auth_from_uri(self): self.client.admin.add_user("admin", "pass") - self.client.admin.authenticate("admin", "pass") try: self.client.pymongo_test.add_user( "user", "pass", roles=['userAdmin', 'readWrite']) @@ -378,9 +373,7 @@ class TestClient(IntegrationTest, TestRequestMixin): finally: # Clean up. remove_all_users(self.client.pymongo_test) - remove_all_users(self.client.admin) - self.client.admin.logout() - self.client.disconnect() + self.client.admin.remove_user('admin') @client_context.require_auth def test_lazy_auth_raises_operation_failure(self): @@ -394,7 +387,9 @@ class TestClient(IntegrationTest, TestRequestMixin): def test_unix_socket(self): if not hasattr(socket, "AF_UNIX"): raise SkipTest("UNIX-sockets are not supported on this system") - if sys.platform == 'darwin' and client_context.auth_enabled: + if (sys.platform == 'darwin' and + client_context.auth_enabled and + not client_context.version.at_least(2, 7, 1)): raise SkipTest("SERVER-8492") mongodb_socket = '/tmp/mongodb-27017.sock' @@ -491,7 +486,7 @@ class TestClient(IntegrationTest, TestRequestMixin): finally: c.document_class = dict - c = MongoClient(host, port, document_class=SON) + c = get_client(pair, document_class=SON) db = c.pymongo_test self.assertEqual(SON, c.document_class) @@ -511,29 +506,28 @@ class TestClient(IntegrationTest, TestRequestMixin): self.assertEqual(10.5, get_pool(client).opts.socket_timeout) def test_socket_timeout_ms_validation(self): - c = get_client(socketTimeoutMS=10 * 1000) + c = get_client(pair, socketTimeoutMS=10 * 1000) self.assertEqual(10, c._MongoClient__pool_opts.socket_timeout) - c = get_client(socketTimeoutMS=None) + c = get_client(pair, socketTimeoutMS=None) self.assertEqual(None, c._MongoClient__pool_opts.socket_timeout) self.assertRaises(ConfigurationError, - get_client, socketTimeoutMS=0) + get_client, pair, socketTimeoutMS=0) self.assertRaises(ConfigurationError, - get_client, socketTimeoutMS=-1) + get_client, pair, socketTimeoutMS=-1) self.assertRaises(ConfigurationError, - get_client, socketTimeoutMS=1e10) + get_client, pair, socketTimeoutMS=1e10) self.assertRaises(ConfigurationError, - get_client, socketTimeoutMS='foo') + get_client, pair, socketTimeoutMS='foo') def test_socket_timeout(self): no_timeout = self.client timeout_sec = 1 - timeout = MongoClient( - host, port, socketTimeoutMS=1000 * timeout_sec) + timeout = get_client(pair, socketTimeoutMS=1000 * timeout_sec) no_timeout.pymongo_test.drop_collection("test") no_timeout.pymongo_test.test.insert({"x": 1}) @@ -560,7 +554,7 @@ class TestClient(IntegrationTest, TestRequestMixin): def test_tz_aware(self): self.assertRaises(ConfigurationError, MongoClient, tz_aware='foo') - aware = MongoClient(host, port, tz_aware=True) + aware = get_client(pair, tz_aware=True) naive = self.client aware.pymongo_test.drop_collection("test") @@ -622,7 +616,7 @@ class TestClient(IntegrationTest, TestRequestMixin): def test_contextlib(self): import contextlib - client = get_client(auto_start_request=False) + client = get_client(pair, auto_start_request=False) client.pymongo_test.drop_collection("test") client.pymongo_test.test.insert({"foo": "bar"}) @@ -675,13 +669,13 @@ class TestClient(IntegrationTest, TestRequestMixin): for bad_horrible_value in (None, 5, 'hi!'): self.assertRaises( (TypeError, ConfigurationError), - lambda: get_client(auto_start_request=bad_horrible_value) + lambda: get_client(pair, auto_start_request=bad_horrible_value) ) # auto_start_request should default to False self.assertFalse(self.client.auto_start_request) - client = get_client(auto_start_request=True) + client = get_client(pair, auto_start_request=True) self.assertTrue(client.auto_start_request) # Assure we acquire a request socket. @@ -834,7 +828,7 @@ class TestClient(IntegrationTest, TestRequestMixin): def test_operation_failure_with_request(self): # Ensure MongoClient doesn't close socket after it gets an error # response to getLastError. PYTHON-395. - c = get_client(auto_start_request=True) + c = get_client(pair, auto_start_request=True) pool = get_pool(c) # Pool reserves a socket for this thread. @@ -867,7 +861,7 @@ class TestClient(IntegrationTest, TestRequestMixin): _connect=False) c.set_wire_version_range('a:1', 1, 5) - c.db.collection.find_one() # Connect. + c.db.command('ismaster') # Connect. self.assertEqual(c.min_wire_version, 1) self.assertEqual(c.max_wire_version, 5) @@ -889,7 +883,7 @@ class TestClient(IntegrationTest, TestRequestMixin): # Starts with default max batch size. self.assertEqual(1000, c.max_write_batch_size) - c.db.collection.find_one() # Connect. + c.db.command('ismaster') # Connect. # Uses primary's max batch size. self.assertEqual(c.max_write_batch_size, 1) @@ -897,7 +891,7 @@ class TestClient(IntegrationTest, TestRequestMixin): c.mock_primary = 'b:2' c.disconnect() self.assertEqual(1000, c.max_write_batch_size) - c.db.collection.find_one() # Connect. + c.db.command('ismaster') # Connect. self.assertEqual(c.max_write_batch_size, 2) def test_wire_version_mongos_ha(self): @@ -911,7 +905,7 @@ class TestClient(IntegrationTest, TestRequestMixin): c.set_wire_version_range('a:1', 2, 5) c.set_wire_version_range('b:2', 2, 2) c.set_wire_version_range('c:3', 1, 1) - c.db.collection.find_one() # Connect. + c.db.command('ismaster') # Connect. # Which member did we use? used_host = '%s:%s' % (c.host, c.port) @@ -923,7 +917,7 @@ class TestClient(IntegrationTest, TestRequestMixin): c.set_wire_version_range('b:2', 0, 0) c.set_wire_version_range('c:3', 0, 0) c.disconnect() - c.db.collection.find_one() + c.db.command('ismaster') used_host = '%s:%s' % (c.host, c.port) expected_min, expected_max = c.mock_wire_versions[used_host] self.assertEqual(expected_min, c.min_wire_version) @@ -939,20 +933,20 @@ class TestClient(IntegrationTest, TestRequestMixin): MongoClient, host, port, replicaSet='bad' + name) def test_lazy_connect_w0(self): - client = get_client(_connect=False) + client = get_client(connection_string(), _connect=False) client.pymongo_test.test.insert({}, w=0) - client = get_client(_connect=False) + client = get_client(connection_string(), _connect=False) client.pymongo_test.test.update({}, {'$set': {'x': 1}}, w=0) - client = get_client(_connect=False) + client = get_client(connection_string(), _connect=False) client.pymongo_test.test.remove(w=0) class TestClientLazyConnect(IntegrationTest, _TestLazyConnectMixin): def _get_client(self, **kwargs): - return get_client(**kwargs) + return get_client(connection_string(), **kwargs) class TestClientLazyConnectBadSeeds(IntegrationTest): @@ -962,7 +956,7 @@ class TestClientLazyConnectBadSeeds(IntegrationTest): # Assume there are no open mongods listening on a.com, b.com, .... bad_seeds = ['%s.com' % chr(ord('a') + i) for i in range(10)] - return MongoClient(bad_seeds, **kwargs) + return get_client(bad_seeds, **kwargs) def test_connect(self): def reset(dummy): @@ -993,7 +987,7 @@ class TestClientLazyConnectOneGoodSeed( # MongoClient puts the seeds in a set before iterating, so order is # undefined. - return MongoClient(seeds, **kwargs) + return get_client(connection_string(seeds=seeds), **kwargs) def test_insert(self): def reset(collection): @@ -1030,7 +1024,7 @@ class TestMongoClientFailover(IntegrationTest): # Force reconnect. c.disconnect() - c.db.collection.find_one() + c.db.command('ismaster') self.assertEqual('b', c.host) self.assertEqual(2, c.port) @@ -1059,7 +1053,7 @@ class TestMongoClientFailover(IntegrationTest): # So it can reconnect. c.revive_host('a:1') - c.db.collection.find_one() + c.db.command('ismaster') if __name__ == "__main__": diff --git a/test/test_collection.py b/test/test_collection.py index 938509ca9..805163df2 100644 --- a/test/test_collection.py +++ b/test/test_collection.py @@ -39,7 +39,6 @@ from pymongo import message as message_module from pymongo import MongoClient from pymongo.collection import Collection from pymongo.command_cursor import CommandCursor -from pymongo.database import Database from pymongo.read_preferences import ReadPreference from pymongo.son_manipulator import SONManipulator from pymongo.errors import (DocumentTooLarge, @@ -52,7 +51,7 @@ from pymongo.errors import (DocumentTooLarge, from test.test_client import get_client, IntegrationTest from test.utils import (is_mongos, joinall, enable_text_search, get_pool, oid_generated_on_client) -from test import client_context, host, port, qcheck, unittest +from test import client_context, host, port, pair, qcheck, unittest class TestCollectionNoConnect(unittest.TestCase): @@ -1715,7 +1714,7 @@ class TestCollection(IntegrationTest): # Insert enough documents to require more than one batch self.db.test.insert([{'i': i} for i in range(150)]) - client = get_client(max_pool_size=1) + client = get_client(pair, max_pool_size=1) socks = get_pool(client).sockets self.assertEqual(1, len(socks)) diff --git a/test/test_common.py b/test/test_common.py index 697fa6a24..a27588709 100644 --- a/test/test_common.py +++ b/test/test_common.py @@ -27,6 +27,7 @@ from pymongo.mongo_client import MongoClient from pymongo.mongo_replica_set_client import MongoReplicaSetClient from pymongo.errors import ConfigurationError, OperationFailure from test import client_context, pair, unittest +from test.utils import get_client, get_rs_client @client_context.require_connection @@ -208,7 +209,7 @@ class TestCommon(unittest.TestCase): self.assertEqual(wc.to_dict(), coll.write_concern) def test_mongo_client(self): - m = MongoClient(pair, w=0) + m = get_client(pair, w=0) coll = m.pymongo_test.write_concern_test coll.drop() doc = {"_id": ObjectId()} @@ -217,16 +218,16 @@ class TestCommon(unittest.TestCase): self.assertTrue(coll.insert(doc)) self.assertRaises(OperationFailure, coll.insert, doc, w=1) - m = MongoClient(pair) + m = get_client(pair) coll = m.pymongo_test.write_concern_test self.assertTrue(coll.insert(doc, w=0)) self.assertRaises(OperationFailure, coll.insert, doc) self.assertRaises(OperationFailure, coll.insert, doc, w=1) - m = MongoClient("mongodb://%s/" % (pair,)) + m = get_client("mongodb://%s/" % (pair,)) coll = m.pymongo_test.write_concern_test self.assertRaises(OperationFailure, coll.insert, doc) - m = MongoClient("mongodb://%s/?w=0" % (pair,)) + m = get_client("mongodb://%s/?w=0" % (pair,)) coll = m.pymongo_test.write_concern_test self.assertTrue(coll.insert(doc)) @@ -237,7 +238,7 @@ class TestCommon(unittest.TestCase): @client_context.require_replica_set def test_mongo_replica_set_client(self): setname = client_context.setname - m = MongoReplicaSetClient(pair, replicaSet=setname, w=0) + m = get_rs_client(pair, replicaSet=setname, w=0) coll = m.pymongo_test.write_concern_test coll.drop() doc = {"_id": ObjectId()} diff --git a/test/test_database.py b/test/test_database.py index f0698ceb7..ef779d284 100644 --- a/test/test_database.py +++ b/test/test_database.py @@ -46,7 +46,13 @@ from pymongo.son_manipulator import (AutoReference, NamespaceInjector, SONManipulator, ObjectIdShuffler) -from test import client_context, SkipTest, unittest, host, port, IntegrationTest +from test import (client_context, + SkipTest, + unittest, + host, + port, + pair, + IntegrationTest) from test.utils import remove_all_users, server_started_with_auth from test.test_client import get_client @@ -378,7 +384,9 @@ class TestDatabase(IntegrationTest): "user", "password", digestPassword=True) self.client.admin.add_user("admin", "password") - self.client.admin.authenticate("admin", "password") + auth_c = MongoClient(pair) + auth_c.admin.authenticate("admin", "password") + db = auth_c.pymongo_test try: # Add / authenticate / remove @@ -420,18 +428,17 @@ class TestDatabase(IntegrationTest): # Cleanup finally: remove_all_users(db) - self.client.pymongo_test.logout() - self.client.admin.remove_user("admin") - self.client.admin.logout() - self.client.disconnect() + db.logout() + auth_c.admin.remove_user("admin") @client_context.require_auth def test_make_user_readonly(self): - admin = self.client.admin - admin.add_user('admin', 'pw') + auth_c = MongoClient(pair) + admin = auth_c.admin + self.client.admin.add_user('admin', 'pw') admin.authenticate('admin', 'pw') - db = self.client.pymongo_test + db = auth_c.pymongo_test try: # Make a read-write user. @@ -455,16 +462,14 @@ class TestDatabase(IntegrationTest): admin.authenticate('admin', 'pw') remove_all_users(db) admin.remove_user("admin") - admin.logout() - db.logout() - self.client.disconnect() @client_context.require_version_min(2, 5, 3, -1) @client_context.require_auth def test_default_roles(self): # "Admin" user - db = self.client.admin - db.add_user('admin', 'pass') + self.client.admin.add_user('admin', 'pass') + auth_c = MongoClient(pair) + db = auth_c.admin try: db.authenticate('admin', 'pass') info = db.command('usersInfo', 'admin')['users'][0] @@ -481,22 +486,24 @@ class TestDatabase(IntegrationTest): # Cleanup finally: db.authenticate('admin', 'pass') - remove_all_users(db) + db.remove_user('ro-admin') + db.remove_user('admin') db.logout() db.connection.disconnect() # "Non-admin" user - db = self.client.pymongo_test - db.add_user('user', 'pass') + db = auth_c.pymongo_test + client_context.client.pymongo_test.add_user('user', 'pass') try: db.authenticate('user', 'pass') info = db.command('usersInfo', 'user')['users'][0] self.assertEqual("dbOwner", info['roles'][0]['role']) + db.logout() # Read only "Non-admin" user - db.add_user('ro-user', 'pass', read_only=True) - db.logout() + client_context.client.pymongo_test.add_user('ro-user', 'pass', + read_only=True) db.authenticate('ro-user', 'pass') info = db.command('usersInfo', 'ro-user')['users'][0] self.assertEqual("read", info['roles'][0]['role']) @@ -506,14 +513,15 @@ class TestDatabase(IntegrationTest): finally: db.authenticate('user', 'pass') remove_all_users(db) - db.logout() - self.client.disconnect() @client_context.require_version_min(2, 5, 3, -1) @client_context.require_auth def test_new_user_cmds(self): - db = self.client.pymongo_test - db.add_user("amalia", "password", roles=["userAdmin"]) + auth_c = MongoClient(pair) + db = auth_c.pymongo_test + client_context.client.pymongo_test.add_user("amalia", "password", + roles=["userAdmin"]) + db.authenticate("amalia", "password") try: # This tests the ability to update user attributes. @@ -527,15 +535,15 @@ class TestDatabase(IntegrationTest): self.assertEqual(amalia_user["customData"], {"secret": "koalas"}) finally: db.remove_user("amalia") - db.logout() - self.client.disconnect() @client_context.require_auth def test_authenticate_and_safe(self): - db = self.client.auth_test + auth_c = MongoClient(pair) + db = auth_c.auth_test - db.add_user("bernie", "password", - roles=["userAdmin", "dbAdmin", "readWrite"]) + client_context.client.auth_test.add_user( + "bernie", "password", + roles=["userAdmin", "dbAdmin", "readWrite"]) db.authenticate("bernie", "password") try: db.test.remove({}) @@ -552,8 +560,6 @@ class TestDatabase(IntegrationTest): self.assertEqual(0, db.test.count()) finally: db.remove_user("bernie") - db.logout() - self.client.disconnect() @client_context.require_auth def test_authenticate_and_request(self): @@ -561,37 +567,38 @@ class TestDatabase(IntegrationTest): # always runs in a request, and that it restores the request state # (in or not in a request) properly when it's finished. self.assertFalse(self.client.auto_start_request) - db = self.client.pymongo_test - db.add_user("mike", "password", - roles=["userAdmin", "dbAdmin", "readWrite"]) + auth_c = MongoClient(pair) + db = auth_c.pymongo_test + client_context.client.pymongo_test.add_user( + "mike", "password", + roles=["userAdmin", "dbAdmin", "readWrite"]) try: - self.assertFalse(self.client.in_request()) + self.assertFalse(auth_c.in_request()) self.assertTrue(db.authenticate("mike", "password")) - self.assertFalse(self.client.in_request()) + self.assertFalse(auth_c.in_request()) - request_cx = get_client(auto_start_request=True) + request_cx = get_client(pair, auto_start_request=True) request_db = request_cx.pymongo_test self.assertTrue(request_db.authenticate("mike", "password")) self.assertTrue(request_cx.in_request()) finally: db.authenticate("mike", "password") db.remove_user("mike") - db.logout() - request_db.logout() - self.client.disconnect() @client_context.require_auth def test_authenticate_multiple(self): # Setup - users_db = self.client.pymongo_test - admin_db = self.client.admin - other_db = self.client.pymongo_test1 - users_db.test.remove() - other_db.test.remove() + client_context.client.drop_database("pymongo_test") + client_context.client.drop_database("pymongo_test1") + auth_c = MongoClient(pair) + users_db = auth_c.pymongo_test + admin_db = auth_c.admin + other_db = auth_c.pymongo_test1 - admin_db.add_user('admin', 'pass', - roles=["userAdminAnyDatabase", "dbAdmin", - "clusterAdmin", "readWrite"]) + client_context.client.admin.add_user( + 'admin', 'pass', + roles=["userAdminAnyDatabase", "dbAdmin", + "clusterAdmin", "readWrite"]) try: self.assertTrue(admin_db.authenticate('admin', 'pass')) @@ -621,7 +628,7 @@ class TestDatabase(IntegrationTest): other_db.test.insert, {}) # Force close all sockets - self.client.disconnect() + auth_c.disconnect() # We should still be able to write to the regular user's db self.assertTrue(users_db.test.remove()) @@ -634,10 +641,8 @@ class TestDatabase(IntegrationTest): # Cleanup finally: remove_all_users(users_db) - remove_all_users(admin_db) - admin_db.logout() - users_db.logout() - self.client.disconnect() + client_context.client.admin.remove_user('ro-admin') + client_context.client.admin.remove_user('admin') def test_id_ordering(self): # PyMongo attempts to have _id show up first @@ -679,6 +684,7 @@ class TestDatabase(IntegrationTest): db.test.save(obj) self.assertEqual(obj, db.dereference(DBRef("test", 4))) + @client_context.require_no_auth def test_eval(self): db = self.client.pymongo_test db.test.remove({}) @@ -843,6 +849,7 @@ class TestDatabase(IntegrationTest): self.assertEqual("buzz", db.users.find_one()["messages"][0]["title"]) self.assertEqual("bar", db.users.find_one()["messages"][1]["title"]) + @client_context.require_no_auth def test_system_js(self): db = self.client.pymongo_test db.system.js.remove() diff --git a/test/test_gridfs.py b/test/test_gridfs.py index 019cb2e1a..fde86dc87 100644 --- a/test/test_gridfs.py +++ b/test/test_gridfs.py @@ -32,8 +32,13 @@ import gridfs from bson.py3compat import u, StringIO, string_type from gridfs.errors import (FileExists, NoFile) -from test import client_context, unittest, host, port, IntegrationTest -from test.utils import joinall +from test import (client_context, + connection_string, + unittest, + host, + port, + IntegrationTest) +from test.utils import joinall, get_client class JustWrite(threading.Thread): @@ -418,29 +423,30 @@ class TestGridfsReplicaSet(TestReplicaSetClientBase): def test_gridfs_secondary(self): primary_host, primary_port = self.primary - primary_connection = MongoClient(primary_host, primary_port) + primary_connection = get_client(primary_host, primary_port) secondary_host, secondary_port = self.secondaries[0] - for secondary_connection in [ - MongoClient(secondary_host, secondary_port, - read_preference=ReadPreference.SECONDARY), - ]: - primary_connection.pymongo_test.drop_collection("fs.files") - primary_connection.pymongo_test.drop_collection("fs.chunks") + secondary_connection = get_client( + secondary_host, secondary_port, + read_preference=ReadPreference.SECONDARY) - # Should detect it's connected to secondary and not attempt to - # create index - fs = gridfs.GridFS(secondary_connection.pymongo_test) + primary_connection.pymongo_test.drop_collection("fs.files") + primary_connection.pymongo_test.drop_collection("fs.chunks") - # This won't detect secondary, raises error - self.assertRaises(ConnectionFailure, fs.put, b'foo') + # Should detect it's connected to secondary and not attempt to + # create index + fs = gridfs.GridFS(secondary_connection.pymongo_test) + + # This won't detect secondary, raises error + self.assertRaises(ConnectionFailure, fs.put, b'foo') def test_gridfs_secondary_lazy(self): # Should detect it's connected to secondary and not attempt to # create index. secondary_host, secondary_port = self.secondaries[0] + secondary_pair = '%s:%d' % (secondary_host, secondary_port) client = MongoClient( - secondary_host, secondary_port, + connection_string(seeds=[secondary_pair]), read_preference=ReadPreference.SECONDARY, _connect=False) diff --git a/test/test_mongos_ha.py b/test/test_mongos_ha.py index 6764ee4b3..3b9f86a8a 100644 --- a/test/test_mongos_ha.py +++ b/test/test_mongos_ha.py @@ -29,19 +29,20 @@ def setUpModule(): pass -class FindOne(threading.Thread): +class SimpleOp(threading.Thread): + def __init__(self, client): - super(FindOne, self).__init__() + super(SimpleOp, self).__init__() self.client = client self.passed = False def run(self): - self.client.db.collection.find_one() + self.client.db.command('ismaster') self.passed = True # No exception raised. -def do_find_one(client, nthreads): - threads = [FindOne(client) for _ in range(nthreads)] +def do_simple_op(client, nthreads): + threads = [SimpleOp(client) for _ in range(nthreads)] for t in threads: t.start() @@ -67,7 +68,7 @@ class TestMongosHA(unittest.TestCase): self.assertEqual(0, len(client.nodes)) # Trigger initial connection. - do_find_one(client, nthreads) + do_simple_op(client, nthreads) self.assertEqual(3, len(client.nodes)) def test_reconnect(self): @@ -77,7 +78,7 @@ class TestMongosHA(unittest.TestCase): # Trigger reconnect. client.disconnect() - do_find_one(client, nthreads) + do_simple_op(client, nthreads) self.assertEqual(3, len(client.nodes)) def test_failover(self): @@ -102,12 +103,12 @@ class TestMongosHA(unittest.TestCase): def f(): try: - client.db.collection.find_one() + client.db.command('ismaster') except AutoReconnect: errors.append(True) # Second attempt succeeds. - client.db.collection.find_one() + client.db.command('ismaster') passed.append(True) diff --git a/test/test_pooling_base.py b/test/test_pooling_base.py index c2f5d9b4f..fe6ed85d8 100644 --- a/test/test_pooling_base.py +++ b/test/test_pooling_base.py @@ -345,7 +345,7 @@ class _TestPoolingBase(object): def get_client(self, *args, **kwargs): opts = kwargs.copy() opts['use_greenlets'] = self.use_greenlets - return get_client(*args, **opts) + return get_client(host, port, *args, **opts) def get_pool(self, pair, *args, **kwargs): kwargs['use_greenlets'] = self.use_greenlets @@ -1156,6 +1156,7 @@ class _TestPoolSocketSharing(_TestPoolingBase): gr0: get results """ cx = get_client( + host, port, use_greenlets=self.use_greenlets, auto_start_request=False ) @@ -1189,16 +1190,7 @@ class _TestPoolSocketSharing(_TestPoolingBase): # Javascript function that pauses N seconds per document fn = delay(10) - if (is_mongos(db.connection) or not - Version.from_client(db.connection).at_least(1, 7, 2)): - # mongos doesn't support eval so we have to use $where - # which is less reliable in this context. - self.assertEqual(1, db.test.find({"$where": fn}).count()) - else: - # 'nolock' allows find_fast to start and finish while we're - # waiting for this to complete. - self.assertEqual({'ok': 1.0, 'retval': True}, - db.command('eval', fn, nolock=True)) + self.assertEqual(1, db.test.find({"$where": fn}).count()) history.append('find_slow done') diff --git a/test/test_read_preferences.py b/test/test_read_preferences.py index b0609e6f3..d71cfaf67 100644 --- a/test/test_read_preferences.py +++ b/test/test_read_preferences.py @@ -38,7 +38,9 @@ from test import (client_context, SkipTest, unittest, utils, - IntegrationTest) + IntegrationTest, + db_user, + db_pwd) from test.version import Version @@ -212,6 +214,8 @@ class TestCommandAndReadPreference(TestReplicaSetClientBase): # Effectively ignore members' ping times so we can test the effect # of ReadPreference modes only latencyThresholdMS=1000*1000) + if client_context.auth_enabled: + self.c.admin.authenticate(db_user, db_pwd) self.client_version = Version.from_client(self.c) def tearDown(self): @@ -516,7 +520,7 @@ class TestMovingAverage(unittest.TestCase): class TestMongosConnection(IntegrationTest): def test_mongos_connection(self): - c = get_client() + c = get_client(host, port) is_mongos = utils.is_mongos(c) # Test default mode, PRIMARY @@ -547,7 +551,8 @@ class TestMongosConnection(IntegrationTest): None, [{}] ): # Create a client e.g. with read_preference=NEAREST - c = get_client(read_preference=mode(tag_sets=tag_sets)) + c = get_client(host, port, + read_preference=mode(tag_sets=tag_sets)) self.assertEqual(is_mongos, c.is_mongos) cursor = c.pymongo_test.test.find() @@ -586,7 +591,8 @@ class TestMongosConnection(IntegrationTest): [{'dc': 'la'}, {'dc': 'sf'}], [{'dc': 'la'}, {'dc': 'sf'}, {}], ): - c = get_client(read_preference=mode(tag_sets=tag_sets)) + c = get_client(host, port, + read_preference=mode(tag_sets=tag_sets)) self.assertEqual(is_mongos, c.is_mongos) cursor = c.pymongo_test.test.find() @@ -599,7 +605,7 @@ class TestMongosConnection(IntegrationTest): '$readPreference' in cursor._Cursor__query_spec()) def test_only_secondary_ok_commands_have_read_prefs(self): - c = get_client(read_preference=ReadPreference.SECONDARY) + c = get_client(host, port, read_preference=ReadPreference.SECONDARY) with warnings.catch_warnings(): warnings.simplefilter("ignore", UserWarning) diff --git a/test/test_replica_set_client.py b/test/test_replica_set_client.py index d126b899f..aa6ab6ce2 100644 --- a/test/test_replica_set_client.py +++ b/test/test_replica_set_client.py @@ -39,13 +39,18 @@ from pymongo.errors import (AutoReconnect, ConnectionFailure, InvalidName, OperationFailure, InvalidOperation) -from test import client_context, pair, port, SkipTest, unittest +from test import (client_context, + connection_string, + pair, + port, + SkipTest, + unittest) from test.pymongo_mocks import MockReplicaSetClient from test.utils import ( delay, assertReadFrom, assertReadFromAll, read_from_which_host, remove_all_users, assertRaisesExactly, TestRequestMixin, one, server_started_with_auth, pools_from_rs_client, get_pool, - _TestLazyConnectMixin) + get_rs_client, _TestLazyConnectMixin) from test.version import Version @@ -90,9 +95,8 @@ class TestReplicaSetClientBase(unittest.TestCase): ] def _get_client(self, **kwargs): - return MongoReplicaSetClient(pair, - replicaSet=self.name, - **kwargs) + return get_rs_client(connection_string(), + replicaSet=self.name, **kwargs) class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin): @@ -168,11 +172,9 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin): @client_context.require_auth def test_init_disconnected_with_auth(self): c = client_context.rs_client - - c.admin.add_user("admin", "pass") - c.admin.authenticate("admin", "pass") try: - c.pymongo_test.add_user("user", "pass", roles=['readWrite', 'userAdmin']) + c.pymongo_test.add_user("user", "pass", + roles=['readWrite', 'userAdmin']) # Auth with lazy connection. host = one(self.hosts) @@ -193,9 +195,6 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin): finally: # Clean up. remove_all_users(c.pymongo_test) - remove_all_users(c.admin) - c.admin.logout() - c.disconnect() def test_connect(self): assertRaisesExactly(ConnectionFailure, MongoReplicaSetClient, @@ -418,7 +417,8 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin): self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"]) self.assertFalse(c.in_request()) - c.copy_database("pymongo_test", "pymongo_test2", pair) + + c.copy_database("pymongo_test", "pymongo_test2") # copy_database() didn't accidentally restart the request self.assertFalse(c.in_request()) @@ -431,8 +431,6 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin): server_started_with_auth(c)): c.drop_database("pymongo_test1") - c.admin.add_user("admin", "password") - c.admin.authenticate("admin", "password") try: c.pymongo_test.add_user("mike", "password") @@ -455,10 +453,6 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin): finally: # Cleanup remove_all_users(c.pymongo_test) - c.admin.remove_user("admin") - c.admin.logout() - c.pymongo_test.logout() - c.disconnect() def test_get_default_database(self): host = one(self.hosts) @@ -1090,7 +1084,7 @@ class TestReplicaSetWireVersion(unittest.TestCase): c.set_wire_version_range('a:1', 1, 5) c.set_wire_version_range('b:2', 0, 1) c.set_wire_version_range('c:3', 1, 2) - c.db.collection.find_one() # Connect. + c.db.command('ismaster') # Connect. self.assertEqual(c.min_wire_version, 1) self.assertEqual(c.max_wire_version, 5) @@ -1113,9 +1107,13 @@ class TestReplicaSetClientLazyConnect( TestReplicaSetClientBase, _TestLazyConnectMixin): + @classmethod + def setUpClass(cls): + TestReplicaSetClientBase.setUpClass() + def test_read_mode_secondary(self): client = MongoReplicaSetClient( - pair, replicaSet=self.name, _connect=False, + connection_string(), replicaSet=self.name, _connect=False, read_preference=ReadPreference.SECONDARY) # No error. @@ -1128,18 +1126,27 @@ class TestReplicaSetClientLazyConnectGevent( _TestLazyConnectMixin): use_greenlets = True + @classmethod + def setUpClass(cls): + TestReplicaSetClientBase.setUpClass() + class TestReplicaSetClientLazyConnectBadSeeds( TestReplicaSetClientBase, _TestLazyConnectMixin): + @classmethod + def setUpClass(cls): + TestReplicaSetClientBase.setUpClass() + def _get_client(self, **kwargs): kwargs.setdefault('connectTimeoutMS', 500) # Assume there are no open mongods listening on a.com, b.com, .... bad_seeds = ['%s.com' % chr(ord('a') + i) for i in range(5)] - seeds = ','.join(bad_seeds + [pair]) - client = MongoReplicaSetClient(seeds, replicaSet=self.name, **kwargs) + client = MongoReplicaSetClient( + connection_string(seeds=(bad_seeds + [pair])), + replicaSet=self.name, **kwargs) # In case of a slow test machine. client._refresh_timeout_sec = 30 @@ -1180,7 +1187,7 @@ class TestReplicaSetClientMaxWriteBatchSize(unittest.TestCase): # Starts with default max batch size. self.assertEqual(1000, c.max_write_batch_size) - c.db.collection.find_one() # Connect. + c.db.command('ismaster') # Connect. # Uses primary's max batch size. self.assertEqual(c.max_write_batch_size, 1) diff --git a/test/test_replica_set_reconfig.py b/test/test_replica_set_reconfig.py index 6c8d72b56..7e76ac64a 100644 --- a/test/test_replica_set_reconfig.py +++ b/test/test_replica_set_reconfig.py @@ -57,7 +57,7 @@ class TestSecondaryBecomesStandalone(unittest.TestCase): c.disconnect() try: - c.db.collection.find_one() + c.db.command('ismaster') except ConfigurationError as e: self.assertTrue('not a member of replica set' in str(e)) else: @@ -147,7 +147,7 @@ class TestSecondaryAdded(unittest.TestCase): c.mock_ismaster_hosts.append('c:3') c.disconnect() - c.db.collection.find_one() + c.db.command('ismaster') self.assertEqual('a', c.host) self.assertEqual(1, c.port) diff --git a/test/test_threads.py b/test/test_threads.py index bad0acc72..3610dc997 100644 --- a/test/test_threads.py +++ b/test/test_threads.py @@ -17,9 +17,8 @@ import threading import traceback -from test import SkipTest, unittest, client_context -from test.utils import (joinall, remove_all_users, - server_started_with_auth, RendezvousThread) +from test import unittest, client_context, pair +from test.utils import joinall, remove_all_users, RendezvousThread from test.test_client import get_client from test.utils import get_pool from pymongo.pool import SocketInfo, _closed @@ -185,7 +184,7 @@ class BaseTestThreads(object): test_threads_replica_set_connection.py. """ # Regular test client - return get_client() + return get_client(pair) def test_threading(self): self.db.drop_collection("test") @@ -253,7 +252,7 @@ class BaseTestThreads(object): # # If we've fixed PYTHON-345, then only one AutoReconnect is raised, # and all the threads get new request sockets. - cx = get_client(auto_start_request=True) + cx = get_client(pair, auto_start_request=True) collection = cx.db.pymongo_test # acquire a request socket for the main thread @@ -310,6 +309,11 @@ class BaseTestThreadsAuth(object): unittest imports this module, and once when unittest imports test_threads_replica_set_connection.py, which imports this module.) """ + @classmethod + @client_context.require_auth + def setUpClass(cls): + pass + def _get_client(self): """ Intended for overriding in TestThreadsAuthReplicaSet. This method @@ -317,18 +321,19 @@ class BaseTestThreadsAuth(object): test_threads_replica_set_connection.py. """ # Regular test client - return get_client() + return get_client(pair) def setUp(self): client = self._get_client() - if not server_started_with_auth(client): - raise SkipTest("Authentication is not enabled on server") self.client = client self.client.admin.add_user('admin-user', 'password', roles=['clusterAdmin', 'dbAdminAnyDatabase', 'readWriteAnyDatabase', 'userAdminAnyDatabase']) + # client returned from self._get_client() may already be authenticated + # to get around restricted localhost exception in MongoDB >= 2.7.1. + self.client.admin.logout() self.client.admin.authenticate("admin-user", "password") self.client.auth_test.add_user("test-user", "password", roles=['readWrite']) @@ -338,17 +343,20 @@ class BaseTestThreadsAuth(object): self.client.admin.authenticate("admin-user", "password") remove_all_users(self.client.auth_test) self.client.drop_database('auth_test') - remove_all_users(self.client.admin) + self.client.admin.remove_user('admin-user') + self.client.admin.logout() # Clear client reference so that RSC's monitor thread # dies. self.client = None def test_auto_auth_login(self): client = self._get_client() + client.admin.logout() self.assertRaises(OperationFailure, client.auth_test.test.find_one) # Admin auth client = self._get_client() + client.admin.logout() client.admin.authenticate("admin-user", "password") nthreads = 10 @@ -365,6 +373,7 @@ class BaseTestThreadsAuth(object): # Database-specific auth client = self._get_client() + client.admin.logout() client.auth_test.authenticate("test-user", "password") threads = [] diff --git a/test/test_threads_replica_set_client.py b/test/test_threads_replica_set_client.py index 42e050b0f..f67a5b073 100644 --- a/test/test_threads_replica_set_client.py +++ b/test/test_threads_replica_set_client.py @@ -14,11 +14,10 @@ """Test that pymongo is thread safe.""" -from pymongo.mongo_replica_set_client import MongoReplicaSetClient - from test import unittest from test.test_threads import BaseTestThreads, BaseTestThreadsAuth from test.test_replica_set_client import TestReplicaSetClientBase, pair +from test.utils import get_rs_client class TestThreadsReplicaSet(TestReplicaSetClientBase, BaseTestThreads): @@ -40,6 +39,15 @@ class TestThreadsReplicaSet(TestReplicaSetClientBase, BaseTestThreads): class TestThreadsAuthReplicaSet(TestReplicaSetClientBase, BaseTestThreadsAuth): + @classmethod + def setUpClass(cls): + TestReplicaSetClientBase.setUpClass() + BaseTestThreadsAuth.setUpClass() + + @classmethod + def tearDownClass(cls): + TestReplicaSetClientBase.tearDownClass() + def setUp(self): """ Prepare to test all the same things that TestThreads tests, but do it @@ -57,7 +65,7 @@ class TestThreadsAuthReplicaSet(TestReplicaSetClientBase, BaseTestThreadsAuth): Override TestThreadsAuth, so its tests run on a MongoReplicaSetClient instead of a regular MongoClient. """ - return MongoReplicaSetClient(pair, replicaSet=self.name) + return get_rs_client(pair, replicaSet=self.name) if __name__ == "__main__": diff --git a/test/utils.py b/test/utils.py index 8a7214f8e..adba6282b 100644 --- a/test/utils.py +++ b/test/utils.py @@ -23,7 +23,10 @@ import threading from pymongo import MongoClient, MongoReplicaSetClient from pymongo.errors import AutoReconnect from pymongo.pool import NO_REQUEST, NO_SOCKET_YET, SocketInfo -from test import host, port, SkipTest +from test import (SkipTest, + client_context, + db_user, + db_pwd) from test.version import Version @@ -34,6 +37,20 @@ except ImportError: has_gevent = False +def get_client(*args, **kwargs): + client = MongoClient(*args, **kwargs) + if client_context.auth_enabled and kwargs.get("_connect", True): + client.admin.authenticate(db_user, db_pwd) + return client + + +def get_rs_client(*args, **kwargs): + client = MongoReplicaSetClient(*args, **kwargs) + if client_context.auth_enabled and kwargs.get("_connect", True): + client.admin.authenticate(db_user, db_pwd) + return client + + # No functools in Python 2.4 def my_partial(f, *args, **kwargs): def _f(*new_args, **new_kwargs): @@ -126,9 +143,10 @@ def drop_collections(db): def remove_all_users(db): if Version.from_client(db.connection).at_least(2, 5, 3, -1): - db.command({"dropAllUsersFromDatabase": 1}) + db.command({"dropAllUsersFromDatabase": 1, + "writeConcern": {"w": "majority"}}) else: - db.system.users.remove({}) + db.system.users.remove({}, w="majority") def joinall(threads): @@ -147,8 +165,10 @@ def enable_text_search(client): if isinstance(client, MongoReplicaSetClient): for host, port in client.secondaries: - MongoClient(host, port).admin.command( - 'setParameter', textSearchEnabled=True) + client = MongoClient(host, port) + if client_context.auth_enabled: + client.admin.authenticate(db_user, db_pwd) + client.admin.command('setParameter', textSearchEnabled=True) def assertRaisesExactly(cls, fn, *args, **kwargs): """ @@ -448,7 +468,7 @@ def lazy_client_trial(reset, target, test, get_client, use_greenlets): if use_greenlets and not has_gevent: raise SkipTest('Gevent not installed') - collection = MongoClient(host, port).pymongo_test.test + collection = client_context.client.pymongo_test.test # Make concurrency bugs more likely to manifest. interval = None @@ -463,8 +483,8 @@ def lazy_client_trial(reset, target, test, get_client, use_greenlets): try: for i in range(NTRIALS): reset(collection) - lazy_client = get_client( - _connect=False, use_greenlets=use_greenlets) + lazy_client = get_client(_connect=False, + use_greenlets=use_greenlets) lazy_collection = lazy_client.pymongo_test.test run_threads(lazy_collection, target, use_greenlets)