Skip to content

Commit 0351a0e

Browse files
committed
add tests for DatabaseFeatures.supports_transactions
1 parent 0615e3e commit 0351a0e

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
@@ -106,28 +106,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
106106
"test_utils.tests.CaptureOnCommitCallbacksTests.test_with_rolled_back_savepoint",
107107
}
108108

109-
@cached_property
110-
def supports_transactions(self):
111-
"""Confirm support for transactions."""
112-
is_replica_set = False
113-
is_sharded_cluster = False
114-
with self.connection.cursor():
115-
client = self.connection.connection
116-
hello_response = client.admin.command("hello")
117-
server_status = client.admin.command("serverStatus")
118-
if "setName" in hello_response:
119-
is_replica_set = True
120-
if "msg" in hello_response and hello_response["msg"] == "isdbgrid":
121-
is_sharded_cluster = True
122-
if (
123-
"storageEngine" in server_status
124-
and server_status["storageEngine"].get("name") == "wiredTiger"
125-
):
126-
is_wired_tiger = True
127-
if (is_replica_set or is_sharded_cluster) and is_wired_tiger:
128-
return True
129-
return False
130-
131109
@cached_property
132110
def django_test_expected_failures(self):
133111
expected_failures = super().django_test_expected_failures
@@ -615,3 +593,19 @@ def supports_atlas_search(self):
615593
def supports_select_union(self):
616594
# Stage not supported inside of a multi-document transaction: $unionWith
617595
return not self.supports_transactions
596+
597+
@cached_property
598+
def supports_transactions(self):
599+
"""
600+
Transactions are enabled if the MongoDB configuration supports it:
601+
MongoDB must be configured as a replica set or sharded cluster, and
602+
the store engine must be WiredTiger.
603+
"""
604+
client = self.connection.connection.admin
605+
hello_response = client.command("hello")
606+
is_replica_set = "setName" in hello_response
607+
is_sharded_cluster = hello_response.get("msg") == "isdbgrid"
608+
if is_replica_set or is_sharded_cluster:
609+
engine = client.command("serverStatus").get("storageEngine", {})
610+
return engine.get("name") == "wiredTiger"
611+
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)