Skip to content

Commit 8a9c4cb

Browse files
committed
add async tests (PYTHON-5403)
1 parent 265ef3b commit 8a9c4cb

File tree

3 files changed

+215
-16
lines changed

3 files changed

+215
-16
lines changed
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Copyright 2013-present 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+
from __future__ import annotations
15+
16+
import asyncio
17+
import time
18+
import unittest
19+
from test.asynchronous import AsyncIntegrationTest
20+
from test.utils_shared import CMAPListener
21+
from typing import Any, Optional
22+
23+
import pytest
24+
from mockupdb import MockupDB, OpMsgReply
25+
26+
from pymongo import AsyncMongoClient, MongoClient
27+
from pymongo.driver_info import DriverInfo
28+
from pymongo.monitoring import ConnectionClosedEvent
29+
30+
pytestmark = pytest.mark.mockupdb
31+
32+
_IS_SYNC = False
33+
34+
35+
def _get_handshake_driver_info(request):
36+
assert "client" in request
37+
return request["client"]
38+
39+
40+
class TestClientMetadataProse(AsyncIntegrationTest):
41+
async def asyncSetUp(self):
42+
await super().asyncSetUp()
43+
self.server = MockupDB()
44+
self.handshake_req = None
45+
46+
def respond(r):
47+
if "ismaster" in r:
48+
# then this is a handshake request
49+
self.handshake_req = r
50+
return r.reply(OpMsgReply(minWireVersion=0, maxWireVersion=13))
51+
52+
self.server.autoresponds(respond)
53+
self.server.run()
54+
self.addAsyncCleanup(self.server.stop)
55+
56+
async def send_ping_and_get_metadata(
57+
self, client: AsyncMongoClient, is_handshake: bool
58+
) -> tuple[str, Optional[str], Optional[str], dict[str, Any]]:
59+
# reset if handshake request
60+
if is_handshake:
61+
self.handshake_req: Optional[dict] = None
62+
63+
await client.admin.command("ping")
64+
metadata = _get_handshake_driver_info(self.handshake_req)
65+
driver_metadata = metadata["driver"]
66+
name, version, platform = (
67+
driver_metadata["name"],
68+
driver_metadata["version"],
69+
metadata["platform"],
70+
)
71+
return name, version, platform, metadata
72+
73+
async def check_metadata_added(
74+
self,
75+
client: AsyncMongoClient,
76+
add_name: str,
77+
add_version: Optional[str],
78+
add_platform: Optional[str],
79+
) -> None:
80+
# send initial metadata
81+
name, version, platform, metadata = await self.send_ping_and_get_metadata(client, True)
82+
await asyncio.sleep(0.005)
83+
84+
# add new metadata
85+
client.append_metadata(DriverInfo(add_name, add_version, add_platform))
86+
new_name, new_version, new_platform, new_metadata = await self.send_ping_and_get_metadata(
87+
client, True
88+
)
89+
self.assertEqual(new_name, f"{name}|{add_name}" if add_name is not None else name)
90+
self.assertEqual(
91+
new_version,
92+
f"{version}|{add_version}" if add_version is not None else version,
93+
)
94+
self.assertEqual(
95+
new_platform,
96+
f"{platform}|{add_platform}" if add_platform is not None else platform,
97+
)
98+
99+
metadata.pop("driver")
100+
metadata.pop("platform")
101+
new_metadata.pop("driver")
102+
new_metadata.pop("platform")
103+
self.assertEqual(metadata, new_metadata)
104+
105+
async def test_append_metadata(self):
106+
client = AsyncMongoClient(
107+
"mongodb://" + self.server.address_string,
108+
maxIdleTimeMS=1,
109+
driver=DriverInfo("library", "1.2", "Library Platform"),
110+
)
111+
await self.check_metadata_added(client, "framework", "2.0", "Framework Platform")
112+
await client.close()
113+
114+
async def test_append_metadata_platform_none(self):
115+
client = AsyncMongoClient(
116+
"mongodb://" + self.server.address_string,
117+
maxIdleTimeMS=1,
118+
driver=DriverInfo("library", "1.2", "Library Platform"),
119+
)
120+
await self.check_metadata_added(client, "framework", "2.0", None)
121+
await client.close()
122+
123+
async def test_append_metadata_version_none(self):
124+
client = AsyncMongoClient(
125+
"mongodb://" + self.server.address_string,
126+
maxIdleTimeMS=1,
127+
driver=DriverInfo("library", "1.2", "Library Platform"),
128+
)
129+
await self.check_metadata_added(client, "framework", None, "Framework Platform")
130+
await client.close()
131+
132+
async def test_append_metadata_platform_version_none(self):
133+
client = AsyncMongoClient(
134+
"mongodb://" + self.server.address_string,
135+
maxIdleTimeMS=1,
136+
driver=DriverInfo("library", "1.2", "Library Platform"),
137+
)
138+
await self.check_metadata_added(client, "framework", None, None)
139+
await client.close()
140+
141+
async def test_multiple_successive_metadata_updates(self):
142+
client = AsyncMongoClient(
143+
"mongodb://" + self.server.address_string, maxIdleTimeMS=1, connect=False
144+
)
145+
client.append_metadata(DriverInfo("library", "1.2", "Library Platform"))
146+
await self.check_metadata_added(client, "framework", "2.0", "Framework Platform")
147+
await client.close()
148+
149+
async def test_multiple_successive_metadata_updates_platform_none(self):
150+
client = AsyncMongoClient(
151+
"mongodb://" + self.server.address_string,
152+
maxIdleTimeMS=1,
153+
)
154+
client.append_metadata(DriverInfo("library", "1.2", "Library Platform"))
155+
await self.check_metadata_added(client, "framework", "2.0", None)
156+
await client.close()
157+
158+
async def test_multiple_successive_metadata_updates_version_none(self):
159+
client = AsyncMongoClient(
160+
"mongodb://" + self.server.address_string,
161+
maxIdleTimeMS=1,
162+
)
163+
client.append_metadata(DriverInfo("library", "1.2", "Library Platform"))
164+
await self.check_metadata_added(client, "framework", None, "Framework Platform")
165+
await client.close()
166+
167+
async def test_multiple_successive_metadata_updates_platform_version_none(self):
168+
client = AsyncMongoClient(
169+
"mongodb://" + self.server.address_string,
170+
maxIdleTimeMS=1,
171+
)
172+
client.append_metadata(DriverInfo("library", "1.2", "Library Platform"))
173+
await self.check_metadata_added(client, "framework", None, None)
174+
await client.close()
175+
176+
async def test_doesnt_update_established_connections(self):
177+
listener = CMAPListener()
178+
client = AsyncMongoClient(
179+
"mongodb://" + self.server.address_string,
180+
maxIdleTimeMS=1,
181+
driver=DriverInfo("library", "1.2", "Library Platform"),
182+
event_listeners=[listener],
183+
)
184+
185+
# send initial metadata
186+
name, version, platform, metadata = await self.send_ping_and_get_metadata(client, True)
187+
self.assertIsNotNone(name)
188+
self.assertIsNotNone(version)
189+
self.assertIsNotNone(platform)
190+
191+
# add data
192+
add_name, add_version, add_platform = "framework", "2.0", "Framework Platform"
193+
client.append_metadata(DriverInfo(add_name, add_version, add_platform))
194+
# check new data isn't sent
195+
self.handshake_req: Optional[dict] = None
196+
await client.admin.command("ping")
197+
self.assertIsNone(self.handshake_req)
198+
self.assertEqual(listener.event_count(ConnectionClosedEvent), 0)
199+
200+
await client.close()
201+
202+
203+
if __name__ == "__main__":
204+
unittest.main()

test/mockupdb/test_client_metadata.py renamed to test/test_client_metadata.py

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,37 +13,35 @@
1313
# limitations under the License.
1414
from __future__ import annotations
1515

16+
import asyncio
1617
import time
1718
import unittest
19+
from test import IntegrationTest
1820
from test.utils_shared import CMAPListener
1921
from typing import Any, Optional
2022

2123
import pytest
24+
from mockupdb import MockupDB, OpMsgReply
2225

2326
from pymongo import MongoClient
2427
from pymongo.driver_info import DriverInfo
2528
from pymongo.monitoring import ConnectionClosedEvent
2629

27-
try:
28-
from mockupdb import MockupDB, OpMsgReply
29-
30-
_HAVE_MOCKUPDB = True
31-
except ImportError:
32-
_HAVE_MOCKUPDB = False
33-
3430
pytestmark = pytest.mark.mockupdb
3531

32+
_IS_SYNC = True
33+
3634

3735
def _get_handshake_driver_info(request):
3836
assert "client" in request
3937
return request["client"]
4038

4139

42-
class TestClientMetadataProse(unittest.TestCase):
40+
class TestClientMetadataProse(IntegrationTest):
4341
def setUp(self):
42+
super().setUp()
4443
self.server = MockupDB()
45-
# there are two handshake requests, i believe one is from the monitor, and the other is from the client
46-
self.handshake_req: Optional[dict] = None
44+
self.handshake_req = None
4745

4846
def respond(r):
4947
if "ismaster" in r:
@@ -58,9 +56,10 @@ def respond(r):
5856
def send_ping_and_get_metadata(
5957
self, client: MongoClient, is_handshake: bool
6058
) -> tuple[str, Optional[str], Optional[str], dict[str, Any]]:
61-
# reset
59+
# reset if handshake request
6260
if is_handshake:
6361
self.handshake_req: Optional[dict] = None
62+
6463
client.admin.command("ping")
6564
metadata = _get_handshake_driver_info(self.handshake_req)
6665
driver_metadata = metadata["driver"]
@@ -87,11 +86,6 @@ def check_metadata_added(
8786
new_name, new_version, new_platform, new_metadata = self.send_ping_and_get_metadata(
8887
client, True
8988
)
90-
print("IN SEND PING AND GET METADATA")
91-
print(name, version, platform)
92-
print(metadata)
93-
print(new_name, new_version, new_platform)
94-
print(new_metadata)
9589
self.assertEqual(new_name, f"{name}|{add_name}" if add_name is not None else name)
9690
self.assertEqual(
9791
new_version,

tools/synchro.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ def async_only_test(f: str) -> bool:
210210
"test_client.py",
211211
"test_client_bulk_write.py",
212212
"test_client_context.py",
213+
"test_client_metadata.py",
213214
"test_collation.py",
214215
"test_collection.py",
215216
"test_collection_management.py",

0 commit comments

Comments
 (0)