Skip to content

Commit 214caa5

Browse files
committed
Convert test.test_max_staleness to async
1 parent c8d3afd commit 214caa5

File tree

3 files changed

+156
-3
lines changed

3 files changed

+156
-3
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# Copyright 2016 MongoDB, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Test maxStalenessSeconds support."""
16+
from __future__ import annotations
17+
18+
import os
19+
import sys
20+
import time
21+
import warnings
22+
from pathlib import Path
23+
24+
from pymongo import AsyncMongoClient
25+
from pymongo.operations import _Op
26+
27+
sys.path[0:0] = [""]
28+
29+
from test.asynchronous import AsyncPyMongoTestCase, async_client_context, unittest
30+
from test.utils_selection_tests import create_selection_tests
31+
32+
from pymongo.errors import ConfigurationError
33+
from pymongo.server_selectors import writable_server_selector
34+
35+
_IS_SYNC = False
36+
37+
# Location of JSON test specifications.
38+
if _IS_SYNC:
39+
TEST_PATH = os.path.join(Path(__file__).resolve().parent, "max_staleness")
40+
else:
41+
TEST_PATH = os.path.join(Path(__file__).resolve().parent.parent, "max_staleness")
42+
43+
class TestAllScenarios(create_selection_tests(TEST_PATH)): # type: ignore
44+
pass
45+
46+
47+
class TestMaxStaleness(AsyncPyMongoTestCase):
48+
async def test_max_staleness(self):
49+
client = self.simple_client()
50+
self.assertEqual(-1, client.read_preference.max_staleness)
51+
52+
client = self.simple_client("mongodb://a/?readPreference=secondary")
53+
self.assertEqual(-1, client.read_preference.max_staleness)
54+
55+
# These tests are specified in max-staleness-tests.rst.
56+
with self.assertRaises(ConfigurationError):
57+
# Default read pref "primary" can't be used with max staleness.
58+
self.simple_client("mongodb://a/?maxStalenessSeconds=120")
59+
60+
with self.assertRaises(ConfigurationError):
61+
# Read pref "primary" can't be used with max staleness.
62+
self.simple_client("mongodb://a/?readPreference=primary&maxStalenessSeconds=120")
63+
64+
client = self.simple_client("mongodb://host/?maxStalenessSeconds=-1")
65+
self.assertEqual(-1, client.read_preference.max_staleness)
66+
67+
client = self.simple_client("mongodb://host/?readPreference=primary&maxStalenessSeconds=-1")
68+
self.assertEqual(-1, client.read_preference.max_staleness)
69+
70+
client = self.simple_client(
71+
"mongodb://host/?readPreference=secondary&maxStalenessSeconds=120"
72+
)
73+
self.assertEqual(120, client.read_preference.max_staleness)
74+
75+
client = self.simple_client("mongodb://a/?readPreference=secondary&maxStalenessSeconds=1")
76+
self.assertEqual(1, client.read_preference.max_staleness)
77+
78+
client = self.simple_client("mongodb://a/?readPreference=secondary&maxStalenessSeconds=-1")
79+
self.assertEqual(-1, client.read_preference.max_staleness)
80+
81+
client = self.simple_client(maxStalenessSeconds=-1, readPreference="nearest")
82+
self.assertEqual(-1, client.read_preference.max_staleness)
83+
84+
with self.assertRaises(TypeError):
85+
# Prohibit None.
86+
self.simple_client(maxStalenessSeconds=None, readPreference="nearest")
87+
88+
async def test_max_staleness_float(self):
89+
with self.assertRaises(TypeError) as ctx:
90+
await self.async_rs_or_single_client(maxStalenessSeconds=1.5, readPreference="nearest")
91+
92+
self.assertIn("must be an integer", str(ctx.exception))
93+
94+
with warnings.catch_warnings(record=True) as ctx:
95+
warnings.simplefilter("always")
96+
client = self.simple_client(
97+
"mongodb://host/?maxStalenessSeconds=1.5&readPreference=nearest"
98+
)
99+
100+
# Option was ignored.
101+
self.assertEqual(-1, client.read_preference.max_staleness)
102+
self.assertIn("must be an integer", str(ctx[0]))
103+
104+
async def test_max_staleness_zero(self):
105+
# Zero is too small.
106+
with self.assertRaises(ValueError) as ctx:
107+
await self.async_rs_or_single_client(maxStalenessSeconds=0, readPreference="nearest")
108+
109+
self.assertIn("must be a positive integer", str(ctx.exception))
110+
111+
with warnings.catch_warnings(record=True) as ctx:
112+
warnings.simplefilter("always")
113+
client = self.simple_client(
114+
"mongodb://host/?maxStalenessSeconds=0&readPreference=nearest"
115+
)
116+
117+
# Option was ignored.
118+
self.assertEqual(-1, client.read_preference.max_staleness)
119+
self.assertIn("must be a positive integer", str(ctx[0]))
120+
121+
@async_client_context.require_replica_set
122+
async def test_last_write_date(self):
123+
# From max-staleness-tests.rst, "Parse lastWriteDate".
124+
client = await self.async_rs_or_single_client(heartbeatFrequencyMS=500)
125+
await client.pymongo_test.test.insert_one({})
126+
# Wait for the server description to be updated.
127+
time.sleep(1)
128+
server = await client._topology.select_server(writable_server_selector, _Op.TEST)
129+
first = server.description.last_write_date
130+
self.assertTrue(first)
131+
# The first last_write_date may correspond to a internal server write,
132+
# sleep so that the next write does not occur within the same second.
133+
time.sleep(1)
134+
await client.pymongo_test.test.insert_one({})
135+
# Wait for the server description to be updated.
136+
time.sleep(1)
137+
server = await client._topology.select_server(writable_server_selector, _Op.TEST)
138+
second = server.description.last_write_date
139+
assert first is not None
140+
141+
assert second is not None
142+
self.assertGreater(second, first)
143+
self.assertLess(second, first + 10)
144+
145+
146+
if __name__ == "__main__":
147+
unittest.main()

test/test_max_staleness.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import sys
2020
import time
2121
import warnings
22+
from pathlib import Path
2223

2324
from pymongo import MongoClient
2425
from pymongo.operations import _Op
@@ -31,11 +32,15 @@
3132
from pymongo.errors import ConfigurationError
3233
from pymongo.server_selectors import writable_server_selector
3334

34-
# Location of JSON test specifications.
35-
_TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "max_staleness")
35+
_IS_SYNC = True
3636

37+
# Location of JSON test specifications.
38+
if _IS_SYNC:
39+
TEST_PATH = os.path.join(Path(__file__).resolve().parent, "max_staleness")
40+
else:
41+
TEST_PATH = os.path.join(Path(__file__).resolve().parent.parent, "max_staleness")
3742

38-
class TestAllScenarios(create_selection_tests(_TEST_PATH)): # type: ignore
43+
class TestAllScenarios(create_selection_tests(TEST_PATH)): # type: ignore
3944
pass
4045

4146

tools/synchro.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ def async_only_test(f: str) -> bool:
215215
"test_gridfs_spec.py",
216216
"test_logger.py",
217217
"test_monitoring.py",
218+
"test_max_staleness.py",
218219
"test_raw_bson.py",
219220
"test_retryable_reads.py",
220221
"test_retryable_writes.py",

0 commit comments

Comments
 (0)