Skip to content

Commit 6bdaf19

Browse files
authored
PYTHON-4617 Skip unified retryable writes tests on MMAPv1 (#1841)
1 parent 1eb3b85 commit 6bdaf19

File tree

6 files changed

+62
-248
lines changed

6 files changed

+62
-248
lines changed

test/asynchronous/test_transactions.py

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,14 @@
1515
"""Execute Transactions Spec tests."""
1616
from __future__ import annotations
1717

18-
import os
1918
import sys
2019
from io import BytesIO
2120

2221
from gridfs.asynchronous.grid_file import AsyncGridFS, AsyncGridFSBucket
2322

2423
sys.path[0:0] = [""]
2524

26-
from test.asynchronous import async_client_context, unittest
27-
from test.asynchronous.utils_spec_runner import AsyncSpecRunner
25+
from test.asynchronous import AsyncIntegrationTest, async_client_context, unittest
2826
from test.utils import (
2927
OvertCommandListener,
3028
async_rs_client,
@@ -54,40 +52,14 @@
5452

5553
_IS_SYNC = False
5654

57-
_TXN_TESTS_DEBUG = os.environ.get("TRANSACTION_TESTS_DEBUG")
58-
5955
# Max number of operations to perform after a transaction to prove unpinning
6056
# occurs. Chosen so that there's a low false positive rate. With 2 mongoses,
6157
# 50 attempts yields a one in a quadrillion chance of a false positive
6258
# (1/(0.5^50)).
6359
UNPIN_TEST_MAX_ATTEMPTS = 50
6460

6561

66-
class AsyncTransactionsBase(AsyncSpecRunner):
67-
@classmethod
68-
async def _setup_class(cls):
69-
await super()._setup_class()
70-
if async_client_context.supports_transactions():
71-
for address in async_client_context.mongoses:
72-
cls.mongos_clients.append(await async_single_client("{}:{}".format(*address)))
73-
74-
@classmethod
75-
async def _tearDown_class(cls):
76-
for client in cls.mongos_clients:
77-
await client.close()
78-
await super()._tearDown_class()
79-
80-
def maybe_skip_scenario(self, test):
81-
super().maybe_skip_scenario(test)
82-
if (
83-
"secondary" in self.id()
84-
and not async_client_context.is_mongos
85-
and not async_client_context.has_secondaries
86-
):
87-
raise unittest.SkipTest("No secondaries")
88-
89-
90-
class TestTransactions(AsyncTransactionsBase):
62+
class TestTransactions(AsyncIntegrationTest):
9163
RUN_ON_SERVERLESS = True
9264

9365
@async_client_context.require_transactions
@@ -421,7 +393,31 @@ def __exit__(self, exc_type, exc_val, exc_tb):
421393
client_session._WITH_TRANSACTION_RETRY_TIME_LIMIT = self.real_timeout
422394

423395

424-
class TestTransactionsConvenientAPI(AsyncTransactionsBase):
396+
class TestTransactionsConvenientAPI(AsyncIntegrationTest):
397+
@classmethod
398+
async def _setup_class(cls):
399+
await super()._setup_class()
400+
cls.mongos_clients = []
401+
if async_client_context.supports_transactions():
402+
for address in async_client_context.mongoses:
403+
cls.mongos_clients.append(await async_single_client("{}:{}".format(*address)))
404+
405+
@classmethod
406+
async def _tearDown_class(cls):
407+
for client in cls.mongos_clients:
408+
await client.close()
409+
await super()._tearDown_class()
410+
411+
async def _set_fail_point(self, client, command_args):
412+
cmd = {"configureFailPoint": "failCommand"}
413+
cmd.update(command_args)
414+
await client.admin.command(cmd)
415+
416+
async def set_fail_point(self, command_args):
417+
clients = self.mongos_clients if self.mongos_clients else [self.client]
418+
for client in clients:
419+
await self._set_fail_point(client, command_args)
420+
425421
@async_client_context.require_transactions
426422
async def test_callback_raises_custom_error(self):
427423
class _MyException(Exception):

test/crud_v2_format.py

Lines changed: 0 additions & 55 deletions
This file was deleted.

test/test_retryable_reads.py

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import sys
2121
import threading
2222

23-
from bson import SON
2423
from pymongo.errors import AutoReconnect
2524

2625
sys.path[0:0] = [""]
@@ -34,14 +33,10 @@
3433
)
3534
from test.utils import (
3635
CMAPListener,
37-
EventListener,
3836
OvertCommandListener,
39-
SpecTestCreator,
40-
rs_client,
4137
rs_or_single_client,
4238
set_fail_point,
4339
)
44-
from test.utils_spec_runner import SpecRunner
4540

4641
from pymongo.monitoring import (
4742
ConnectionCheckedOutEvent,
@@ -50,7 +45,6 @@
5045
PoolClearedEvent,
5146
)
5247
from pymongo.synchronous.mongo_client import MongoClient
53-
from pymongo.write_concern import WriteConcern
5448

5549
# Location of JSON test specifications.
5650
_TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "retryable_reads", "legacy")
@@ -74,81 +68,6 @@ def test_uri(self):
7468
self.assertEqual(client.options.retry_reads, False)
7569

7670

77-
class TestSpec(SpecRunner):
78-
RUN_ON_LOAD_BALANCER = True
79-
RUN_ON_SERVERLESS = True
80-
81-
@classmethod
82-
@client_context.require_failCommand_fail_point
83-
# TODO: remove this once PYTHON-1948 is done.
84-
@client_context.require_no_mmap
85-
def setUpClass(cls):
86-
super().setUpClass()
87-
88-
def maybe_skip_scenario(self, test):
89-
super().maybe_skip_scenario(test)
90-
skip_names = ["listCollectionObjects", "listIndexNames", "listDatabaseObjects"]
91-
for name in skip_names:
92-
if name.lower() in test["description"].lower():
93-
self.skipTest(f"PyMongo does not support {name}")
94-
95-
# Serverless does not support $out and collation.
96-
if client_context.serverless:
97-
for operation in test["operations"]:
98-
if operation["name"] == "aggregate":
99-
for stage in operation["arguments"]["pipeline"]:
100-
if "$out" in stage:
101-
self.skipTest("MongoDB Serverless does not support $out")
102-
if "collation" in operation["arguments"]:
103-
self.skipTest("MongoDB Serverless does not support collations")
104-
105-
# Skip changeStream related tests on MMAPv1 and serverless.
106-
test_name = self.id().rsplit(".")[-1]
107-
if "changestream" in test_name.lower():
108-
if client_context.storage_engine == "mmapv1":
109-
self.skipTest("MMAPv1 does not support change streams.")
110-
if client_context.serverless:
111-
self.skipTest("Serverless does not support change streams.")
112-
113-
def get_scenario_coll_name(self, scenario_def):
114-
"""Override a test's collection name to support GridFS tests."""
115-
if "bucket_name" in scenario_def:
116-
return scenario_def["bucket_name"]
117-
return super().get_scenario_coll_name(scenario_def)
118-
119-
def setup_scenario(self, scenario_def):
120-
"""Override a test's setup to support GridFS tests."""
121-
if "bucket_name" in scenario_def:
122-
data = scenario_def["data"]
123-
db_name = self.get_scenario_db_name(scenario_def)
124-
db = client_context.client[db_name]
125-
# Create a bucket for the retryable reads GridFS tests with as few
126-
# majority writes as possible.
127-
wc = WriteConcern(w="majority")
128-
if data:
129-
db["fs.chunks"].drop()
130-
db["fs.files"].drop()
131-
db["fs.chunks"].insert_many(data["fs.chunks"])
132-
db.get_collection("fs.files", write_concern=wc).insert_many(data["fs.files"])
133-
else:
134-
db.get_collection("fs.chunks").drop()
135-
db.get_collection("fs.files", write_concern=wc).drop()
136-
else:
137-
super().setup_scenario(scenario_def)
138-
139-
140-
def create_test(scenario_def, test, name):
141-
@client_context.require_test_commands
142-
def run_scenario(self):
143-
self.run_scenario(scenario_def, test)
144-
145-
return run_scenario
146-
147-
148-
test_creator = SpecTestCreator(create_test, TestSpec, _TEST_PATH)
149-
test_creator.create_tests()
150-
151-
15271
class FindThread(threading.Thread):
15372
def __init__(self, collection):
15473
super().__init__()

test/test_retryable_writes.py

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from __future__ import annotations
1717

1818
import copy
19-
import os
2019
import pprint
2120
import sys
2221
import threading
@@ -29,11 +28,9 @@
2928
DeprecationFilter,
3029
EventListener,
3130
OvertCommandListener,
32-
SpecTestCreator,
3331
rs_or_single_client,
3432
set_fail_point,
3533
)
36-
from test.utils_spec_runner import SpecRunner
3734
from test.version import Version
3835

3936
from bson.codec_options import DEFAULT_CODEC_OPTIONS
@@ -65,9 +62,6 @@
6562
from pymongo.synchronous.mongo_client import MongoClient
6663
from pymongo.write_concern import WriteConcern
6764

68-
# Location of JSON test specifications.
69-
_TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "retryable_writes", "legacy")
70-
7165

7266
class InsertEventListener(EventListener):
7367
def succeeded(self, event: CommandSucceededEvent) -> None:
@@ -89,44 +83,6 @@ def succeeded(self, event: CommandSucceededEvent) -> None:
8983
)
9084

9185

92-
class TestAllScenarios(SpecRunner):
93-
RUN_ON_LOAD_BALANCER = True
94-
RUN_ON_SERVERLESS = True
95-
96-
def get_object_name(self, op):
97-
return op.get("object", "collection")
98-
99-
def get_scenario_db_name(self, scenario_def):
100-
return scenario_def.get("database_name", "pymongo_test")
101-
102-
def get_scenario_coll_name(self, scenario_def):
103-
return scenario_def.get("collection_name", "test")
104-
105-
def run_test_ops(self, sessions, collection, test):
106-
# Transform retryable writes spec format into transactions.
107-
operation = test["operation"]
108-
outcome = test["outcome"]
109-
if "error" in outcome:
110-
operation["error"] = outcome["error"]
111-
if "result" in outcome:
112-
operation["result"] = outcome["result"]
113-
test["operations"] = [operation]
114-
super().run_test_ops(sessions, collection, test)
115-
116-
117-
def create_test(scenario_def, test, name):
118-
@client_context.require_test_commands
119-
@client_context.require_no_mmap
120-
def run_scenario(self):
121-
self.run_scenario(scenario_def, test)
122-
123-
return run_scenario
124-
125-
126-
test_creator = SpecTestCreator(create_test, TestAllScenarios, _TEST_PATH)
127-
test_creator.create_tests()
128-
129-
13086
def retryable_single_statement_ops(coll):
13187
return [
13288
(coll.bulk_write, [[InsertOne({}), InsertOne({})]], {}),

0 commit comments

Comments
 (0)