diff --git a/test/test_bulk.py b/test/test_bulk.py index 3f4a57cdd..f6e0552a6 100644 --- a/test/test_bulk.py +++ b/test/test_bulk.py @@ -643,78 +643,74 @@ class TestBulk(BulkTestBase): def test_single_error_ordered_batch(self): self.coll.ensure_index('a', unique=True) + self.addCleanup(self.coll.drop_index, [('a', 1)]) + batch = self.coll.initialize_ordered_bulk_op() + batch.insert({'b': 1, 'a': 1}) + batch.find({'b': 2}).upsert().update_one({'$set': {'a': 1}}) + batch.insert({'b': 3, 'a': 2}) + try: - batch = self.coll.initialize_ordered_bulk_op() - batch.insert({'b': 1, 'a': 1}) - batch.find({'b': 2}).upsert().update_one({'$set': {'a': 1}}) - batch.insert({'b': 3, 'a': 2}) + batch.execute() + except BulkWriteError as exc: + result = exc.details + self.assertEqual(exc.code, 65) + else: + self.fail("Error not raised") - try: - batch.execute() - except BulkWriteError as exc: - result = exc.details - self.assertEqual(exc.code, 65) - else: - self.fail("Error not raised") - - self.assertEqualResponse( - {'nMatched': 0, - 'nModified': 0, - 'nUpserted': 0, - 'nInserted': 1, - 'nRemoved': 0, - 'upserted': [], - 'writeConcernErrors': [], - 'writeErrors': [ - {'index': 1, - 'code': 11000, - 'errmsg': '...', - 'op': {'q': {'b': 2}, - 'u': {'$set': {'a': 1}}, - 'multi': False, - 'upsert': True}}]}, - result) - finally: - self.coll.drop_index([('a', 1)]) + self.assertEqualResponse( + {'nMatched': 0, + 'nModified': 0, + 'nUpserted': 0, + 'nInserted': 1, + 'nRemoved': 0, + 'upserted': [], + 'writeConcernErrors': [], + 'writeErrors': [ + {'index': 1, + 'code': 11000, + 'errmsg': '...', + 'op': {'q': {'b': 2}, + 'u': {'$set': {'a': 1}}, + 'multi': False, + 'upsert': True}}]}, + result) def test_multiple_error_ordered_batch(self): self.coll.ensure_index('a', unique=True) + self.addCleanup(self.coll.drop_index, [('a', 1)]) + batch = self.coll.initialize_ordered_bulk_op() + batch.insert({'b': 1, 'a': 1}) + batch.find({'b': 2}).upsert().update_one({'$set': {'a': 1}}) + batch.find({'b': 3}).upsert().update_one({'$set': {'a': 2}}) + batch.find({'b': 2}).upsert().update_one({'$set': {'a': 1}}) + batch.insert({'b': 4, 'a': 3}) + batch.insert({'b': 5, 'a': 1}) + try: - batch = self.coll.initialize_ordered_bulk_op() - batch.insert({'b': 1, 'a': 1}) - batch.find({'b': 2}).upsert().update_one({'$set': {'a': 1}}) - batch.find({'b': 3}).upsert().update_one({'$set': {'a': 2}}) - batch.find({'b': 2}).upsert().update_one({'$set': {'a': 1}}) - batch.insert({'b': 4, 'a': 3}) - batch.insert({'b': 5, 'a': 1}) + batch.execute() + except BulkWriteError as exc: + result = exc.details + self.assertEqual(exc.code, 65) + else: + self.fail("Error not raised") - try: - batch.execute() - except BulkWriteError as exc: - result = exc.details - self.assertEqual(exc.code, 65) - else: - self.fail("Error not raised") - - self.assertEqualResponse( - {'nMatched': 0, - 'nModified': 0, - 'nUpserted': 0, - 'nInserted': 1, - 'nRemoved': 0, - 'upserted': [], - 'writeConcernErrors': [], - 'writeErrors': [ - {'index': 1, - 'code': 11000, - 'errmsg': '...', - 'op': {'q': {'b': 2}, - 'u': {'$set': {'a': 1}}, - 'multi': False, - 'upsert': True}}]}, - result) - finally: - self.coll.drop_index([('a', 1)]) + self.assertEqualResponse( + {'nMatched': 0, + 'nModified': 0, + 'nUpserted': 0, + 'nInserted': 1, + 'nRemoved': 0, + 'upserted': [], + 'writeConcernErrors': [], + 'writeErrors': [ + {'index': 1, + 'code': 11000, + 'errmsg': '...', + 'op': {'q': {'b': 2}, + 'u': {'$set': {'a': 1}}, + 'multi': False, + 'upsert': True}}]}, + result) def test_single_unordered_batch(self): batch = self.coll.initialize_unordered_bulk_op() @@ -737,85 +733,81 @@ class TestBulk(BulkTestBase): def test_single_error_unordered_batch(self): self.coll.ensure_index('a', unique=True) + self.addCleanup(self.coll.drop_index, [('a', 1)]) + batch = self.coll.initialize_unordered_bulk_op() + batch.insert({'b': 1, 'a': 1}) + batch.find({'b': 2}).upsert().update_one({'$set': {'a': 1}}) + batch.insert({'b': 3, 'a': 2}) + try: - batch = self.coll.initialize_unordered_bulk_op() - batch.insert({'b': 1, 'a': 1}) - batch.find({'b': 2}).upsert().update_one({'$set': {'a': 1}}) - batch.insert({'b': 3, 'a': 2}) + batch.execute() + except BulkWriteError as exc: + result = exc.details + self.assertEqual(exc.code, 65) + else: + self.fail("Error not raised") - try: - batch.execute() - except BulkWriteError as exc: - result = exc.details - self.assertEqual(exc.code, 65) - else: - self.fail("Error not raised") - - self.assertEqualResponse( - {'nMatched': 0, - 'nModified': 0, - 'nUpserted': 0, - 'nInserted': 2, - 'nRemoved': 0, - 'upserted': [], - 'writeConcernErrors': [], - 'writeErrors': [ - {'index': 1, - 'code': 11000, - 'errmsg': '...', - 'op': {'q': {'b': 2}, - 'u': {'$set': {'a': 1}}, - 'multi': False, - 'upsert': True}}]}, - result) - finally: - self.coll.drop_index([('a', 1)]) + self.assertEqualResponse( + {'nMatched': 0, + 'nModified': 0, + 'nUpserted': 0, + 'nInserted': 2, + 'nRemoved': 0, + 'upserted': [], + 'writeConcernErrors': [], + 'writeErrors': [ + {'index': 1, + 'code': 11000, + 'errmsg': '...', + 'op': {'q': {'b': 2}, + 'u': {'$set': {'a': 1}}, + 'multi': False, + 'upsert': True}}]}, + result) def test_multiple_error_unordered_batch(self): self.coll.ensure_index('a', unique=True) - try: - batch = self.coll.initialize_unordered_bulk_op() - batch.insert({'b': 1, 'a': 1}) - batch.find({'b': 2}).upsert().update_one({'$set': {'a': 3}}) - batch.find({'b': 3}).upsert().update_one({'$set': {'a': 4}}) - batch.find({'b': 4}).upsert().update_one({'$set': {'a': 3}}) - batch.insert({'b': 5, 'a': 2}) - batch.insert({'b': 6, 'a': 1}) + self.addCleanup(self.coll.drop_index, [('a', 1)]) + batch = self.coll.initialize_unordered_bulk_op() + batch.insert({'b': 1, 'a': 1}) + batch.find({'b': 2}).upsert().update_one({'$set': {'a': 3}}) + batch.find({'b': 3}).upsert().update_one({'$set': {'a': 4}}) + batch.find({'b': 4}).upsert().update_one({'$set': {'a': 3}}) + batch.insert({'b': 5, 'a': 2}) + batch.insert({'b': 6, 'a': 1}) - try: - batch.execute() - except BulkWriteError as exc: - result = exc.details - self.assertEqual(exc.code, 65) - else: - self.fail("Error not raised") - # Assume the update at index 1 runs before the update at index 3, - # although the spec does not require it. Same for inserts. - self.assertEqualResponse( - {'nMatched': 0, - 'nModified': 0, - 'nUpserted': 2, - 'nInserted': 2, - 'nRemoved': 0, - 'upserted': [ - {'index': 1, '_id': '...'}, - {'index': 2, '_id': '...'}], - 'writeConcernErrors': [], - 'writeErrors': [ - {'index': 3, - 'code': 11000, - 'errmsg': '...', - 'op': {'q': {'b': 4}, - 'u': {'$set': {'a': 3}}, - 'multi': False, - 'upsert': True}}, - {'index': 5, - 'code': 11000, - 'errmsg': '...', - 'op': {'_id': '...', 'b': 6, 'a': 1}}]}, - result) - finally: - self.coll.drop_index([('a', 1)]) + try: + batch.execute() + except BulkWriteError as exc: + result = exc.details + self.assertEqual(exc.code, 65) + else: + self.fail("Error not raised") + # Assume the update at index 1 runs before the update at index 3, + # although the spec does not require it. Same for inserts. + self.assertEqualResponse( + {'nMatched': 0, + 'nModified': 0, + 'nUpserted': 2, + 'nInserted': 2, + 'nRemoved': 0, + 'upserted': [ + {'index': 1, '_id': '...'}, + {'index': 2, '_id': '...'}], + 'writeConcernErrors': [], + 'writeErrors': [ + {'index': 3, + 'code': 11000, + 'errmsg': '...', + 'op': {'q': {'b': 4}, + 'u': {'$set': {'a': 3}}, + 'multi': False, + 'upsert': True}}, + {'index': 5, + 'code': 11000, + 'errmsg': '...', + 'op': {'_id': '...', 'b': 6, 'a': 1}}]}, + result) def test_large_inserts_ordered(self): big = 'x' * self.coll.database.connection.max_bson_size @@ -994,42 +986,40 @@ class TestBulkWriteConcern(BulkTestBase): self.coll.remove() self.coll.ensure_index('a', unique=True) + self.addCleanup(self.coll.drop_index, [('a', 1)]) # Fail due to write concern support as well # as duplicate key error on ordered batch. + batch = self.coll.initialize_ordered_bulk_op() + batch.insert({'a': 1}) + batch.find({'a': 3}).upsert().replace_one({'b': 1}) + batch.insert({'a': 1}) + batch.insert({'a': 2}) try: - batch = self.coll.initialize_ordered_bulk_op() - batch.insert({'a': 1}) - batch.find({'a': 3}).upsert().replace_one({'b': 1}) - batch.insert({'a': 1}) - batch.insert({'a': 2}) - try: - self.cause_wtimeout(batch) - except BulkWriteError as exc: - result = exc.details - self.assertEqual(exc.code, 65) - else: - self.fail("Error not raised") + self.cause_wtimeout(batch) + except BulkWriteError as exc: + result = exc.details + self.assertEqual(exc.code, 65) + else: + self.fail("Error not raised") - self.assertEqualResponse( - {'nMatched': 0, - 'nModified': 0, - 'nUpserted': 1, - 'nInserted': 1, - 'nRemoved': 0, - 'upserted': [{'index': 1, '_id': '...'}], - 'writeErrors': [ - {'index': 2, - 'code': 11000, - 'errmsg': '...', - 'op': {'_id': '...', 'a': 1}}]}, - result) + self.assertEqualResponse( + {'nMatched': 0, + 'nModified': 0, + 'nUpserted': 1, + 'nInserted': 1, + 'nRemoved': 0, + 'upserted': [{'index': 1, '_id': '...'}], + 'writeErrors': [ + {'index': 2, + 'code': 11000, + 'errmsg': '...', + 'op': {'_id': '...', 'a': 1}}]}, + result) - self.assertEqual(2, len(result['writeConcernErrors'])) - failed = result['writeErrors'][0] - self.assertTrue("duplicate" in failed['errmsg']) - finally: - self.coll.drop_index([('a', 1)]) + self.assertEqual(2, len(result['writeConcernErrors'])) + failed = result['writeErrors'][0] + self.assertTrue("duplicate" in failed['errmsg']) @client_context.require_replica_set def test_write_concern_failure_unordered(self): @@ -1062,47 +1052,45 @@ class TestBulkWriteConcern(BulkTestBase): self.coll.remove() self.coll.ensure_index('a', unique=True) + self.addCleanup(self.coll.drop_index, [('a', 1)]) # Fail due to write concern support as well # as duplicate key error on unordered batch. + batch = self.coll.initialize_unordered_bulk_op() + batch.insert({'a': 1}) + batch.find({'a': 3}).upsert().update_one({'$set': {'a': 3, + 'b': 1}}) + batch.insert({'a': 1}) + batch.insert({'a': 2}) try: - batch = self.coll.initialize_unordered_bulk_op() - batch.insert({'a': 1}) - batch.find({'a': 3}).upsert().update_one({'$set': {'a': 3, - 'b': 1}}) - batch.insert({'a': 1}) - batch.insert({'a': 2}) - try: - self.cause_wtimeout(batch) - except BulkWriteError as exc: - result = exc.details - self.assertEqual(exc.code, 65) - else: - self.fail("Error not raised") + self.cause_wtimeout(batch) + except BulkWriteError as exc: + result = exc.details + self.assertEqual(exc.code, 65) + else: + self.fail("Error not raised") - self.assertEqual(2, result['nInserted']) - self.assertEqual(1, result['nUpserted']) - self.assertEqual(1, len(result['writeErrors'])) - # When talking to legacy servers there will be a - # write concern error for each operation. - self.assertTrue(len(result['writeConcernErrors']) > 1) + self.assertEqual(2, result['nInserted']) + self.assertEqual(1, result['nUpserted']) + self.assertEqual(1, len(result['writeErrors'])) + # When talking to legacy servers there will be a + # write concern error for each operation. + self.assertTrue(len(result['writeConcernErrors']) > 1) - failed = result['writeErrors'][0] - self.assertEqual(2, failed['index']) - self.assertEqual(11000, failed['code']) - self.assertTrue(isinstance(failed['errmsg'], string_type)) - self.assertEqual(1, failed['op']['a']) + failed = result['writeErrors'][0] + self.assertEqual(2, failed['index']) + self.assertEqual(11000, failed['code']) + self.assertTrue(isinstance(failed['errmsg'], string_type)) + self.assertEqual(1, failed['op']['a']) - failed = result['writeConcernErrors'][0] - self.assertEqual(64, failed['code']) - self.assertTrue(isinstance(failed['errmsg'], string_type)) + failed = result['writeConcernErrors'][0] + self.assertEqual(64, failed['code']) + self.assertTrue(isinstance(failed['errmsg'], string_type)) - upserts = result['upserted'] - self.assertEqual(1, len(upserts)) - self.assertEqual(1, upserts[0]['index']) - self.assertTrue(upserts[0].get('_id')) - finally: - self.coll.drop_index([('a', 1)]) + upserts = result['upserted'] + self.assertEqual(1, len(upserts)) + self.assertEqual(1, upserts[0]['index']) + self.assertTrue(upserts[0].get('_id')) class TestBulkNoResults(BulkTestBase): diff --git a/test/test_client.py b/test/test_client.py index f395febe2..8a019db0f 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -323,74 +323,68 @@ class TestClient(IntegrationTest): @client_context.require_auth def test_auth_from_uri(self): self.client.admin.add_user("admin", "pass", roles=["root"]) - try: - self.client.pymongo_test.add_user( - "user", "pass", roles=['userAdmin', 'readWrite']) + self.addCleanup(self.client.admin.remove_user, 'admin') + self.addCleanup(remove_all_users, self.client.pymongo_test) - with self.assertRaises(OperationFailure): - connected(rs_or_single_client( - "mongodb://a:b@%s:%d" % (host, port))) + self.client.pymongo_test.add_user( + "user", "pass", roles=['userAdmin', 'readWrite']) - # No error. - connected(rs_or_single_client_noauth( - "mongodb://admin:pass@%s:%d" % (host, port))) + with self.assertRaises(OperationFailure): + connected(rs_or_single_client( + "mongodb://a:b@%s:%d" % (host, port))) - # Wrong database. - uri = "mongodb://admin:pass@%s:%d/pymongo_test" % (host, port) - with self.assertRaises(OperationFailure): - connected(rs_or_single_client(uri)) + # No error. + connected(rs_or_single_client_noauth( + "mongodb://admin:pass@%s:%d" % (host, port))) - # No error. - connected(rs_or_single_client_noauth( - "mongodb://user:pass@%s:%d/pymongo_test" % (host, port))) + # Wrong database. + uri = "mongodb://admin:pass@%s:%d/pymongo_test" % (host, port) + with self.assertRaises(OperationFailure): + connected(rs_or_single_client(uri)) - # Auth with lazy connection. - rs_or_single_client( - "mongodb://user:pass@%s:%d/pymongo_test" % (host, port), - connect=False).pymongo_test.test.find_one() + # No error. + connected(rs_or_single_client_noauth( + "mongodb://user:pass@%s:%d/pymongo_test" % (host, port))) - # Wrong password. - bad_client = rs_or_single_client( - "mongodb://user:wrong@%s:%d/pymongo_test" % (host, port), - connect=False) + # Auth with lazy connection. + rs_or_single_client( + "mongodb://user:pass@%s:%d/pymongo_test" % (host, port), + connect=False).pymongo_test.test.find_one() - self.assertRaises(OperationFailure, - bad_client.pymongo_test.test.find_one) + # Wrong password. + bad_client = rs_or_single_client( + "mongodb://user:wrong@%s:%d/pymongo_test" % (host, port), + connect=False) - finally: - # Clean up. - remove_all_users(self.client.pymongo_test) - self.client.admin.remove_user('admin') + self.assertRaises(OperationFailure, + bad_client.pymongo_test.test.find_one) @client_context.require_auth def test_multiple_logins(self): self.client.pymongo_test.add_user('user1', 'pass', roles=['readWrite']) self.client.pymongo_test.add_user('user2', 'pass', roles=['readWrite']) + self.addCleanup(remove_all_users, self.client.pymongo_test) - try: - client = rs_or_single_client_noauth( - "mongodb://user1:pass@%s:%d/pymongo_test" % (host, port)) - - client.pymongo_test.test.find_one() - with self.assertRaises(OperationFailure): - # Can't log in to the same database with multiple users. - client.pymongo_test.authenticate('user2', 'pass') - - client.pymongo_test.test.find_one() - client.pymongo_test.logout() - with self.assertRaises(OperationFailure): - client.pymongo_test.test.find_one() + client = rs_or_single_client_noauth( + "mongodb://user1:pass@%s:%d/pymongo_test" % (host, port)) + client.pymongo_test.test.find_one() + with self.assertRaises(OperationFailure): + # Can't log in to the same database with multiple users. client.pymongo_test.authenticate('user2', 'pass') + + client.pymongo_test.test.find_one() + client.pymongo_test.logout() + with self.assertRaises(OperationFailure): client.pymongo_test.test.find_one() - with self.assertRaises(OperationFailure): - client.pymongo_test.authenticate('user1', 'pass') + client.pymongo_test.authenticate('user2', 'pass') + client.pymongo_test.test.find_one() - client.pymongo_test.test.find_one() + with self.assertRaises(OperationFailure): + client.pymongo_test.authenticate('user1', 'pass') - finally: - remove_all_users(self.client.pymongo_test) + client.pymongo_test.test.find_one() @client_context.require_auth def test_lazy_auth_raises_operation_failure(self): @@ -879,38 +873,35 @@ class TestExhaustCursor(IntegrationTest): collection.remove() collection.insert([{} for _ in range(200)]) + self.addCleanup(client_context.client.pymongo_test.test.drop) - try: - pool = get_pool(client) - pool._check_interval_seconds = None # Never check. - sock_info = one(pool.sockets) + pool = get_pool(client) + pool._check_interval_seconds = None # Never check. + sock_info = one(pool.sockets) - cursor = collection.find(cursor_type=EXHAUST) + cursor = collection.find(cursor_type=EXHAUST) - # Initial query succeeds. - cursor.next() + # Initial query succeeds. + cursor.next() - # Cause a server error on getmore. - def receive_message(operation, request_id): - # Discard the actual server response. - SocketInfo.receive_message(sock_info, operation, request_id) + # Cause a server error on getmore. + def receive_message(operation, request_id): + # Discard the actual server response. + SocketInfo.receive_message(sock_info, operation, request_id) - # responseFlags bit 1 is QueryFailure. - msg = struct.pack('= 3.2) or ConnectionFailure + # (2.x) depending on where OpenSSL first sees the PEM file. try: - self.assertRaises(OperationFailure, coll.count) - self.assertTrue(ssl_client.admin.authenticate( - MONGODB_X509_USERNAME, mechanism='MONGODB-X509')) - self.assertTrue(coll.remove()) - uri = ('mongodb://%s@%s:%d/?authMechanism=' - 'MONGODB-X509' % ( - quote_plus(MONGODB_X509_USERNAME), host, port)) - # SSL options aren't supported in the URI... - self.assertTrue(MongoClient(uri, - ssl=True, ssl_certfile=CLIENT_PEM)) + with client_knobs(server_wait_time=0.1): + connected(MongoClient(uri, ssl=True, ssl_certfile=CA_PEM)) + except (ssl.SSLError, ConnectionFailure): + pass + else: + self.fail("Invalid certificate accepted.") - # Should require a username - uri = ('mongodb://%s:%d/?authMechanism=MONGODB-X509' % (host, - port)) - client_bad = MongoClient(uri, ssl=True, ssl_certfile=CLIENT_PEM) - self.assertRaises(OperationFailure, - client_bad.pymongo_test.test.remove) + try: + with client_knobs(server_wait_time=0.1): + connected(MongoClient(pair, ssl=True, ssl_certfile=CA_PEM)) + except (ssl.SSLError, ConnectionFailure): + pass + else: + self.fail("Invalid certificate accepted.") - # Auth should fail if username and certificate do not match - uri = ('mongodb://%s@%s:%d/?authMechanism=' - 'MONGODB-X509' % ( - quote_plus("not the username"), host, port)) - - bad_client = MongoClient(uri, ssl=True, ssl_certfile=CLIENT_PEM) - with self.assertRaises(OperationFailure): - bad_client.pymongo_test.test.find_one() - - self.assertRaises(OperationFailure, ssl_client.admin.authenticate, - "not the username", - mechanism="MONGODB-X509") - - # Invalid certificate (using CA certificate as client certificate) - uri = ('mongodb://%s@%s:%d/?authMechanism=' - 'MONGODB-X509' % ( - quote_plus(MONGODB_X509_USERNAME), host, port)) - # These tests will raise SSLError (>= 3.2) or ConnectionFailure - # (2.x) depending on where OpenSSL first sees the PEM file. - try: - with client_knobs(server_wait_time=0.1): - connected(MongoClient(uri, ssl=True, ssl_certfile=CA_PEM)) - except (ssl.SSLError, ConnectionFailure): - pass - else: - self.fail("Invalid certificate accepted.") - - try: - with client_knobs(server_wait_time=0.1): - connected(MongoClient(pair, ssl=True, ssl_certfile=CA_PEM)) - except (ssl.SSLError, ConnectionFailure): - pass - else: - self.fail("Invalid certificate accepted.") - - # Cleanup - finally: - remove_all_users(ssl_client['$external']) - ssl_client['$external'].logout() if __name__ == "__main__": unittest.main()