Skip to content

Commit 07df027

Browse files
committed
add tests for DatabaseFeatures.supports_transactions
1 parent f26e114 commit 07df027

File tree

2 files changed

+92
-22
lines changed

2 files changed

+92
-22
lines changed

django_mongodb_backend/features.py

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -102,28 +102,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
102102
"get_or_create.tests.UpdateOrCreateTestsWithManualPKs.test_create_with_duplicate_primary_key",
103103
}
104104

105-
@cached_property
106-
def supports_transactions(self):
107-
"""Confirm support for transactions."""
108-
is_replica_set = False
109-
is_sharded_cluster = False
110-
with self.connection.cursor():
111-
client = self.connection.connection
112-
hello_response = client.admin.command("hello")
113-
server_status = client.admin.command("serverStatus")
114-
if "setName" in hello_response:
115-
is_replica_set = True
116-
if "msg" in hello_response and hello_response["msg"] == "isdbgrid":
117-
is_sharded_cluster = True
118-
if (
119-
"storageEngine" in server_status
120-
and server_status["storageEngine"].get("name") == "wiredTiger"
121-
):
122-
is_wired_tiger = True
123-
if (is_replica_set or is_sharded_cluster) and is_wired_tiger:
124-
return True
125-
return False
126-
127105
@cached_property
128106
def django_test_expected_failures(self):
129107
expected_failures = super().django_test_expected_failures
@@ -611,3 +589,19 @@ def supports_atlas_search(self):
611589
def supports_select_union(self):
612590
# Stage not supported inside of a multi-document transaction: $unionWith
613591
return not self.supports_transactions
592+
593+
@cached_property
594+
def supports_transactions(self):
595+
"""
596+
Transactions are enabled if the MongoDB configuration supports it:
597+
MongoDB must be configured as a replica set or sharded cluster, and
598+
the store engine must be WiredTiger.
599+
"""
600+
client = self.connection.connection.admin
601+
hello_response = client.command("hello")
602+
is_replica_set = "setName" in hello_response
603+
is_sharded_cluster = hello_response.get("msg") == "isdbgrid"
604+
if is_replica_set or is_sharded_cluster:
605+
engine = client.command("serverStatus").get("storageEngine", {})
606+
return engine.get("name") == "wiredTiger"
607+
return False

tests/backend_/test_features.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from unittest.mock import patch
2+
3+
from django.db import connection
4+
from django.test import TestCase
5+
6+
7+
class SupportsTransactionsTests(TestCase):
8+
def setUp(self):
9+
# Clear the cached property.
10+
del connection.features.supports_transactions
11+
12+
def tearDown(self):
13+
del connection.features.supports_transactions
14+
15+
def test_replica_set(self):
16+
"""A replica set supports transactions."""
17+
18+
def mocked_command(command):
19+
if command == "hello":
20+
return {"setName": "foo"}
21+
if command == "serverStatus":
22+
return {"storageEngine": {"name": "wiredTiger"}}
23+
raise Exception("Unexpected command")
24+
25+
with patch("pymongo.synchronous.database.Database.command", wraps=mocked_command):
26+
self.assertIs(connection.features.supports_transactions, True)
27+
28+
def test_replica_set_other_storage_engine(self):
29+
"""No support on a non-wiredTiger replica set."""
30+
31+
def mocked_command(command):
32+
if command == "hello":
33+
return {"setName": "foo"}
34+
if command == "serverStatus":
35+
return {"storageEngine": {"name": "other"}}
36+
raise Exception("Unexpected command")
37+
38+
with patch("pymongo.synchronous.database.Database.command", wraps=mocked_command):
39+
self.assertIs(connection.features.supports_transactions, False)
40+
41+
def test_sharded_cluster(self):
42+
"""A sharded cluster with wiredTiger storage engine supports them."""
43+
44+
def mocked_command(command):
45+
if command == "hello":
46+
return {"msg": "isdbgrid"}
47+
if command == "serverStatus":
48+
return {"storageEngine": {"name": "wiredTiger"}}
49+
raise Exception("Unexpected command")
50+
51+
with patch("pymongo.synchronous.database.Database.command", wraps=mocked_command):
52+
self.assertIs(connection.features.supports_transactions, True)
53+
54+
def test_sharded_cluster_other_storage_engine(self):
55+
"""No support on a non-wiredTiger shared cluster."""
56+
57+
def mocked_command(command):
58+
if command == "hello":
59+
return {"msg": "isdbgrid"}
60+
if command == "serverStatus":
61+
return {"storageEngine": {"name": "other"}}
62+
raise Exception("Unexpected command")
63+
64+
with patch("pymongo.synchronous.database.Database.command", wraps=mocked_command):
65+
self.assertIs(connection.features.supports_transactions, False)
66+
67+
def test_no_support(self):
68+
"""No support on a non-replica set, non-sharded cluster."""
69+
70+
def mocked_command(command):
71+
if command == "hello":
72+
return {}
73+
raise Exception("Unexpected command")
74+
75+
with patch("pymongo.synchronous.database.Database.command", wraps=mocked_command):
76+
self.assertIs(connection.features.supports_transactions, False)

0 commit comments

Comments
 (0)