diff --git a/test/asynchronous/test_client_bulk_write.py b/test/asynchronous/test_client_bulk_write.py index cf863979b5..49f969fa34 100644 --- a/test/asynchronous/test_client_bulk_write.py +++ b/test/asynchronous/test_client_bulk_write.py @@ -84,6 +84,7 @@ async def test_formats_write_error_correctly(self): # 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 @@ async def asyncSetUp(self): 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 @@ async def test_batch_splits_if_num_operations_too_large(self): 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 @@ async def test_batch_splits_if_ops_payload_too_large(self): @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 @@ async def test_collects_write_concern_errors_across_batches(self): 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 @@ async def test_collects_write_errors_across_batches_unordered(self): 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 @@ async def test_collects_write_errors_across_batches_ordered(self): 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 @@ async def test_handles_cursor_requiring_getMore(self): @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 @@ async def test_handles_cursor_requiring_getMore_within_transaction(self): @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 @@ async def test_handles_getMore_error(self): 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 @@ async def _setup_namespace_test_models(self): 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 @@ async def test_no_batch_splits_if_new_namespace_is_not_too_large(self): 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 @@ async def test_batch_splits_if_new_namespace_is_too_large(self): 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 @@ async def test_returns_error_if_auto_encryption_configured(self): 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 @@ async def test_upserted_result(self): 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() diff --git a/test/asynchronous/test_read_write_concern_spec.py b/test/asynchronous/test_read_write_concern_spec.py index 86f79fd28d..b5cb32932f 100644 --- a/test/asynchronous/test_read_write_concern_spec.py +++ b/test/asynchronous/test_read_write_concern_spec.py @@ -180,6 +180,8 @@ async def test_raise_wtimeout(self): 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 @@ async def test_error_includes_errInfo(self): } 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() diff --git a/test/test_client_bulk_write.py b/test/test_client_bulk_write.py index 1614e9f3cf..0cb6845099 100644 --- a/test/test_client_bulk_write.py +++ b/test/test_client_bulk_write.py @@ -84,6 +84,7 @@ def test_formats_write_error_correctly(self): # 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 @@ def setUp(self): 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 @@ def test_batch_splits_if_num_operations_too_large(self): 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 @@ def test_batch_splits_if_ops_payload_too_large(self): @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 @@ def test_collects_write_concern_errors_across_batches(self): 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 @@ def test_collects_write_errors_across_batches_unordered(self): 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 @@ def test_collects_write_errors_across_batches_ordered(self): 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 @@ def test_handles_cursor_requiring_getMore(self): @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 @@ def test_handles_cursor_requiring_getMore_within_transaction(self): @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 @@ def test_handles_getMore_error(self): 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 @@ def _setup_namespace_test_models(self): 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 @@ def test_no_batch_splits_if_new_namespace_is_not_too_large(self): 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 @@ def test_batch_splits_if_new_namespace_is_too_large(self): 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 @@ def test_returns_error_if_auto_encryption_configured(self): 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 @@ def test_upserted_result(self): 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() diff --git a/test/test_read_write_concern_spec.py b/test/test_read_write_concern_spec.py index 383dc70902..4b816b7af9 100644 --- a/test/test_read_write_concern_spec.py +++ b/test/test_read_write_concern_spec.py @@ -178,6 +178,8 @@ def test_raise_wtimeout(self): 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 @@ def test_error_includes_errInfo(self): } 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()