PYTHON-5374 Assert unset BulkWriteException.partialResult in CRUD prose tests (#2425)
Co-authored-by: Noah Stapp <noah@noahstapp.com>
This commit is contained in:
parent
e07a6b7e77
commit
5ce53dc175
@ -84,6 +84,7 @@ class TestClientBulkWrite(AsyncIntegrationTest):
|
||||
|
||||
|
||||
# https://github.com/mongodb/specifications/tree/master/source/crud/tests
|
||||
# Note: tests 1 and 2 are in test_read_write_concern_spec.py
|
||||
class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
@ -92,7 +93,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
self.max_message_size_bytes = await async_client_context.max_message_size_bytes
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
async def test_batch_splits_if_num_operations_too_large(self):
|
||||
async def test_3_batch_splits_if_num_operations_too_large(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -116,7 +117,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
self.assertEqual(first_event.operation_id, second_event.operation_id)
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
async def test_batch_splits_if_ops_payload_too_large(self):
|
||||
async def test_4_batch_splits_if_ops_payload_too_large(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -148,7 +149,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
@async_client_context.require_failCommand_fail_point
|
||||
async def test_collects_write_concern_errors_across_batches(self):
|
||||
async def test_5_collects_write_concern_errors_across_batches(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(
|
||||
event_listeners=[listener],
|
||||
@ -189,7 +190,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
self.assertEqual(len(bulk_write_events), 2)
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
async def test_collects_write_errors_across_batches_unordered(self):
|
||||
async def test_6_collects_write_errors_across_batches_unordered(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -218,7 +219,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
self.assertEqual(len(bulk_write_events), 2)
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
async def test_collects_write_errors_across_batches_ordered(self):
|
||||
async def test_6_collects_write_errors_across_batches_ordered(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -247,7 +248,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
self.assertEqual(len(bulk_write_events), 1)
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
async def test_handles_cursor_requiring_getMore(self):
|
||||
async def test_7_handles_cursor_requiring_getMore(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -287,7 +288,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
@async_client_context.require_no_standalone
|
||||
async def test_handles_cursor_requiring_getMore_within_transaction(self):
|
||||
async def test_8_handles_cursor_requiring_getMore_within_transaction(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -329,7 +330,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
@async_client_context.require_failCommand_fail_point
|
||||
async def test_handles_getMore_error(self):
|
||||
async def test_9_handles_getMore_error(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -382,7 +383,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
self.assertTrue(kill_cursors_event)
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
async def test_returns_error_if_unacknowledged_too_large_insert(self):
|
||||
async def test_10_returns_error_if_unacknowledged_too_large_insert(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -441,7 +442,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
return num_models, models
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
async def test_no_batch_splits_if_new_namespace_is_not_too_large(self):
|
||||
async def test_11_no_batch_splits_if_new_namespace_is_not_too_large(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -471,7 +472,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
self.assertEqual(event.command["nsInfo"][0]["ns"], "db.coll")
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
async def test_batch_splits_if_new_namespace_is_too_large(self):
|
||||
async def test_11_batch_splits_if_new_namespace_is_too_large(self):
|
||||
listener = OvertCommandListener()
|
||||
client = await self.async_rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -508,25 +509,27 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
self.assertEqual(second_event.command["nsInfo"][0]["ns"], namespace)
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
async def test_returns_error_if_no_writes_can_be_added_to_ops(self):
|
||||
async def test_12_returns_error_if_no_writes_can_be_added_to_ops(self):
|
||||
client = await self.async_rs_or_single_client()
|
||||
|
||||
# Document too large.
|
||||
b_repeated = "b" * self.max_message_size_bytes
|
||||
models = [InsertOne(namespace="db.coll", document={"a": b_repeated})]
|
||||
with self.assertRaises(DocumentTooLarge):
|
||||
with self.assertRaises(DocumentTooLarge) as context:
|
||||
await client.bulk_write(models=models)
|
||||
self.assertIsNone(context.exception.partial_result)
|
||||
|
||||
# Namespace too large.
|
||||
c_repeated = "c" * self.max_message_size_bytes
|
||||
namespace = f"db.{c_repeated}"
|
||||
models = [InsertOne(namespace=namespace, document={"a": "b"})]
|
||||
with self.assertRaises(DocumentTooLarge):
|
||||
with self.assertRaises(DocumentTooLarge) as context:
|
||||
await client.bulk_write(models=models)
|
||||
self.assertIsNone(context.exception.partial_result)
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
@unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed")
|
||||
async def test_returns_error_if_auto_encryption_configured(self):
|
||||
async def test_13_returns_error_if_auto_encryption_configured(self):
|
||||
opts = AutoEncryptionOpts(
|
||||
key_vault_namespace="db.coll",
|
||||
kms_providers={"aws": {"accessKeyId": "foo", "secretAccessKey": "bar"}},
|
||||
@ -536,6 +539,7 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
models = [InsertOne(namespace="db.coll", document={"a": "b"})]
|
||||
with self.assertRaises(InvalidOperation) as context:
|
||||
await client.bulk_write(models=models)
|
||||
self.assertIsNone(context.exception.partial_result)
|
||||
self.assertIn(
|
||||
"bulk_write does not currently support automatic encryption", context.exception._message
|
||||
)
|
||||
@ -579,6 +583,8 @@ class TestClientBulkWriteCRUD(AsyncIntegrationTest):
|
||||
self.assertEqual(result.update_results[1].did_upsert, True)
|
||||
self.assertEqual(result.update_results[2].did_upsert, False)
|
||||
|
||||
# Note: test 14 is optional and intentionally not implemented because we provide multiple APIs to specify explain.
|
||||
|
||||
@async_client_context.require_version_min(8, 0, 0, -24)
|
||||
async def test_15_unacknowledged_write_across_batches(self):
|
||||
listener = OvertCommandListener()
|
||||
|
||||
@ -180,6 +180,8 @@ class TestReadWriteConcernSpec(AsyncIntegrationTest):
|
||||
WriteConcern(w=async_client_context.w, wtimeout=1), WTimeoutError
|
||||
)
|
||||
|
||||
# https://github.com/mongodb/specifications/tree/master/source/crud/tests
|
||||
# Test 1 (included here instead of test_client_bulk_write.py)
|
||||
@async_client_context.require_failCommand_fail_point
|
||||
async def test_error_includes_errInfo(self):
|
||||
expected_wce = {
|
||||
@ -214,6 +216,8 @@ class TestReadWriteConcernSpec(AsyncIntegrationTest):
|
||||
}
|
||||
self.assertEqual(ctx.exception.details, expected_details)
|
||||
|
||||
# https://github.com/mongodb/specifications/tree/master/source/crud/tests
|
||||
# Test 2 (included here instead of test_client_bulk_write.py)
|
||||
@async_client_context.require_version_min(4, 9)
|
||||
async def test_write_error_details_exposes_errinfo(self):
|
||||
listener = OvertCommandListener()
|
||||
|
||||
@ -84,6 +84,7 @@ class TestClientBulkWrite(IntegrationTest):
|
||||
|
||||
|
||||
# https://github.com/mongodb/specifications/tree/master/source/crud/tests
|
||||
# Note: tests 1 and 2 are in test_read_write_concern_spec.py
|
||||
class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
@ -92,7 +93,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
self.max_message_size_bytes = client_context.max_message_size_bytes
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
def test_batch_splits_if_num_operations_too_large(self):
|
||||
def test_3_batch_splits_if_num_operations_too_large(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -116,7 +117,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
self.assertEqual(first_event.operation_id, second_event.operation_id)
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
def test_batch_splits_if_ops_payload_too_large(self):
|
||||
def test_4_batch_splits_if_ops_payload_too_large(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -148,7 +149,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
@client_context.require_failCommand_fail_point
|
||||
def test_collects_write_concern_errors_across_batches(self):
|
||||
def test_5_collects_write_concern_errors_across_batches(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(
|
||||
event_listeners=[listener],
|
||||
@ -189,7 +190,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
self.assertEqual(len(bulk_write_events), 2)
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
def test_collects_write_errors_across_batches_unordered(self):
|
||||
def test_6_collects_write_errors_across_batches_unordered(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -218,7 +219,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
self.assertEqual(len(bulk_write_events), 2)
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
def test_collects_write_errors_across_batches_ordered(self):
|
||||
def test_6_collects_write_errors_across_batches_ordered(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -247,7 +248,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
self.assertEqual(len(bulk_write_events), 1)
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
def test_handles_cursor_requiring_getMore(self):
|
||||
def test_7_handles_cursor_requiring_getMore(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -287,7 +288,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
@client_context.require_no_standalone
|
||||
def test_handles_cursor_requiring_getMore_within_transaction(self):
|
||||
def test_8_handles_cursor_requiring_getMore_within_transaction(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -329,7 +330,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
@client_context.require_failCommand_fail_point
|
||||
def test_handles_getMore_error(self):
|
||||
def test_9_handles_getMore_error(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -382,7 +383,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
self.assertTrue(kill_cursors_event)
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
def test_returns_error_if_unacknowledged_too_large_insert(self):
|
||||
def test_10_returns_error_if_unacknowledged_too_large_insert(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -437,7 +438,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
return num_models, models
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
def test_no_batch_splits_if_new_namespace_is_not_too_large(self):
|
||||
def test_11_no_batch_splits_if_new_namespace_is_not_too_large(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -467,7 +468,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
self.assertEqual(event.command["nsInfo"][0]["ns"], "db.coll")
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
def test_batch_splits_if_new_namespace_is_too_large(self):
|
||||
def test_11_batch_splits_if_new_namespace_is_too_large(self):
|
||||
listener = OvertCommandListener()
|
||||
client = self.rs_or_single_client(event_listeners=[listener])
|
||||
|
||||
@ -504,25 +505,27 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
self.assertEqual(second_event.command["nsInfo"][0]["ns"], namespace)
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
def test_returns_error_if_no_writes_can_be_added_to_ops(self):
|
||||
def test_12_returns_error_if_no_writes_can_be_added_to_ops(self):
|
||||
client = self.rs_or_single_client()
|
||||
|
||||
# Document too large.
|
||||
b_repeated = "b" * self.max_message_size_bytes
|
||||
models = [InsertOne(namespace="db.coll", document={"a": b_repeated})]
|
||||
with self.assertRaises(DocumentTooLarge):
|
||||
with self.assertRaises(DocumentTooLarge) as context:
|
||||
client.bulk_write(models=models)
|
||||
self.assertIsNone(context.exception.partial_result)
|
||||
|
||||
# Namespace too large.
|
||||
c_repeated = "c" * self.max_message_size_bytes
|
||||
namespace = f"db.{c_repeated}"
|
||||
models = [InsertOne(namespace=namespace, document={"a": "b"})]
|
||||
with self.assertRaises(DocumentTooLarge):
|
||||
with self.assertRaises(DocumentTooLarge) as context:
|
||||
client.bulk_write(models=models)
|
||||
self.assertIsNone(context.exception.partial_result)
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
@unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed")
|
||||
def test_returns_error_if_auto_encryption_configured(self):
|
||||
def test_13_returns_error_if_auto_encryption_configured(self):
|
||||
opts = AutoEncryptionOpts(
|
||||
key_vault_namespace="db.coll",
|
||||
kms_providers={"aws": {"accessKeyId": "foo", "secretAccessKey": "bar"}},
|
||||
@ -532,6 +535,7 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
models = [InsertOne(namespace="db.coll", document={"a": "b"})]
|
||||
with self.assertRaises(InvalidOperation) as context:
|
||||
client.bulk_write(models=models)
|
||||
self.assertIsNone(context.exception.partial_result)
|
||||
self.assertIn(
|
||||
"bulk_write does not currently support automatic encryption", context.exception._message
|
||||
)
|
||||
@ -575,6 +579,8 @@ class TestClientBulkWriteCRUD(IntegrationTest):
|
||||
self.assertEqual(result.update_results[1].did_upsert, True)
|
||||
self.assertEqual(result.update_results[2].did_upsert, False)
|
||||
|
||||
# Note: test 14 is optional and intentionally not implemented because we provide multiple APIs to specify explain.
|
||||
|
||||
@client_context.require_version_min(8, 0, 0, -24)
|
||||
def test_15_unacknowledged_write_across_batches(self):
|
||||
listener = OvertCommandListener()
|
||||
|
||||
@ -178,6 +178,8 @@ class TestReadWriteConcernSpec(IntegrationTest):
|
||||
self.disable_replication(client_context.client)
|
||||
self.assertWriteOpsRaise(WriteConcern(w=client_context.w, wtimeout=1), WTimeoutError)
|
||||
|
||||
# https://github.com/mongodb/specifications/tree/master/source/crud/tests
|
||||
# Test 1 (included here instead of test_client_bulk_write.py)
|
||||
@client_context.require_failCommand_fail_point
|
||||
def test_error_includes_errInfo(self):
|
||||
expected_wce = {
|
||||
@ -212,6 +214,8 @@ class TestReadWriteConcernSpec(IntegrationTest):
|
||||
}
|
||||
self.assertEqual(ctx.exception.details, expected_details)
|
||||
|
||||
# https://github.com/mongodb/specifications/tree/master/source/crud/tests
|
||||
# Test 2 (included here instead of test_client_bulk_write.py)
|
||||
@client_context.require_version_min(4, 9)
|
||||
def test_write_error_details_exposes_errinfo(self):
|
||||
listener = OvertCommandListener()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user