From d6dae9369dcf7dd8300dee3d45d093554e46fdff Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Tue, 4 Apr 2023 10:59:05 +0200 Subject: [PATCH 1/5] ADR 013: bolt_agent, user_agent update, Bolt 5.3 * Update the default `user_agent` to conform the new common format * Added support for Bolt 5.3 with the new `bolt_agent` string --- src/neo4j/_async/io/_bolt.py | 15 +- src/neo4j/_async/io/_bolt3.py | 6 +- src/neo4j/_async/io/_bolt4.py | 12 +- src/neo4j/_async/io/_bolt5.py | 22 +- src/neo4j/_conf.py | 2 +- src/neo4j/_meta.py | 35 +- src/neo4j/_sync/io/_bolt.py | 15 +- src/neo4j/_sync/io/_bolt3.py | 6 +- src/neo4j/_sync/io/_bolt4.py | 12 +- src/neo4j/_sync/io/_bolt5.py | 22 +- testkitbackend/test_config.json | 1 + tests/unit/async_/io/test_class_bolt.py | 12 +- tests/unit/async_/io/test_class_bolt3.py | 53 ++- tests/unit/async_/io/test_class_bolt4x0.py | 53 ++- tests/unit/async_/io/test_class_bolt4x1.py | 53 ++- tests/unit/async_/io/test_class_bolt4x2.py | 53 ++- tests/unit/async_/io/test_class_bolt4x3.py | 53 ++- tests/unit/async_/io/test_class_bolt4x4.py | 53 ++- tests/unit/async_/io/test_class_bolt5x0.py | 53 ++- tests/unit/async_/io/test_class_bolt5x1.py | 53 ++- tests/unit/async_/io/test_class_bolt5x2.py | 55 ++- tests/unit/async_/io/test_class_bolt5x3.py | 463 +++++++++++++++++++++ tests/unit/common/work/test_summary.py | 2 + tests/unit/sync/io/test_class_bolt.py | 12 +- tests/unit/sync/io/test_class_bolt3.py | 53 ++- tests/unit/sync/io/test_class_bolt4x0.py | 53 ++- tests/unit/sync/io/test_class_bolt4x1.py | 53 ++- tests/unit/sync/io/test_class_bolt4x2.py | 53 ++- tests/unit/sync/io/test_class_bolt4x3.py | 53 ++- tests/unit/sync/io/test_class_bolt4x4.py | 53 ++- tests/unit/sync/io/test_class_bolt5x0.py | 53 ++- tests/unit/sync/io/test_class_bolt5x1.py | 53 ++- tests/unit/sync/io/test_class_bolt5x2.py | 55 ++- tests/unit/sync/io/test_class_bolt5x3.py | 463 +++++++++++++++++++++ 34 files changed, 1979 insertions(+), 79 deletions(-) create mode 100644 tests/unit/async_/io/test_class_bolt5x3.py create mode 100644 tests/unit/sync/io/test_class_bolt5x3.py diff --git a/src/neo4j/_async/io/_bolt.py b/src/neo4j/_async/io/_bolt.py index 4c9ebfbb9..5f3eb9133 100644 --- a/src/neo4j/_async/io/_bolt.py +++ b/src/neo4j/_async/io/_bolt.py @@ -33,7 +33,7 @@ BoltError, BoltHandshakeError, ) -from ..._meta import get_user_agent +from ..._meta import BOLT_AGENT from ...addressing import Address from ...api import ( ServerInfo, @@ -131,11 +131,7 @@ def __init__(self, unresolved_address, sock, max_connection_lifetime, *, self.routing_context = routing_context self.idle_since = perf_counter() - # Determine the user agent - if user_agent: - self.user_agent = user_agent - else: - self.user_agent = get_user_agent() + self.user_agent = user_agent # Determine auth details if not auth: @@ -229,6 +225,7 @@ def protocol_handlers(cls, protocol_version=None): AsyncBolt5x0, AsyncBolt5x1, AsyncBolt5x2, + AsyncBolt5x3, ) handlers = { @@ -241,6 +238,7 @@ def protocol_handlers(cls, protocol_version=None): AsyncBolt5x0.PROTOCOL_VERSION: AsyncBolt5x0, AsyncBolt5x1.PROTOCOL_VERSION: AsyncBolt5x1, AsyncBolt5x2.PROTOCOL_VERSION: AsyncBolt5x2, + AsyncBolt5x3.PROTOCOL_VERSION: AsyncBolt5x3, } if protocol_version is None: @@ -355,7 +353,10 @@ async def open( # Carry out Bolt subclass imports locally to avoid circular dependency # issues. - if protocol_version == (5, 2): + if protocol_version == (5, 3): + from ._bolt5 import AsyncBolt5x3 + bolt_cls = AsyncBolt5x3 + elif protocol_version == (5, 2): from ._bolt5 import AsyncBolt5x2 bolt_cls = AsyncBolt5x2 elif protocol_version == (5, 1): diff --git a/src/neo4j/_async/io/_bolt3.py b/src/neo4j/_async/io/_bolt3.py index 483c525a0..a15a34804 100644 --- a/src/neo4j/_async/io/_bolt3.py +++ b/src/neo4j/_async/io/_bolt3.py @@ -21,6 +21,7 @@ from ssl import SSLSocket from ..._exceptions import BoltProtocolError +from ..._meta import BOLT_AGENT from ...api import ( READ_ACCESS, Version, @@ -135,8 +136,11 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): + user_agent = self.user_agent + if user_agent is None: + user_agent = BOLT_AGENT return { - "user_agent": self.user_agent, + "user_agent": user_agent, } async def hello(self, dehydration_hooks=None, hydration_hooks=None): diff --git a/src/neo4j/_async/io/_bolt4.py b/src/neo4j/_async/io/_bolt4.py index 10dc99e3f..9f27a8742 100644 --- a/src/neo4j/_async/io/_bolt4.py +++ b/src/neo4j/_async/io/_bolt4.py @@ -19,8 +19,8 @@ from logging import getLogger from ssl import SSLSocket -from ..._async_compat.util import AsyncUtil from ..._exceptions import BoltProtocolError +from ..._meta import BOLT_AGENT from ...api import ( READ_ACCESS, SYSTEM_DATABASE, @@ -93,8 +93,11 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): + user_agent = self.user_agent + if user_agent is None: + user_agent = BOLT_AGENT return { - "user_agent": self.user_agent, + "user_agent": user_agent, } async def hello(self, dehydration_hooks=None, hydration_hooks=None): @@ -377,8 +380,11 @@ def get_base_headers(self): enables server-side routing to propagate the same behaviour through its driver. """ + user_agent = self.user_agent + if user_agent is None: + user_agent = BOLT_AGENT headers = { - "user_agent": self.user_agent, + "user_agent": user_agent, } if self.routing_context is not None: headers["routing"] = self.routing_context diff --git a/src/neo4j/_async/io/_bolt5.py b/src/neo4j/_async/io/_bolt5.py index e545647e3..27dd03b63 100644 --- a/src/neo4j/_async/io/_bolt5.py +++ b/src/neo4j/_async/io/_bolt5.py @@ -21,6 +21,7 @@ from ..._codec.hydration import v2 as hydration_v2 from ..._exceptions import BoltProtocolError +from ..._meta import BOLT_AGENT from ...api import ( READ_ACCESS, Version, @@ -59,6 +60,8 @@ class AsyncBolt5x0(AsyncBolt): supports_multiple_databases = True + supports_notification_filtering = False + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._server_state_manager = ServerStateManager( @@ -88,7 +91,10 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): - headers = {"user_agent": self.user_agent} + user_agent = self.user_agent + if user_agent is None: + user_agent = BOLT_AGENT + headers = {"user_agent": user_agent} if self.routing_context is not None: headers["routing"] = self.routing_context return headers @@ -409,6 +415,8 @@ class AsyncBolt5x2(AsyncBolt5x1): PROTOCOL_VERSION = Version(5, 2) + supports_notification_filtering = True + def get_base_headers(self): headers = super().get_base_headers() if self.notifications_min_severity is not None: @@ -541,3 +549,15 @@ def begin(self, mode=None, bookmarks=None, metadata=None, timeout=None, self._append(b"\x11", (extra,), Response(self, "begin", hydration_hooks, **handlers), dehydration_hooks=dehydration_hooks) + + +class AsyncBolt5x3(AsyncBolt5x2): + + PROTOCOL_VERSION = Version(5, 3) + + def get_base_headers(self): + headers = super().get_base_headers() + if self.user_agent is None: + del headers["user_agent"] + headers["bolt_agent"] = BOLT_AGENT + return headers diff --git a/src/neo4j/_conf.py b/src/neo4j/_conf.py index b3a4d0b05..821a7dd6e 100644 --- a/src/neo4j/_conf.py +++ b/src/neo4j/_conf.py @@ -400,7 +400,7 @@ class PoolConfig(Config): # The use of this option is strongly discouraged. #: User Agent (Python Driver Specific) - user_agent = get_user_agent() + user_agent = None # Specify the client agent name. #: Socket Keep Alive (Python and .NET Driver Specific) diff --git a/src/neo4j/_meta.py b/src/neo4j/_meta.py index f8f8cd9c6..33fcd8eea 100644 --- a/src/neo4j/_meta.py +++ b/src/neo4j/_meta.py @@ -17,6 +17,8 @@ import asyncio +import platform +import sys import tracemalloc import typing as t from functools import wraps @@ -32,17 +34,34 @@ deprecated_package = False -def get_user_agent(): +def _compute_bolt_agent() -> str: + def format_version_info(version_info): + return "{}.{}.{}-{}-{}".format(*version_info) + + return ( + # product/version + f"neo4j-python/{version} " + # platform + f"({platform.system() or 'Unknown'} {platform.release() or 'unknown'}" + f"; {platform.machine() or 'unknown'}) " + # language/version + f"Python/{format_version_info(sys.version_info)} " + # language details + f"({platform.python_implementation()}; " + f"{format_version_info(sys.implementation.version)} " + f"({', '.join(platform.python_build())}) " + f"[{platform.python_compiler()}])" + ) + + +BOLT_AGENT = _compute_bolt_agent() + + +def get_user_agent() -> str: """ Obtain the default user agent string sent to the server after a successful handshake. """ - from sys import ( - platform, - version_info, - ) - template = "neo4j-python/{} Python/{}.{}.{}-{}-{} ({})" - fields = (version,) + tuple(version_info) + (platform,) - return template.format(*fields) + return BOLT_AGENT def _id(x): diff --git a/src/neo4j/_sync/io/_bolt.py b/src/neo4j/_sync/io/_bolt.py index 09f832e20..c7e82f455 100644 --- a/src/neo4j/_sync/io/_bolt.py +++ b/src/neo4j/_sync/io/_bolt.py @@ -33,7 +33,7 @@ BoltError, BoltHandshakeError, ) -from ..._meta import get_user_agent +from ..._meta import BOLT_AGENT from ...addressing import Address from ...api import ( ServerInfo, @@ -131,11 +131,7 @@ def __init__(self, unresolved_address, sock, max_connection_lifetime, *, self.routing_context = routing_context self.idle_since = perf_counter() - # Determine the user agent - if user_agent: - self.user_agent = user_agent - else: - self.user_agent = get_user_agent() + self.user_agent = user_agent # Determine auth details if not auth: @@ -229,6 +225,7 @@ def protocol_handlers(cls, protocol_version=None): Bolt5x0, Bolt5x1, Bolt5x2, + Bolt5x3, ) handlers = { @@ -241,6 +238,7 @@ def protocol_handlers(cls, protocol_version=None): Bolt5x0.PROTOCOL_VERSION: Bolt5x0, Bolt5x1.PROTOCOL_VERSION: Bolt5x1, Bolt5x2.PROTOCOL_VERSION: Bolt5x2, + Bolt5x3.PROTOCOL_VERSION: Bolt5x3, } if protocol_version is None: @@ -355,7 +353,10 @@ def open( # Carry out Bolt subclass imports locally to avoid circular dependency # issues. - if protocol_version == (5, 2): + if protocol_version == (5, 3): + from ._bolt5 import Bolt5x3 + bolt_cls = Bolt5x3 + elif protocol_version == (5, 2): from ._bolt5 import Bolt5x2 bolt_cls = Bolt5x2 elif protocol_version == (5, 1): diff --git a/src/neo4j/_sync/io/_bolt3.py b/src/neo4j/_sync/io/_bolt3.py index b98b3f25b..fd3d35875 100644 --- a/src/neo4j/_sync/io/_bolt3.py +++ b/src/neo4j/_sync/io/_bolt3.py @@ -21,6 +21,7 @@ from ssl import SSLSocket from ..._exceptions import BoltProtocolError +from ..._meta import BOLT_AGENT from ...api import ( READ_ACCESS, Version, @@ -135,8 +136,11 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): + user_agent = self.user_agent + if user_agent is None: + user_agent = BOLT_AGENT return { - "user_agent": self.user_agent, + "user_agent": user_agent, } def hello(self, dehydration_hooks=None, hydration_hooks=None): diff --git a/src/neo4j/_sync/io/_bolt4.py b/src/neo4j/_sync/io/_bolt4.py index 147a16868..062ad8839 100644 --- a/src/neo4j/_sync/io/_bolt4.py +++ b/src/neo4j/_sync/io/_bolt4.py @@ -19,8 +19,8 @@ from logging import getLogger from ssl import SSLSocket -from ..._async_compat.util import Util from ..._exceptions import BoltProtocolError +from ..._meta import BOLT_AGENT from ...api import ( READ_ACCESS, SYSTEM_DATABASE, @@ -93,8 +93,11 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): + user_agent = self.user_agent + if user_agent is None: + user_agent = BOLT_AGENT return { - "user_agent": self.user_agent, + "user_agent": user_agent, } def hello(self, dehydration_hooks=None, hydration_hooks=None): @@ -377,8 +380,11 @@ def get_base_headers(self): enables server-side routing to propagate the same behaviour through its driver. """ + user_agent = self.user_agent + if user_agent is None: + user_agent = BOLT_AGENT headers = { - "user_agent": self.user_agent, + "user_agent": user_agent, } if self.routing_context is not None: headers["routing"] = self.routing_context diff --git a/src/neo4j/_sync/io/_bolt5.py b/src/neo4j/_sync/io/_bolt5.py index dcf520509..8356a585e 100644 --- a/src/neo4j/_sync/io/_bolt5.py +++ b/src/neo4j/_sync/io/_bolt5.py @@ -21,6 +21,7 @@ from ..._codec.hydration import v2 as hydration_v2 from ..._exceptions import BoltProtocolError +from ..._meta import BOLT_AGENT from ...api import ( READ_ACCESS, Version, @@ -59,6 +60,8 @@ class Bolt5x0(Bolt): supports_multiple_databases = True + supports_notification_filtering = False + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._server_state_manager = ServerStateManager( @@ -88,7 +91,10 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): - headers = {"user_agent": self.user_agent} + user_agent = self.user_agent + if user_agent is None: + user_agent = BOLT_AGENT + headers = {"user_agent": user_agent} if self.routing_context is not None: headers["routing"] = self.routing_context return headers @@ -409,6 +415,8 @@ class Bolt5x2(Bolt5x1): PROTOCOL_VERSION = Version(5, 2) + supports_notification_filtering = True + def get_base_headers(self): headers = super().get_base_headers() if self.notifications_min_severity is not None: @@ -541,3 +549,15 @@ def begin(self, mode=None, bookmarks=None, metadata=None, timeout=None, self._append(b"\x11", (extra,), Response(self, "begin", hydration_hooks, **handlers), dehydration_hooks=dehydration_hooks) + + +class Bolt5x3(Bolt5x2): + + PROTOCOL_VERSION = Version(5, 3) + + def get_base_headers(self): + headers = super().get_base_headers() + if self.user_agent is None: + del headers["user_agent"] + headers["bolt_agent"] = BOLT_AGENT + return headers diff --git a/testkitbackend/test_config.json b/testkitbackend/test_config.json index 847adae83..d7c8b8530 100644 --- a/testkitbackend/test_config.json +++ b/testkitbackend/test_config.json @@ -44,6 +44,7 @@ "Feature:Bolt:5.0": true, "Feature:Bolt:5.1": true, "Feature:Bolt:5.2": true, + "Feature:Bolt:5.3": true, "Feature:Bolt:Patch:UTC": true, "Feature:Impersonation": true, "Feature:TLS:1.1": "Driver blocks TLS 1.1 for security reasons.", diff --git a/tests/unit/async_/io/test_class_bolt.py b/tests/unit/async_/io/test_class_bolt.py index 100c57a6b..05ccaffef 100644 --- a/tests/unit/async_/io/test_class_bolt.py +++ b/tests/unit/async_/io/test_class_bolt.py @@ -38,7 +38,7 @@ def test_class_method_protocol_handlers(): expected_handlers = { (3, 0), (4, 1), (4, 2), (4, 3), (4, 4), - (5, 0), (5, 1), (5, 2), + (5, 0), (5, 1), (5, 2), (5, 3), } protocol_handlers = AsyncBolt.protocol_handlers() @@ -63,7 +63,8 @@ def test_class_method_protocol_handlers(): ((5, 0), 1), ((5, 1), 1), ((5, 2), 1), - ((5, 3), 0), + ((5, 3), 1), + ((5, 4), 0), ((6, 0), 0), ] ) @@ -83,7 +84,7 @@ def test_class_method_protocol_handlers_with_invalid_protocol_version(): # [bolt-version-bump] search tag when changing bolt version support def test_class_method_get_handshake(): handshake = AsyncBolt.get_handshake() - assert (b"\x00\x02\x02\x05\x00\x02\x04\x04\x00\x00\x01\x04\x00\x00\x00\x03" + assert (b"\x00\x03\x03\x05\x00\x02\x04\x04\x00\x00\x01\x04\x00\x00\x00\x03" == handshake) @@ -129,6 +130,7 @@ async def test_cancel_hello_in_open(mocker): ((5, 0), "neo4j._async.io._bolt5.AsyncBolt5x0"), ((5, 1), "neo4j._async.io._bolt5.AsyncBolt5x1"), ((5, 2), "neo4j._async.io._bolt5.AsyncBolt5x2"), + ((5, 3), "neo4j._async.io._bolt5.AsyncBolt5x3"), ), ) @mark_async_test @@ -159,13 +161,13 @@ async def test_version_negotiation(mocker, bolt_version, bolt_cls_path): (2, 0), (4, 0), (3, 1), - (5, 3), + (5, 4), (6, 0), )) @mark_async_test async def test_failing_version_negotiation(mocker, bolt_version): supported_protocols = \ - "('3.0', '4.1', '4.2', '4.3', '4.4', '5.0', '5.1', '5.2')" + "('3.0', '4.1', '4.2', '4.3', '4.4', '5.0', '5.1', '5.2', '5.3')" address = ("localhost", 7687) socket_mock = mocker.AsyncMock(spec=AsyncBoltSocket) diff --git a/tests/unit/async_/io/test_class_bolt3.py b/tests/unit/async_/io/test_class_bolt3.py index aacb57c0c..d85a486cf 100644 --- a/tests/unit/async_/io/test_class_bolt3.py +++ b/tests/unit/async_/io/test_class_bolt3.py @@ -22,6 +22,7 @@ from neo4j._async.io._bolt3 import AsyncBolt3 from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -209,8 +210,9 @@ def items(): unpacker_cls=AsyncBolt3.UNPACKER_CLS) await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = AsyncBolt3(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = AsyncBolt3( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): await connection.hello() @@ -224,3 +226,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt3.PACKER_CLS, + unpacker_cls=AsyncBolt3.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt3.PACKER_CLS, + unpacker_cls=AsyncBolt3.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/async_/io/test_class_bolt4x0.py b/tests/unit/async_/io/test_class_bolt4x0.py index 3395ae184..f7f715448 100644 --- a/tests/unit/async_/io/test_class_bolt4x0.py +++ b/tests/unit/async_/io/test_class_bolt4x0.py @@ -22,6 +22,7 @@ from neo4j._async.io._bolt4 import AsyncBolt4x0 from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -305,8 +306,9 @@ def items(): unpacker_cls=AsyncBolt4x0.UNPACKER_CLS) await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = AsyncBolt4x0(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = AsyncBolt4x0( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): await connection.hello() @@ -320,3 +322,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt4x0.PACKER_CLS, + unpacker_cls=AsyncBolt4x0.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt4x0( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt4x0.PACKER_CLS, + unpacker_cls=AsyncBolt4x0.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt4x0( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/async_/io/test_class_bolt4x1.py b/tests/unit/async_/io/test_class_bolt4x1.py index 6fb4e5177..4248a4ac8 100644 --- a/tests/unit/async_/io/test_class_bolt4x1.py +++ b/tests/unit/async_/io/test_class_bolt4x1.py @@ -22,6 +22,7 @@ from neo4j._async.io._bolt4 import AsyncBolt4x1 from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -322,8 +323,9 @@ def items(): unpacker_cls=AsyncBolt4x1.UNPACKER_CLS) await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = AsyncBolt4x1(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = AsyncBolt4x1( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): await connection.hello() @@ -337,3 +339,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt4x1.PACKER_CLS, + unpacker_cls=AsyncBolt4x1.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt4x1( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt4x1.PACKER_CLS, + unpacker_cls=AsyncBolt4x1.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt4x1( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/async_/io/test_class_bolt4x2.py b/tests/unit/async_/io/test_class_bolt4x2.py index 0d96ad0d9..ae9bcd9b4 100644 --- a/tests/unit/async_/io/test_class_bolt4x2.py +++ b/tests/unit/async_/io/test_class_bolt4x2.py @@ -22,6 +22,7 @@ from neo4j._async.io._bolt4 import AsyncBolt4x2 from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -323,8 +324,9 @@ def items(): unpacker_cls=AsyncBolt4x2.UNPACKER_CLS) await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = AsyncBolt4x2(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = AsyncBolt4x2( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): await connection.hello() @@ -338,3 +340,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt4x2.PACKER_CLS, + unpacker_cls=AsyncBolt4x2.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt4x2( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt4x2.PACKER_CLS, + unpacker_cls=AsyncBolt4x2.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt4x2( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/async_/io/test_class_bolt4x3.py b/tests/unit/async_/io/test_class_bolt4x3.py index cf1419136..1aa891378 100644 --- a/tests/unit/async_/io/test_class_bolt4x3.py +++ b/tests/unit/async_/io/test_class_bolt4x3.py @@ -22,6 +22,7 @@ from neo4j._async.io._bolt4 import AsyncBolt4x3 from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -349,8 +350,9 @@ def items(): unpacker_cls=AsyncBolt4x3.UNPACKER_CLS) await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = AsyncBolt4x3(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = AsyncBolt4x3( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): await connection.hello() @@ -364,3 +366,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt4x3.PACKER_CLS, + unpacker_cls=AsyncBolt4x3.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt4x3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt4x3.PACKER_CLS, + unpacker_cls=AsyncBolt4x3.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt4x3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/async_/io/test_class_bolt4x4.py b/tests/unit/async_/io/test_class_bolt4x4.py index 5dacc7471..0348359f2 100644 --- a/tests/unit/async_/io/test_class_bolt4x4.py +++ b/tests/unit/async_/io/test_class_bolt4x4.py @@ -22,6 +22,7 @@ from neo4j._async.io._bolt4 import AsyncBolt4x4 from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -363,8 +364,9 @@ def items(): unpacker_cls=AsyncBolt4x4.UNPACKER_CLS) await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = AsyncBolt4x4(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = AsyncBolt4x4( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): await connection.hello() @@ -378,3 +380,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt4x4.PACKER_CLS, + unpacker_cls=AsyncBolt4x4.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt4x4( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt4x4.PACKER_CLS, + unpacker_cls=AsyncBolt4x4.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt4x4( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/async_/io/test_class_bolt5x0.py b/tests/unit/async_/io/test_class_bolt5x0.py index bf9cf3720..e17fe1117 100644 --- a/tests/unit/async_/io/test_class_bolt5x0.py +++ b/tests/unit/async_/io/test_class_bolt5x0.py @@ -22,6 +22,7 @@ from neo4j._async.io._bolt5 import AsyncBolt5x0 from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -363,8 +364,9 @@ def items(): unpacker_cls=AsyncBolt5x0.UNPACKER_CLS) await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = AsyncBolt5x0(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = AsyncBolt5x0( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): await connection.hello() @@ -378,3 +380,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x0.PACKER_CLS, + unpacker_cls=AsyncBolt5x0.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt5x0( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x0.PACKER_CLS, + unpacker_cls=AsyncBolt5x0.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt5x0( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/async_/io/test_class_bolt5x1.py b/tests/unit/async_/io/test_class_bolt5x1.py index 142b1f91d..11f78af7a 100644 --- a/tests/unit/async_/io/test_class_bolt5x1.py +++ b/tests/unit/async_/io/test_class_bolt5x1.py @@ -22,6 +22,7 @@ from neo4j._async.io._bolt5 import AsyncBolt5x1 from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -125,8 +126,9 @@ def items(): await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) await sockets.server.send_message(b"\x70", {}) max_connection_lifetime = 0 - connection = AsyncBolt5x1(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = AsyncBolt5x1( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): await connection.hello() @@ -140,3 +142,50 @@ def items(): assert value not in logon else: assert str({key: value})[1:-1] in logon + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x1.PACKER_CLS, + unpacker_cls=AsyncBolt5x1.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt5x1( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x1.PACKER_CLS, + unpacker_cls=AsyncBolt5x1.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt5x1( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/async_/io/test_class_bolt5x2.py b/tests/unit/async_/io/test_class_bolt5x2.py index 1a00c9550..d4d2691fc 100644 --- a/tests/unit/async_/io/test_class_bolt5x2.py +++ b/tests/unit/async_/io/test_class_bolt5x2.py @@ -14,6 +14,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + + import itertools import logging @@ -21,6 +23,7 @@ from neo4j._async.io._bolt5 import AsyncBolt5x2 from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j.api import Auth from ...._async_compat import mark_async_test @@ -395,8 +398,9 @@ def items(): await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) await sockets.server.send_message(b"\x70", {}) max_connection_lifetime = 0 - connection = AsyncBolt5x2(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = AsyncBolt5x2( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): await connection.hello() @@ -410,3 +414,50 @@ def items(): assert value not in logon else: assert str({key: value})[1:-1] in logon + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x2.PACKER_CLS, + unpacker_cls=AsyncBolt5x2.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt5x2( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x2.PACKER_CLS, + unpacker_cls=AsyncBolt5x2.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt5x2( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/async_/io/test_class_bolt5x3.py b/tests/unit/async_/io/test_class_bolt5x3.py new file mode 100644 index 000000000..69836c407 --- /dev/null +++ b/tests/unit/async_/io/test_class_bolt5x3.py @@ -0,0 +1,463 @@ +# Copyright (c) "Neo4j" +# Neo4j Sweden AB [https://neo4j.com] +# +# This file is part of Neo4j. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import itertools +import logging + +import pytest + +from neo4j._async.io._bolt5 import AsyncBolt5x3 +from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT +from neo4j.api import Auth + +from ...._async_compat import mark_async_test + + +@pytest.mark.parametrize("set_stale", (True, False)) +def test_conn_is_stale(fake_socket, set_stale): + address = ("127.0.0.1", 7687) + max_connection_lifetime = 0 + connection = AsyncBolt5x3(address, fake_socket(address), max_connection_lifetime) + if set_stale: + connection.set_stale() + assert connection.stale() is True + + +@pytest.mark.parametrize("set_stale", (True, False)) +def test_conn_is_not_stale_if_not_enabled(fake_socket, set_stale): + address = ("127.0.0.1", 7687) + max_connection_lifetime = -1 + connection = AsyncBolt5x3(address, fake_socket(address), max_connection_lifetime) + if set_stale: + connection.set_stale() + assert connection.stale() is set_stale + + +@pytest.mark.parametrize("set_stale", (True, False)) +def test_conn_is_not_stale(fake_socket, set_stale): + address = ("127.0.0.1", 7687) + max_connection_lifetime = 999999999 + connection = AsyncBolt5x3(address, fake_socket(address), max_connection_lifetime) + if set_stale: + connection.set_stale() + assert connection.stale() is set_stale + + +@pytest.mark.parametrize(("args", "kwargs", "expected_fields"), ( + (("", {}), {"db": "something"}, ({"db": "something"},)), + (("", {}), {"imp_user": "imposter"}, ({"imp_user": "imposter"},)), + ( + ("", {}), + {"db": "something", "imp_user": "imposter"}, + ({"db": "something", "imp_user": "imposter"},) + ), +)) +@mark_async_test +async def test_extra_in_begin(fake_socket, args, kwargs, expected_fields): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) + connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.begin(*args, **kwargs) + await connection.send_all() + tag, is_fields = await socket.pop_message() + assert tag == b"\x11" + assert tuple(is_fields) == expected_fields + + +@pytest.mark.parametrize(("args", "kwargs", "expected_fields"), ( + (("", {}), {"db": "something"}, ("", {}, {"db": "something"})), + (("", {}), {"imp_user": "imposter"}, ("", {}, {"imp_user": "imposter"})), + ( + ("", {}), + {"db": "something", "imp_user": "imposter"}, + ("", {}, {"db": "something", "imp_user": "imposter"}) + ), +)) +@mark_async_test +async def test_extra_in_run(fake_socket, args, kwargs, expected_fields): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) + connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.run(*args, **kwargs) + await connection.send_all() + tag, is_fields = await socket.pop_message() + assert tag == b"\x10" + assert tuple(is_fields) == expected_fields + + +@mark_async_test +async def test_n_extra_in_discard(fake_socket): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) + connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.discard(n=666) + await connection.send_all() + tag, fields = await socket.pop_message() + assert tag == b"\x2F" + assert len(fields) == 1 + assert fields[0] == {"n": 666} + + +@pytest.mark.parametrize( + "test_input, expected", + [ + (666, {"n": -1, "qid": 666}), + (-1, {"n": -1}), + ] +) +@mark_async_test +async def test_qid_extra_in_discard(fake_socket, test_input, expected): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) + connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.discard(qid=test_input) + await connection.send_all() + tag, fields = await socket.pop_message() + assert tag == b"\x2F" + assert len(fields) == 1 + assert fields[0] == expected + + +@pytest.mark.parametrize( + "test_input, expected", + [ + (777, {"n": 666, "qid": 777}), + (-1, {"n": 666}), + ] +) +@mark_async_test +async def test_n_and_qid_extras_in_discard(fake_socket, test_input, expected): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) + connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.discard(n=666, qid=test_input) + await connection.send_all() + tag, fields = await socket.pop_message() + assert tag == b"\x2F" + assert len(fields) == 1 + assert fields[0] == expected + + +@pytest.mark.parametrize( + "test_input, expected", + [ + (666, {"n": 666}), + (-1, {"n": -1}), + ] +) +@mark_async_test +async def test_n_extra_in_pull(fake_socket, test_input, expected): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) + connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.pull(n=test_input) + await connection.send_all() + tag, fields = await socket.pop_message() + assert tag == b"\x3F" + assert len(fields) == 1 + assert fields[0] == expected + + +@pytest.mark.parametrize( + "test_input, expected", + [ + (777, {"n": -1, "qid": 777}), + (-1, {"n": -1}), + ] +) +@mark_async_test +async def test_qid_extra_in_pull(fake_socket, test_input, expected): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) + connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.pull(qid=test_input) + await connection.send_all() + tag, fields = await socket.pop_message() + assert tag == b"\x3F" + assert len(fields) == 1 + assert fields[0] == expected + + +@mark_async_test +async def test_n_and_qid_extras_in_pull(fake_socket): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) + connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.pull(n=666, qid=777) + await connection.send_all() + tag, fields = await socket.pop_message() + assert tag == b"\x3F" + assert len(fields) == 1 + assert fields[0] == {"n": 666, "qid": 777} + + +@mark_async_test +async def test_hello_passes_routing_metadata(fake_socket_pair): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x3.PACKER_CLS, + unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/4.4.0"}) + await sockets.server.send_message(b"\x70", {}) + connection = AsyncBolt5x3( + address, sockets.client, PoolConfig.max_connection_lifetime, + routing_context={"foo": "bar"} + ) + await connection.hello() + tag, fields = await sockets.server.pop_message() + assert tag == b"\x01" + assert len(fields) == 1 + assert fields[0]["routing"] == {"foo": "bar"} + + +@pytest.mark.parametrize(("hints", "valid"), ( + ({"connection.recv_timeout_seconds": 1}, True), + ({"connection.recv_timeout_seconds": 42}, True), + ({}, True), + ({"whatever_this_is": "ignore me!"}, True), + ({"connection.recv_timeout_seconds": -1}, False), + ({"connection.recv_timeout_seconds": 0}, False), + ({"connection.recv_timeout_seconds": 2.5}, False), + ({"connection.recv_timeout_seconds": None}, False), + ({"connection.recv_timeout_seconds": False}, False), + ({"connection.recv_timeout_seconds": "1"}, False), +)) +@mark_async_test +async def test_hint_recv_timeout_seconds( + fake_socket_pair, hints, valid, caplog, mocker +): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x3.PACKER_CLS, + unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) + sockets.client.settimeout = mocker.Mock() + await sockets.server.send_message( + b"\x70", {"server": "Neo4j/4.3.4", "hints": hints} + ) + await sockets.server.send_message(b"\x70", {}) + connection = AsyncBolt5x3( + address, sockets.client, PoolConfig.max_connection_lifetime + ) + with caplog.at_level(logging.INFO): + await connection.hello() + if valid: + if "connection.recv_timeout_seconds" in hints: + sockets.client.settimeout.assert_called_once_with( + hints["connection.recv_timeout_seconds"] + ) + else: + sockets.client.settimeout.assert_not_called() + assert not any("recv_timeout_seconds" in msg + and "invalid" in msg + for msg in caplog.messages) + else: + sockets.client.settimeout.assert_not_called() + assert any(repr(hints["connection.recv_timeout_seconds"]) in msg + and "recv_timeout_seconds" in msg + and "invalid" in msg + for msg in caplog.messages) + + +def _assert_notifications_in_extra(extra, expected): + for key in expected: + assert key in extra + assert extra[key] == expected[key] + + + +@pytest.mark.parametrize(("method", "args", "extra_idx"), ( + ("run", ("RETURN 1",), 2), + ("begin", (), 0), +)) +@pytest.mark.parametrize( + ("cls_min_sev", "method_min_sev"), + itertools.product((None, "WARNING", "OFF"), repeat=2) +) +@pytest.mark.parametrize( + ("cls_dis_cats", "method_dis_cats"), + itertools.product((None, [], ["HINT"], ["HINT", "DEPRECATION"]), repeat=2) +) +@mark_async_test +async def test_supports_notification_filters( + fake_socket, method, args, extra_idx, cls_min_sev, method_min_sev, + cls_dis_cats, method_dis_cats +): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) + connection = AsyncBolt5x3( + address, socket, PoolConfig.max_connection_lifetime, + notifications_min_severity=cls_min_sev, + notifications_disabled_categories=cls_dis_cats + ) + method = getattr(connection, method) + + method(*args, notifications_min_severity=method_min_sev, + notifications_disabled_categories=method_dis_cats) + await connection.send_all() + + _, fields = await socket.pop_message() + extra = fields[extra_idx] + expected = {} + if method_min_sev is not None: + expected["notifications_minimum_severity"] = method_min_sev + if method_dis_cats is not None: + expected["notifications_disabled_categories"] = method_dis_cats + _assert_notifications_in_extra(extra, expected) + + +@pytest.mark.parametrize("min_sev", (None, "WARNING", "OFF")) +@pytest.mark.parametrize("dis_cats", + (None, [], ["HINT"], ["HINT", "DEPRECATION"])) +@mark_async_test +async def test_hello_supports_notification_filters( + fake_socket_pair, min_sev, dis_cats +): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x3.PACKER_CLS, + unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + connection = AsyncBolt5x3( + address, sockets.client, PoolConfig.max_connection_lifetime, + notifications_min_severity=min_sev, + notifications_disabled_categories=dis_cats + ) + + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + expected = {} + if min_sev is not None: + expected["notifications_minimum_severity"] = min_sev + if dis_cats is not None: + expected["notifications_disabled_categories"] = dis_cats + _assert_notifications_in_extra(extra, expected) + + +class HackedAuth: + def __init__(self, dict_): + self.__dict__ = dict_ + + +@mark_async_test +@pytest.mark.parametrize("auth", ( + ("awesome test user", "safe p4ssw0rd"), + Auth("super nice scheme", "awesome test user", "safe p4ssw0rd"), + Auth("super nice scheme", "awesome test user", "safe p4ssw0rd", + realm="super duper realm"), + Auth("super nice scheme", "awesome test user", "safe p4ssw0rd", + realm="super duper realm"), + Auth("super nice scheme", "awesome test user", "safe p4ssw0rd", + foo="bar"), + HackedAuth({ + "scheme": "super nice scheme", "principal": "awesome test user", + "credentials": "safe p4ssw0rd", "realm": "super duper realm", + "parameters": {"credentials": "should be visible!"}, + }) + +)) +async def test_hello_does_not_log_credentials(fake_socket_pair, caplog, auth): + def items(): + if isinstance(auth, tuple): + yield "scheme", "basic" + yield "principal", auth[0] + yield "credentials", auth[1] + elif isinstance(auth, Auth): + for key in ("scheme", "principal", "credentials", "realm", + "parameters"): + value = getattr(auth, key, None) + if value: + yield key, value + elif isinstance(auth, HackedAuth): + yield from auth.__dict__.items() + else: + raise TypeError(auth) + + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x3.PACKER_CLS, + unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt5x3( + address, sockets.client, max_connection_lifetime, auth=auth + ) + + with caplog.at_level(logging.DEBUG): + await connection.hello() + + logons = [m for m in caplog.messages if "C: LOGON " in m] + assert len(logons) == 1 + logon = logons[0] + + for key, value in items(): + if key == "credentials": + assert value not in logon + else: + assert str({key: value})[1:-1] in logon + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x3.PACKER_CLS, + unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt5x3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert "user_agent" not in extra + else: + assert extra["user_agent"] == user_agent + + +@mark_async_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +async def test_sends_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=AsyncBolt5x3.PACKER_CLS, + unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) + await sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + await sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = AsyncBolt5x3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + await connection.hello() + + tag, fields = await sockets.server.pop_message() + extra = fields[0] + assert extra["bolt_agent"] == BOLT_AGENT diff --git a/tests/unit/common/work/test_summary.py b/tests/unit/common/work/test_summary.py index d92fc742c..3d3049356 100644 --- a/tests/unit/common/work/test_summary.py +++ b/tests/unit/common/work/test_summary.py @@ -307,6 +307,7 @@ def test_summary_result_counters(summary_args_kwargs, counters_set) -> None: ((5, 0), "t_first"), ((5, 1), "t_first"), ((5, 2), "t_first"), + ((5, 3), "t_first"), )) def test_summary_result_available_after( summary_args_kwargs, exists, bolt_version, meta_name @@ -336,6 +337,7 @@ def test_summary_result_available_after( ((5, 0), "t_last"), ((5, 1), "t_last"), ((5, 2), "t_last"), + ((5, 3), "t_last"), )) def test_summary_result_consumed_after( summary_args_kwargs, exists, bolt_version, meta_name diff --git a/tests/unit/sync/io/test_class_bolt.py b/tests/unit/sync/io/test_class_bolt.py index f963834a7..ef7fcba98 100644 --- a/tests/unit/sync/io/test_class_bolt.py +++ b/tests/unit/sync/io/test_class_bolt.py @@ -38,7 +38,7 @@ def test_class_method_protocol_handlers(): expected_handlers = { (3, 0), (4, 1), (4, 2), (4, 3), (4, 4), - (5, 0), (5, 1), (5, 2), + (5, 0), (5, 1), (5, 2), (5, 3), } protocol_handlers = Bolt.protocol_handlers() @@ -63,7 +63,8 @@ def test_class_method_protocol_handlers(): ((5, 0), 1), ((5, 1), 1), ((5, 2), 1), - ((5, 3), 0), + ((5, 3), 1), + ((5, 4), 0), ((6, 0), 0), ] ) @@ -83,7 +84,7 @@ def test_class_method_protocol_handlers_with_invalid_protocol_version(): # [bolt-version-bump] search tag when changing bolt version support def test_class_method_get_handshake(): handshake = Bolt.get_handshake() - assert (b"\x00\x02\x02\x05\x00\x02\x04\x04\x00\x00\x01\x04\x00\x00\x00\x03" + assert (b"\x00\x03\x03\x05\x00\x02\x04\x04\x00\x00\x01\x04\x00\x00\x00\x03" == handshake) @@ -129,6 +130,7 @@ def test_cancel_hello_in_open(mocker): ((5, 0), "neo4j._sync.io._bolt5.Bolt5x0"), ((5, 1), "neo4j._sync.io._bolt5.Bolt5x1"), ((5, 2), "neo4j._sync.io._bolt5.Bolt5x2"), + ((5, 3), "neo4j._sync.io._bolt5.Bolt5x3"), ), ) @mark_sync_test @@ -159,13 +161,13 @@ def test_version_negotiation(mocker, bolt_version, bolt_cls_path): (2, 0), (4, 0), (3, 1), - (5, 3), + (5, 4), (6, 0), )) @mark_sync_test def test_failing_version_negotiation(mocker, bolt_version): supported_protocols = \ - "('3.0', '4.1', '4.2', '4.3', '4.4', '5.0', '5.1', '5.2')" + "('3.0', '4.1', '4.2', '4.3', '4.4', '5.0', '5.1', '5.2', '5.3')" address = ("localhost", 7687) socket_mock = mocker.MagicMock(spec=BoltSocket) diff --git a/tests/unit/sync/io/test_class_bolt3.py b/tests/unit/sync/io/test_class_bolt3.py index 71f0de812..033cd0160 100644 --- a/tests/unit/sync/io/test_class_bolt3.py +++ b/tests/unit/sync/io/test_class_bolt3.py @@ -21,6 +21,7 @@ import pytest from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j._sync.io._bolt3 import Bolt3 from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -209,8 +210,9 @@ def items(): unpacker_cls=Bolt3.UNPACKER_CLS) sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = Bolt3(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = Bolt3( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): connection.hello() @@ -224,3 +226,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt3.PACKER_CLS, + unpacker_cls=Bolt3.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt3.PACKER_CLS, + unpacker_cls=Bolt3.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/sync/io/test_class_bolt4x0.py b/tests/unit/sync/io/test_class_bolt4x0.py index d0d62368c..921e93519 100644 --- a/tests/unit/sync/io/test_class_bolt4x0.py +++ b/tests/unit/sync/io/test_class_bolt4x0.py @@ -21,6 +21,7 @@ import pytest from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j._sync.io._bolt4 import Bolt4x0 from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -305,8 +306,9 @@ def items(): unpacker_cls=Bolt4x0.UNPACKER_CLS) sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = Bolt4x0(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = Bolt4x0( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): connection.hello() @@ -320,3 +322,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt4x0.PACKER_CLS, + unpacker_cls=Bolt4x0.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt4x0( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt4x0.PACKER_CLS, + unpacker_cls=Bolt4x0.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt4x0( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/sync/io/test_class_bolt4x1.py b/tests/unit/sync/io/test_class_bolt4x1.py index 76b4facc9..7ae673a07 100644 --- a/tests/unit/sync/io/test_class_bolt4x1.py +++ b/tests/unit/sync/io/test_class_bolt4x1.py @@ -21,6 +21,7 @@ import pytest from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j._sync.io._bolt4 import Bolt4x1 from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -322,8 +323,9 @@ def items(): unpacker_cls=Bolt4x1.UNPACKER_CLS) sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = Bolt4x1(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = Bolt4x1( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): connection.hello() @@ -337,3 +339,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt4x1.PACKER_CLS, + unpacker_cls=Bolt4x1.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt4x1( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt4x1.PACKER_CLS, + unpacker_cls=Bolt4x1.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt4x1( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/sync/io/test_class_bolt4x2.py b/tests/unit/sync/io/test_class_bolt4x2.py index 90dd813db..5f938a3b3 100644 --- a/tests/unit/sync/io/test_class_bolt4x2.py +++ b/tests/unit/sync/io/test_class_bolt4x2.py @@ -21,6 +21,7 @@ import pytest from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j._sync.io._bolt4 import Bolt4x2 from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -323,8 +324,9 @@ def items(): unpacker_cls=Bolt4x2.UNPACKER_CLS) sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = Bolt4x2(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = Bolt4x2( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): connection.hello() @@ -338,3 +340,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt4x2.PACKER_CLS, + unpacker_cls=Bolt4x2.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt4x2( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt4x2.PACKER_CLS, + unpacker_cls=Bolt4x2.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt4x2( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/sync/io/test_class_bolt4x3.py b/tests/unit/sync/io/test_class_bolt4x3.py index 427fb90df..25f68e541 100644 --- a/tests/unit/sync/io/test_class_bolt4x3.py +++ b/tests/unit/sync/io/test_class_bolt4x3.py @@ -21,6 +21,7 @@ import pytest from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j._sync.io._bolt4 import Bolt4x3 from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -349,8 +350,9 @@ def items(): unpacker_cls=Bolt4x3.UNPACKER_CLS) sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = Bolt4x3(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = Bolt4x3( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): connection.hello() @@ -364,3 +366,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt4x3.PACKER_CLS, + unpacker_cls=Bolt4x3.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt4x3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt4x3.PACKER_CLS, + unpacker_cls=Bolt4x3.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt4x3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/sync/io/test_class_bolt4x4.py b/tests/unit/sync/io/test_class_bolt4x4.py index bdd126d00..522adae02 100644 --- a/tests/unit/sync/io/test_class_bolt4x4.py +++ b/tests/unit/sync/io/test_class_bolt4x4.py @@ -21,6 +21,7 @@ import pytest from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j._sync.io._bolt4 import Bolt4x4 from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -363,8 +364,9 @@ def items(): unpacker_cls=Bolt4x4.UNPACKER_CLS) sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = Bolt4x4(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = Bolt4x4( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): connection.hello() @@ -378,3 +380,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt4x4.PACKER_CLS, + unpacker_cls=Bolt4x4.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt4x4( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt4x4.PACKER_CLS, + unpacker_cls=Bolt4x4.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt4x4( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/sync/io/test_class_bolt5x0.py b/tests/unit/sync/io/test_class_bolt5x0.py index 2f570c9eb..266a65b26 100644 --- a/tests/unit/sync/io/test_class_bolt5x0.py +++ b/tests/unit/sync/io/test_class_bolt5x0.py @@ -21,6 +21,7 @@ import pytest from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j._sync.io._bolt5 import Bolt5x0 from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -363,8 +364,9 @@ def items(): unpacker_cls=Bolt5x0.UNPACKER_CLS) sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) max_connection_lifetime = 0 - connection = Bolt5x0(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = Bolt5x0( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): connection.hello() @@ -378,3 +380,50 @@ def items(): assert value not in hello else: assert str({key: value})[1:-1] in hello + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x0.PACKER_CLS, + unpacker_cls=Bolt5x0.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt5x0( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x0.PACKER_CLS, + unpacker_cls=Bolt5x0.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt5x0( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/sync/io/test_class_bolt5x1.py b/tests/unit/sync/io/test_class_bolt5x1.py index da50daeaf..ea4d559e9 100644 --- a/tests/unit/sync/io/test_class_bolt5x1.py +++ b/tests/unit/sync/io/test_class_bolt5x1.py @@ -21,6 +21,7 @@ import pytest from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j._sync.io._bolt5 import Bolt5x1 from neo4j.api import Auth from neo4j.exceptions import ConfigurationError @@ -125,8 +126,9 @@ def items(): sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) sockets.server.send_message(b"\x70", {}) max_connection_lifetime = 0 - connection = Bolt5x1(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = Bolt5x1( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): connection.hello() @@ -140,3 +142,50 @@ def items(): assert value not in logon else: assert str({key: value})[1:-1] in logon + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x1.PACKER_CLS, + unpacker_cls=Bolt5x1.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt5x1( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x1.PACKER_CLS, + unpacker_cls=Bolt5x1.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt5x1( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/sync/io/test_class_bolt5x2.py b/tests/unit/sync/io/test_class_bolt5x2.py index 084424de8..cc157af4a 100644 --- a/tests/unit/sync/io/test_class_bolt5x2.py +++ b/tests/unit/sync/io/test_class_bolt5x2.py @@ -14,12 +14,15 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + + import itertools import logging import pytest from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT from neo4j._sync.io._bolt5 import Bolt5x2 from neo4j.api import Auth @@ -395,8 +398,9 @@ def items(): sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) sockets.server.send_message(b"\x70", {}) max_connection_lifetime = 0 - connection = Bolt5x2(address, sockets.client, - max_connection_lifetime, auth=auth) + connection = Bolt5x2( + address, sockets.client, max_connection_lifetime, auth=auth + ) with caplog.at_level(logging.DEBUG): connection.hello() @@ -410,3 +414,50 @@ def items(): assert value not in logon else: assert str({key: value})[1:-1] in logon + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x2.PACKER_CLS, + unpacker_cls=Bolt5x2.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt5x2( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert extra["user_agent"] == BOLT_AGENT + else: + assert extra["user_agent"] == user_agent + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x2.PACKER_CLS, + unpacker_cls=Bolt5x2.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt5x2( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + assert "bolt_agent" not in extra diff --git a/tests/unit/sync/io/test_class_bolt5x3.py b/tests/unit/sync/io/test_class_bolt5x3.py new file mode 100644 index 000000000..8990eda9a --- /dev/null +++ b/tests/unit/sync/io/test_class_bolt5x3.py @@ -0,0 +1,463 @@ +# Copyright (c) "Neo4j" +# Neo4j Sweden AB [https://neo4j.com] +# +# This file is part of Neo4j. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import itertools +import logging + +import pytest + +from neo4j._conf import PoolConfig +from neo4j._meta import BOLT_AGENT +from neo4j._sync.io._bolt5 import Bolt5x3 +from neo4j.api import Auth + +from ...._async_compat import mark_sync_test + + +@pytest.mark.parametrize("set_stale", (True, False)) +def test_conn_is_stale(fake_socket, set_stale): + address = ("127.0.0.1", 7687) + max_connection_lifetime = 0 + connection = Bolt5x3(address, fake_socket(address), max_connection_lifetime) + if set_stale: + connection.set_stale() + assert connection.stale() is True + + +@pytest.mark.parametrize("set_stale", (True, False)) +def test_conn_is_not_stale_if_not_enabled(fake_socket, set_stale): + address = ("127.0.0.1", 7687) + max_connection_lifetime = -1 + connection = Bolt5x3(address, fake_socket(address), max_connection_lifetime) + if set_stale: + connection.set_stale() + assert connection.stale() is set_stale + + +@pytest.mark.parametrize("set_stale", (True, False)) +def test_conn_is_not_stale(fake_socket, set_stale): + address = ("127.0.0.1", 7687) + max_connection_lifetime = 999999999 + connection = Bolt5x3(address, fake_socket(address), max_connection_lifetime) + if set_stale: + connection.set_stale() + assert connection.stale() is set_stale + + +@pytest.mark.parametrize(("args", "kwargs", "expected_fields"), ( + (("", {}), {"db": "something"}, ({"db": "something"},)), + (("", {}), {"imp_user": "imposter"}, ({"imp_user": "imposter"},)), + ( + ("", {}), + {"db": "something", "imp_user": "imposter"}, + ({"db": "something", "imp_user": "imposter"},) + ), +)) +@mark_sync_test +def test_extra_in_begin(fake_socket, args, kwargs, expected_fields): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) + connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.begin(*args, **kwargs) + connection.send_all() + tag, is_fields = socket.pop_message() + assert tag == b"\x11" + assert tuple(is_fields) == expected_fields + + +@pytest.mark.parametrize(("args", "kwargs", "expected_fields"), ( + (("", {}), {"db": "something"}, ("", {}, {"db": "something"})), + (("", {}), {"imp_user": "imposter"}, ("", {}, {"imp_user": "imposter"})), + ( + ("", {}), + {"db": "something", "imp_user": "imposter"}, + ("", {}, {"db": "something", "imp_user": "imposter"}) + ), +)) +@mark_sync_test +def test_extra_in_run(fake_socket, args, kwargs, expected_fields): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) + connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.run(*args, **kwargs) + connection.send_all() + tag, is_fields = socket.pop_message() + assert tag == b"\x10" + assert tuple(is_fields) == expected_fields + + +@mark_sync_test +def test_n_extra_in_discard(fake_socket): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) + connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.discard(n=666) + connection.send_all() + tag, fields = socket.pop_message() + assert tag == b"\x2F" + assert len(fields) == 1 + assert fields[0] == {"n": 666} + + +@pytest.mark.parametrize( + "test_input, expected", + [ + (666, {"n": -1, "qid": 666}), + (-1, {"n": -1}), + ] +) +@mark_sync_test +def test_qid_extra_in_discard(fake_socket, test_input, expected): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) + connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.discard(qid=test_input) + connection.send_all() + tag, fields = socket.pop_message() + assert tag == b"\x2F" + assert len(fields) == 1 + assert fields[0] == expected + + +@pytest.mark.parametrize( + "test_input, expected", + [ + (777, {"n": 666, "qid": 777}), + (-1, {"n": 666}), + ] +) +@mark_sync_test +def test_n_and_qid_extras_in_discard(fake_socket, test_input, expected): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) + connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.discard(n=666, qid=test_input) + connection.send_all() + tag, fields = socket.pop_message() + assert tag == b"\x2F" + assert len(fields) == 1 + assert fields[0] == expected + + +@pytest.mark.parametrize( + "test_input, expected", + [ + (666, {"n": 666}), + (-1, {"n": -1}), + ] +) +@mark_sync_test +def test_n_extra_in_pull(fake_socket, test_input, expected): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) + connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.pull(n=test_input) + connection.send_all() + tag, fields = socket.pop_message() + assert tag == b"\x3F" + assert len(fields) == 1 + assert fields[0] == expected + + +@pytest.mark.parametrize( + "test_input, expected", + [ + (777, {"n": -1, "qid": 777}), + (-1, {"n": -1}), + ] +) +@mark_sync_test +def test_qid_extra_in_pull(fake_socket, test_input, expected): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) + connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.pull(qid=test_input) + connection.send_all() + tag, fields = socket.pop_message() + assert tag == b"\x3F" + assert len(fields) == 1 + assert fields[0] == expected + + +@mark_sync_test +def test_n_and_qid_extras_in_pull(fake_socket): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) + connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) + connection.pull(n=666, qid=777) + connection.send_all() + tag, fields = socket.pop_message() + assert tag == b"\x3F" + assert len(fields) == 1 + assert fields[0] == {"n": 666, "qid": 777} + + +@mark_sync_test +def test_hello_passes_routing_metadata(fake_socket_pair): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x3.PACKER_CLS, + unpacker_cls=Bolt5x3.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/4.4.0"}) + sockets.server.send_message(b"\x70", {}) + connection = Bolt5x3( + address, sockets.client, PoolConfig.max_connection_lifetime, + routing_context={"foo": "bar"} + ) + connection.hello() + tag, fields = sockets.server.pop_message() + assert tag == b"\x01" + assert len(fields) == 1 + assert fields[0]["routing"] == {"foo": "bar"} + + +@pytest.mark.parametrize(("hints", "valid"), ( + ({"connection.recv_timeout_seconds": 1}, True), + ({"connection.recv_timeout_seconds": 42}, True), + ({}, True), + ({"whatever_this_is": "ignore me!"}, True), + ({"connection.recv_timeout_seconds": -1}, False), + ({"connection.recv_timeout_seconds": 0}, False), + ({"connection.recv_timeout_seconds": 2.5}, False), + ({"connection.recv_timeout_seconds": None}, False), + ({"connection.recv_timeout_seconds": False}, False), + ({"connection.recv_timeout_seconds": "1"}, False), +)) +@mark_sync_test +def test_hint_recv_timeout_seconds( + fake_socket_pair, hints, valid, caplog, mocker +): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x3.PACKER_CLS, + unpacker_cls=Bolt5x3.UNPACKER_CLS) + sockets.client.settimeout = mocker.Mock() + sockets.server.send_message( + b"\x70", {"server": "Neo4j/4.3.4", "hints": hints} + ) + sockets.server.send_message(b"\x70", {}) + connection = Bolt5x3( + address, sockets.client, PoolConfig.max_connection_lifetime + ) + with caplog.at_level(logging.INFO): + connection.hello() + if valid: + if "connection.recv_timeout_seconds" in hints: + sockets.client.settimeout.assert_called_once_with( + hints["connection.recv_timeout_seconds"] + ) + else: + sockets.client.settimeout.assert_not_called() + assert not any("recv_timeout_seconds" in msg + and "invalid" in msg + for msg in caplog.messages) + else: + sockets.client.settimeout.assert_not_called() + assert any(repr(hints["connection.recv_timeout_seconds"]) in msg + and "recv_timeout_seconds" in msg + and "invalid" in msg + for msg in caplog.messages) + + +def _assert_notifications_in_extra(extra, expected): + for key in expected: + assert key in extra + assert extra[key] == expected[key] + + + +@pytest.mark.parametrize(("method", "args", "extra_idx"), ( + ("run", ("RETURN 1",), 2), + ("begin", (), 0), +)) +@pytest.mark.parametrize( + ("cls_min_sev", "method_min_sev"), + itertools.product((None, "WARNING", "OFF"), repeat=2) +) +@pytest.mark.parametrize( + ("cls_dis_cats", "method_dis_cats"), + itertools.product((None, [], ["HINT"], ["HINT", "DEPRECATION"]), repeat=2) +) +@mark_sync_test +def test_supports_notification_filters( + fake_socket, method, args, extra_idx, cls_min_sev, method_min_sev, + cls_dis_cats, method_dis_cats +): + address = ("127.0.0.1", 7687) + socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) + connection = Bolt5x3( + address, socket, PoolConfig.max_connection_lifetime, + notifications_min_severity=cls_min_sev, + notifications_disabled_categories=cls_dis_cats + ) + method = getattr(connection, method) + + method(*args, notifications_min_severity=method_min_sev, + notifications_disabled_categories=method_dis_cats) + connection.send_all() + + _, fields = socket.pop_message() + extra = fields[extra_idx] + expected = {} + if method_min_sev is not None: + expected["notifications_minimum_severity"] = method_min_sev + if method_dis_cats is not None: + expected["notifications_disabled_categories"] = method_dis_cats + _assert_notifications_in_extra(extra, expected) + + +@pytest.mark.parametrize("min_sev", (None, "WARNING", "OFF")) +@pytest.mark.parametrize("dis_cats", + (None, [], ["HINT"], ["HINT", "DEPRECATION"])) +@mark_sync_test +def test_hello_supports_notification_filters( + fake_socket_pair, min_sev, dis_cats +): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x3.PACKER_CLS, + unpacker_cls=Bolt5x3.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + connection = Bolt5x3( + address, sockets.client, PoolConfig.max_connection_lifetime, + notifications_min_severity=min_sev, + notifications_disabled_categories=dis_cats + ) + + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + expected = {} + if min_sev is not None: + expected["notifications_minimum_severity"] = min_sev + if dis_cats is not None: + expected["notifications_disabled_categories"] = dis_cats + _assert_notifications_in_extra(extra, expected) + + +class HackedAuth: + def __init__(self, dict_): + self.__dict__ = dict_ + + +@mark_sync_test +@pytest.mark.parametrize("auth", ( + ("awesome test user", "safe p4ssw0rd"), + Auth("super nice scheme", "awesome test user", "safe p4ssw0rd"), + Auth("super nice scheme", "awesome test user", "safe p4ssw0rd", + realm="super duper realm"), + Auth("super nice scheme", "awesome test user", "safe p4ssw0rd", + realm="super duper realm"), + Auth("super nice scheme", "awesome test user", "safe p4ssw0rd", + foo="bar"), + HackedAuth({ + "scheme": "super nice scheme", "principal": "awesome test user", + "credentials": "safe p4ssw0rd", "realm": "super duper realm", + "parameters": {"credentials": "should be visible!"}, + }) + +)) +def test_hello_does_not_log_credentials(fake_socket_pair, caplog, auth): + def items(): + if isinstance(auth, tuple): + yield "scheme", "basic" + yield "principal", auth[0] + yield "credentials", auth[1] + elif isinstance(auth, Auth): + for key in ("scheme", "principal", "credentials", "realm", + "parameters"): + value = getattr(auth, key, None) + if value: + yield key, value + elif isinstance(auth, HackedAuth): + yield from auth.__dict__.items() + else: + raise TypeError(auth) + + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x3.PACKER_CLS, + unpacker_cls=Bolt5x3.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt5x3( + address, sockets.client, max_connection_lifetime, auth=auth + ) + + with caplog.at_level(logging.DEBUG): + connection.hello() + + logons = [m for m in caplog.messages if "C: LOGON " in m] + assert len(logons) == 1 + logon = logons[0] + + for key, value in items(): + if key == "credentials": + assert value not in logon + else: + assert str({key: value})[1:-1] in logon + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_user_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x3.PACKER_CLS, + unpacker_cls=Bolt5x3.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt5x3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + if user_agent is None: + assert "user_agent" not in extra + else: + assert extra["user_agent"] == user_agent + + +@mark_sync_test +@pytest.mark.parametrize( + "user_agent", (None, "test user agent", "", BOLT_AGENT) +) +def test_sends_bolt_agent(fake_socket_pair, user_agent): + address = ("127.0.0.1", 7687) + sockets = fake_socket_pair(address, + packer_cls=Bolt5x3.PACKER_CLS, + unpacker_cls=Bolt5x3.UNPACKER_CLS) + sockets.server.send_message(b"\x70", {"server": "Neo4j/1.2.3"}) + sockets.server.send_message(b"\x70", {}) + max_connection_lifetime = 0 + connection = Bolt5x3( + address, sockets.client, max_connection_lifetime, user_agent=user_agent + ) + connection.hello() + + tag, fields = sockets.server.pop_message() + extra = fields[0] + assert extra["bolt_agent"] == BOLT_AGENT From 0b218de2c6b3a78cd66997dd0b9a3c4d6f98b6ca Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Thu, 13 Apr 2023 11:15:33 +0200 Subject: [PATCH 2/5] Fix merge Some internal types changed upstream. Newly added tests needed adjusting. --- tests/unit/async_/io/test_class_bolt3.py | 4 +-- tests/unit/async_/io/test_class_bolt4x0.py | 4 +-- tests/unit/async_/io/test_class_bolt4x1.py | 4 +-- tests/unit/async_/io/test_class_bolt4x2.py | 4 +-- tests/unit/async_/io/test_class_bolt4x3.py | 4 +-- tests/unit/async_/io/test_class_bolt4x4.py | 4 +-- tests/unit/async_/io/test_class_bolt5x0.py | 4 +-- tests/unit/async_/io/test_class_bolt5x1.py | 4 +-- tests/unit/async_/io/test_class_bolt5x2.py | 4 +-- tests/unit/async_/io/test_class_bolt5x3.py | 34 +++++++++++----------- tests/unit/async_/io/test_direct.py | 19 ++++++------ tests/unit/sync/io/test_class_bolt3.py | 4 +-- tests/unit/sync/io/test_class_bolt4x0.py | 4 +-- tests/unit/sync/io/test_class_bolt4x1.py | 4 +-- tests/unit/sync/io/test_class_bolt4x2.py | 4 +-- tests/unit/sync/io/test_class_bolt4x3.py | 4 +-- tests/unit/sync/io/test_class_bolt4x4.py | 4 +-- tests/unit/sync/io/test_class_bolt5x0.py | 4 +-- tests/unit/sync/io/test_class_bolt5x1.py | 4 +-- tests/unit/sync/io/test_class_bolt5x2.py | 4 +-- tests/unit/sync/io/test_class_bolt5x3.py | 34 +++++++++++----------- tests/unit/sync/io/test_direct.py | 19 ++++++------ 22 files changed, 90 insertions(+), 88 deletions(-) diff --git a/tests/unit/async_/io/test_class_bolt3.py b/tests/unit/async_/io/test_class_bolt3.py index 703a320b1..c65b0d771 100644 --- a/tests/unit/async_/io/test_class_bolt3.py +++ b/tests/unit/async_/io/test_class_bolt3.py @@ -257,7 +257,7 @@ async def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt3.PACKER_CLS, unpacker_cls=AsyncBolt3.UNPACKER_CLS) @@ -282,7 +282,7 @@ async def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt3.PACKER_CLS, unpacker_cls=AsyncBolt3.UNPACKER_CLS) diff --git a/tests/unit/async_/io/test_class_bolt4x0.py b/tests/unit/async_/io/test_class_bolt4x0.py index fc73e4c01..1faf595f7 100644 --- a/tests/unit/async_/io/test_class_bolt4x0.py +++ b/tests/unit/async_/io/test_class_bolt4x0.py @@ -354,7 +354,7 @@ async def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt4x0.PACKER_CLS, unpacker_cls=AsyncBolt4x0.UNPACKER_CLS) @@ -379,7 +379,7 @@ async def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt4x0.PACKER_CLS, unpacker_cls=AsyncBolt4x0.UNPACKER_CLS) diff --git a/tests/unit/async_/io/test_class_bolt4x1.py b/tests/unit/async_/io/test_class_bolt4x1.py index b443416b9..a4d162bf6 100644 --- a/tests/unit/async_/io/test_class_bolt4x1.py +++ b/tests/unit/async_/io/test_class_bolt4x1.py @@ -370,7 +370,7 @@ async def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt4x1.PACKER_CLS, unpacker_cls=AsyncBolt4x1.UNPACKER_CLS) @@ -395,7 +395,7 @@ async def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt4x1.PACKER_CLS, unpacker_cls=AsyncBolt4x1.UNPACKER_CLS) diff --git a/tests/unit/async_/io/test_class_bolt4x2.py b/tests/unit/async_/io/test_class_bolt4x2.py index 64bd7ebca..d090c5415 100644 --- a/tests/unit/async_/io/test_class_bolt4x2.py +++ b/tests/unit/async_/io/test_class_bolt4x2.py @@ -371,7 +371,7 @@ async def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt4x2.PACKER_CLS, unpacker_cls=AsyncBolt4x2.UNPACKER_CLS) @@ -396,7 +396,7 @@ async def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt4x2.PACKER_CLS, unpacker_cls=AsyncBolt4x2.UNPACKER_CLS) diff --git a/tests/unit/async_/io/test_class_bolt4x3.py b/tests/unit/async_/io/test_class_bolt4x3.py index 0a97153c0..525836c5d 100644 --- a/tests/unit/async_/io/test_class_bolt4x3.py +++ b/tests/unit/async_/io/test_class_bolt4x3.py @@ -398,7 +398,7 @@ async def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt4x3.PACKER_CLS, unpacker_cls=AsyncBolt4x3.UNPACKER_CLS) @@ -423,7 +423,7 @@ async def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt4x3.PACKER_CLS, unpacker_cls=AsyncBolt4x3.UNPACKER_CLS) diff --git a/tests/unit/async_/io/test_class_bolt4x4.py b/tests/unit/async_/io/test_class_bolt4x4.py index b11a76b08..5eb2fd39a 100644 --- a/tests/unit/async_/io/test_class_bolt4x4.py +++ b/tests/unit/async_/io/test_class_bolt4x4.py @@ -411,7 +411,7 @@ async def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt4x4.PACKER_CLS, unpacker_cls=AsyncBolt4x4.UNPACKER_CLS) @@ -436,7 +436,7 @@ async def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt4x4.PACKER_CLS, unpacker_cls=AsyncBolt4x4.UNPACKER_CLS) diff --git a/tests/unit/async_/io/test_class_bolt5x0.py b/tests/unit/async_/io/test_class_bolt5x0.py index 76b89d2dc..cd14cc26e 100644 --- a/tests/unit/async_/io/test_class_bolt5x0.py +++ b/tests/unit/async_/io/test_class_bolt5x0.py @@ -411,7 +411,7 @@ async def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x0.PACKER_CLS, unpacker_cls=AsyncBolt5x0.UNPACKER_CLS) @@ -436,7 +436,7 @@ async def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x0.PACKER_CLS, unpacker_cls=AsyncBolt5x0.UNPACKER_CLS) diff --git a/tests/unit/async_/io/test_class_bolt5x1.py b/tests/unit/async_/io/test_class_bolt5x1.py index 648282c86..6cb6392fc 100644 --- a/tests/unit/async_/io/test_class_bolt5x1.py +++ b/tests/unit/async_/io/test_class_bolt5x1.py @@ -465,7 +465,7 @@ async def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x1.PACKER_CLS, unpacker_cls=AsyncBolt5x1.UNPACKER_CLS) @@ -490,7 +490,7 @@ async def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x1.PACKER_CLS, unpacker_cls=AsyncBolt5x1.UNPACKER_CLS) diff --git a/tests/unit/async_/io/test_class_bolt5x2.py b/tests/unit/async_/io/test_class_bolt5x2.py index f68b7236f..84ffdab94 100644 --- a/tests/unit/async_/io/test_class_bolt5x2.py +++ b/tests/unit/async_/io/test_class_bolt5x2.py @@ -483,7 +483,7 @@ async def test_hello_supports_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x2.PACKER_CLS, unpacker_cls=AsyncBolt5x2.UNPACKER_CLS) @@ -508,7 +508,7 @@ async def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x2.PACKER_CLS, unpacker_cls=AsyncBolt5x2.UNPACKER_CLS) diff --git a/tests/unit/async_/io/test_class_bolt5x3.py b/tests/unit/async_/io/test_class_bolt5x3.py index c6b1e4039..26c7e5fa9 100644 --- a/tests/unit/async_/io/test_class_bolt5x3.py +++ b/tests/unit/async_/io/test_class_bolt5x3.py @@ -31,7 +31,7 @@ @pytest.mark.parametrize("set_stale", (True, False)) def test_conn_is_stale(fake_socket, set_stale): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) max_connection_lifetime = 0 connection = AsyncBolt5x3(address, fake_socket(address), max_connection_lifetime) if set_stale: @@ -41,7 +41,7 @@ def test_conn_is_stale(fake_socket, set_stale): @pytest.mark.parametrize("set_stale", (True, False)) def test_conn_is_not_stale_if_not_enabled(fake_socket, set_stale): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) max_connection_lifetime = -1 connection = AsyncBolt5x3(address, fake_socket(address), max_connection_lifetime) if set_stale: @@ -51,7 +51,7 @@ def test_conn_is_not_stale_if_not_enabled(fake_socket, set_stale): @pytest.mark.parametrize("set_stale", (True, False)) def test_conn_is_not_stale(fake_socket, set_stale): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) max_connection_lifetime = 999999999 connection = AsyncBolt5x3(address, fake_socket(address), max_connection_lifetime) if set_stale: @@ -70,7 +70,7 @@ def test_conn_is_not_stale(fake_socket, set_stale): )) @mark_async_test async def test_extra_in_begin(fake_socket, args, kwargs, expected_fields): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.begin(*args, **kwargs) @@ -91,7 +91,7 @@ async def test_extra_in_begin(fake_socket, args, kwargs, expected_fields): )) @mark_async_test async def test_extra_in_run(fake_socket, args, kwargs, expected_fields): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.run(*args, **kwargs) @@ -103,7 +103,7 @@ async def test_extra_in_run(fake_socket, args, kwargs, expected_fields): @mark_async_test async def test_n_extra_in_discard(fake_socket): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.discard(n=666) @@ -123,7 +123,7 @@ async def test_n_extra_in_discard(fake_socket): ) @mark_async_test async def test_qid_extra_in_discard(fake_socket, test_input, expected): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.discard(qid=test_input) @@ -143,7 +143,7 @@ async def test_qid_extra_in_discard(fake_socket, test_input, expected): ) @mark_async_test async def test_n_and_qid_extras_in_discard(fake_socket, test_input, expected): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.discard(n=666, qid=test_input) @@ -163,7 +163,7 @@ async def test_n_and_qid_extras_in_discard(fake_socket, test_input, expected): ) @mark_async_test async def test_n_extra_in_pull(fake_socket, test_input, expected): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.pull(n=test_input) @@ -183,7 +183,7 @@ async def test_n_extra_in_pull(fake_socket, test_input, expected): ) @mark_async_test async def test_qid_extra_in_pull(fake_socket, test_input, expected): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.pull(qid=test_input) @@ -196,7 +196,7 @@ async def test_qid_extra_in_pull(fake_socket, test_input, expected): @mark_async_test async def test_n_and_qid_extras_in_pull(fake_socket): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) connection = AsyncBolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.pull(n=666, qid=777) @@ -209,7 +209,7 @@ async def test_n_and_qid_extras_in_pull(fake_socket): @mark_async_test async def test_hello_passes_routing_metadata(fake_socket_pair): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x3.PACKER_CLS, unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) @@ -242,7 +242,7 @@ async def test_hello_passes_routing_metadata(fake_socket_pair): async def test_hint_recv_timeout_seconds( fake_socket_pair, hints, valid, caplog, mocker ): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x3.PACKER_CLS, unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) @@ -332,7 +332,7 @@ async def test_supports_notification_filters( fake_socket, method, args, extra_idx, cls_min_sev, method_min_sev, cls_dis_cats, method_dis_cats ): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, AsyncBolt5x3.UNPACKER_CLS) connection = AsyncBolt5x3( address, socket, PoolConfig.max_connection_lifetime, @@ -362,7 +362,7 @@ async def test_supports_notification_filters( async def test_hello_supports_notification_filters( fake_socket_pair, min_sev, dis_cats ): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x3.PACKER_CLS, unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) @@ -391,7 +391,7 @@ async def test_hello_supports_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x3.PACKER_CLS, unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) @@ -416,7 +416,7 @@ async def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) async def test_sends_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=AsyncBolt5x3.PACKER_CLS, unpacker_cls=AsyncBolt5x3.UNPACKER_CLS) diff --git a/tests/unit/async_/io/test_direct.py b/tests/unit/async_/io/test_direct.py index 953287c6c..6be98a2e2 100644 --- a/tests/unit/async_/io/test_direct.py +++ b/tests/unit/async_/io/test_direct.py @@ -18,6 +18,7 @@ import pytest +import neo4j from neo4j import PreviewWarning from neo4j._async.io import AsyncBolt from neo4j._async.io._pool import AsyncIOPool @@ -161,7 +162,7 @@ def assert_pool_size( address, expected_active, expected_inactive, pool): @mark_async_test async def test_pool_can_acquire(pool): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) connection = await pool._acquire(address, None, Deadline(3), None) assert connection.address == address assert_pool_size(address, 1, 0, pool) @@ -169,7 +170,7 @@ async def test_pool_can_acquire(pool): @mark_async_test async def test_pool_can_acquire_twice(pool): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) connection_1 = await pool._acquire(address, None, Deadline(3), None) connection_2 = await pool._acquire(address, None, Deadline(3), None) assert connection_1.address == address @@ -180,8 +181,8 @@ async def test_pool_can_acquire_twice(pool): @mark_async_test async def test_pool_can_acquire_two_addresses(pool): - address_1 = ("127.0.0.1", 7687) - address_2 = ("127.0.0.1", 7474) + address_1 = neo4j.Address(("127.0.0.1", 7687)) + address_2 = neo4j.Address(("127.0.0.1", 7474)) connection_1 = await pool._acquire(address_1, None, Deadline(3), None) connection_2 = await pool._acquire(address_2, None, Deadline(3), None) assert connection_1.address == address_1 @@ -192,7 +193,7 @@ async def test_pool_can_acquire_two_addresses(pool): @mark_async_test async def test_pool_can_acquire_and_release(pool): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) connection = await pool._acquire(address, None, Deadline(3), None) assert_pool_size(address, 1, 0, pool) await pool.release(connection) @@ -201,7 +202,7 @@ async def test_pool_can_acquire_and_release(pool): @mark_async_test async def test_pool_releasing_twice(pool): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) connection = await pool._acquire(address, None, Deadline(3), None) await pool.release(connection) assert_pool_size(address, 0, 1, pool) @@ -211,7 +212,7 @@ async def test_pool_releasing_twice(pool): @mark_async_test async def test_pool_in_use_count(pool): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) assert pool.in_use_connection_count(address) == 0 connection = await pool._acquire(address, None, Deadline(3), None) assert pool.in_use_connection_count(address) == 1 @@ -222,7 +223,7 @@ async def test_pool_in_use_count(pool): @mark_async_test async def test_pool_max_conn_pool_size(pool): async with AsyncFakeBoltPool((), max_connection_pool_size=1) as pool: - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) await pool._acquire(address, None, Deadline(0), None) assert pool.in_use_connection_count(address) == 1 with pytest.raises(ClientError): @@ -233,7 +234,7 @@ async def test_pool_max_conn_pool_size(pool): @pytest.mark.parametrize("is_reset", (True, False)) @mark_async_test async def test_pool_reset_when_released(is_reset, pool, mocker): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) quick_connection_name = AsyncQuickConnection.__name__ is_reset_mock = mocker.patch( f"{__name__}.{quick_connection_name}.is_reset", diff --git a/tests/unit/sync/io/test_class_bolt3.py b/tests/unit/sync/io/test_class_bolt3.py index 6c713f5a7..ec52e729e 100644 --- a/tests/unit/sync/io/test_class_bolt3.py +++ b/tests/unit/sync/io/test_class_bolt3.py @@ -257,7 +257,7 @@ def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt3.PACKER_CLS, unpacker_cls=Bolt3.UNPACKER_CLS) @@ -282,7 +282,7 @@ def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt3.PACKER_CLS, unpacker_cls=Bolt3.UNPACKER_CLS) diff --git a/tests/unit/sync/io/test_class_bolt4x0.py b/tests/unit/sync/io/test_class_bolt4x0.py index 3c08b9641..3fd3a11ff 100644 --- a/tests/unit/sync/io/test_class_bolt4x0.py +++ b/tests/unit/sync/io/test_class_bolt4x0.py @@ -354,7 +354,7 @@ def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt4x0.PACKER_CLS, unpacker_cls=Bolt4x0.UNPACKER_CLS) @@ -379,7 +379,7 @@ def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt4x0.PACKER_CLS, unpacker_cls=Bolt4x0.UNPACKER_CLS) diff --git a/tests/unit/sync/io/test_class_bolt4x1.py b/tests/unit/sync/io/test_class_bolt4x1.py index 65e35135a..09d262bff 100644 --- a/tests/unit/sync/io/test_class_bolt4x1.py +++ b/tests/unit/sync/io/test_class_bolt4x1.py @@ -370,7 +370,7 @@ def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt4x1.PACKER_CLS, unpacker_cls=Bolt4x1.UNPACKER_CLS) @@ -395,7 +395,7 @@ def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt4x1.PACKER_CLS, unpacker_cls=Bolt4x1.UNPACKER_CLS) diff --git a/tests/unit/sync/io/test_class_bolt4x2.py b/tests/unit/sync/io/test_class_bolt4x2.py index ef22144fa..121aeaddd 100644 --- a/tests/unit/sync/io/test_class_bolt4x2.py +++ b/tests/unit/sync/io/test_class_bolt4x2.py @@ -371,7 +371,7 @@ def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt4x2.PACKER_CLS, unpacker_cls=Bolt4x2.UNPACKER_CLS) @@ -396,7 +396,7 @@ def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt4x2.PACKER_CLS, unpacker_cls=Bolt4x2.UNPACKER_CLS) diff --git a/tests/unit/sync/io/test_class_bolt4x3.py b/tests/unit/sync/io/test_class_bolt4x3.py index 61d75d7ca..c5a738175 100644 --- a/tests/unit/sync/io/test_class_bolt4x3.py +++ b/tests/unit/sync/io/test_class_bolt4x3.py @@ -398,7 +398,7 @@ def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt4x3.PACKER_CLS, unpacker_cls=Bolt4x3.UNPACKER_CLS) @@ -423,7 +423,7 @@ def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt4x3.PACKER_CLS, unpacker_cls=Bolt4x3.UNPACKER_CLS) diff --git a/tests/unit/sync/io/test_class_bolt4x4.py b/tests/unit/sync/io/test_class_bolt4x4.py index c021dc631..b8783a275 100644 --- a/tests/unit/sync/io/test_class_bolt4x4.py +++ b/tests/unit/sync/io/test_class_bolt4x4.py @@ -411,7 +411,7 @@ def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt4x4.PACKER_CLS, unpacker_cls=Bolt4x4.UNPACKER_CLS) @@ -436,7 +436,7 @@ def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt4x4.PACKER_CLS, unpacker_cls=Bolt4x4.UNPACKER_CLS) diff --git a/tests/unit/sync/io/test_class_bolt5x0.py b/tests/unit/sync/io/test_class_bolt5x0.py index 0bbc4da97..7df6b064c 100644 --- a/tests/unit/sync/io/test_class_bolt5x0.py +++ b/tests/unit/sync/io/test_class_bolt5x0.py @@ -411,7 +411,7 @@ def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x0.PACKER_CLS, unpacker_cls=Bolt5x0.UNPACKER_CLS) @@ -436,7 +436,7 @@ def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x0.PACKER_CLS, unpacker_cls=Bolt5x0.UNPACKER_CLS) diff --git a/tests/unit/sync/io/test_class_bolt5x1.py b/tests/unit/sync/io/test_class_bolt5x1.py index 67826ef96..570262585 100644 --- a/tests/unit/sync/io/test_class_bolt5x1.py +++ b/tests/unit/sync/io/test_class_bolt5x1.py @@ -465,7 +465,7 @@ def test_hello_does_not_support_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x1.PACKER_CLS, unpacker_cls=Bolt5x1.UNPACKER_CLS) @@ -490,7 +490,7 @@ def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x1.PACKER_CLS, unpacker_cls=Bolt5x1.UNPACKER_CLS) diff --git a/tests/unit/sync/io/test_class_bolt5x2.py b/tests/unit/sync/io/test_class_bolt5x2.py index b2af36e9e..3390100fc 100644 --- a/tests/unit/sync/io/test_class_bolt5x2.py +++ b/tests/unit/sync/io/test_class_bolt5x2.py @@ -483,7 +483,7 @@ def test_hello_supports_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x2.PACKER_CLS, unpacker_cls=Bolt5x2.UNPACKER_CLS) @@ -508,7 +508,7 @@ def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x2.PACKER_CLS, unpacker_cls=Bolt5x2.UNPACKER_CLS) diff --git a/tests/unit/sync/io/test_class_bolt5x3.py b/tests/unit/sync/io/test_class_bolt5x3.py index 27e59cbd0..c35520702 100644 --- a/tests/unit/sync/io/test_class_bolt5x3.py +++ b/tests/unit/sync/io/test_class_bolt5x3.py @@ -31,7 +31,7 @@ @pytest.mark.parametrize("set_stale", (True, False)) def test_conn_is_stale(fake_socket, set_stale): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) max_connection_lifetime = 0 connection = Bolt5x3(address, fake_socket(address), max_connection_lifetime) if set_stale: @@ -41,7 +41,7 @@ def test_conn_is_stale(fake_socket, set_stale): @pytest.mark.parametrize("set_stale", (True, False)) def test_conn_is_not_stale_if_not_enabled(fake_socket, set_stale): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) max_connection_lifetime = -1 connection = Bolt5x3(address, fake_socket(address), max_connection_lifetime) if set_stale: @@ -51,7 +51,7 @@ def test_conn_is_not_stale_if_not_enabled(fake_socket, set_stale): @pytest.mark.parametrize("set_stale", (True, False)) def test_conn_is_not_stale(fake_socket, set_stale): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) max_connection_lifetime = 999999999 connection = Bolt5x3(address, fake_socket(address), max_connection_lifetime) if set_stale: @@ -70,7 +70,7 @@ def test_conn_is_not_stale(fake_socket, set_stale): )) @mark_sync_test def test_extra_in_begin(fake_socket, args, kwargs, expected_fields): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.begin(*args, **kwargs) @@ -91,7 +91,7 @@ def test_extra_in_begin(fake_socket, args, kwargs, expected_fields): )) @mark_sync_test def test_extra_in_run(fake_socket, args, kwargs, expected_fields): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.run(*args, **kwargs) @@ -103,7 +103,7 @@ def test_extra_in_run(fake_socket, args, kwargs, expected_fields): @mark_sync_test def test_n_extra_in_discard(fake_socket): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.discard(n=666) @@ -123,7 +123,7 @@ def test_n_extra_in_discard(fake_socket): ) @mark_sync_test def test_qid_extra_in_discard(fake_socket, test_input, expected): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.discard(qid=test_input) @@ -143,7 +143,7 @@ def test_qid_extra_in_discard(fake_socket, test_input, expected): ) @mark_sync_test def test_n_and_qid_extras_in_discard(fake_socket, test_input, expected): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.discard(n=666, qid=test_input) @@ -163,7 +163,7 @@ def test_n_and_qid_extras_in_discard(fake_socket, test_input, expected): ) @mark_sync_test def test_n_extra_in_pull(fake_socket, test_input, expected): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.pull(n=test_input) @@ -183,7 +183,7 @@ def test_n_extra_in_pull(fake_socket, test_input, expected): ) @mark_sync_test def test_qid_extra_in_pull(fake_socket, test_input, expected): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.pull(qid=test_input) @@ -196,7 +196,7 @@ def test_qid_extra_in_pull(fake_socket, test_input, expected): @mark_sync_test def test_n_and_qid_extras_in_pull(fake_socket): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) connection = Bolt5x3(address, socket, PoolConfig.max_connection_lifetime) connection.pull(n=666, qid=777) @@ -209,7 +209,7 @@ def test_n_and_qid_extras_in_pull(fake_socket): @mark_sync_test def test_hello_passes_routing_metadata(fake_socket_pair): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x3.PACKER_CLS, unpacker_cls=Bolt5x3.UNPACKER_CLS) @@ -242,7 +242,7 @@ def test_hello_passes_routing_metadata(fake_socket_pair): def test_hint_recv_timeout_seconds( fake_socket_pair, hints, valid, caplog, mocker ): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x3.PACKER_CLS, unpacker_cls=Bolt5x3.UNPACKER_CLS) @@ -332,7 +332,7 @@ def test_supports_notification_filters( fake_socket, method, args, extra_idx, cls_min_sev, method_min_sev, cls_dis_cats, method_dis_cats ): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) socket = fake_socket(address, Bolt5x3.UNPACKER_CLS) connection = Bolt5x3( address, socket, PoolConfig.max_connection_lifetime, @@ -362,7 +362,7 @@ def test_supports_notification_filters( def test_hello_supports_notification_filters( fake_socket_pair, min_sev, dis_cats ): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x3.PACKER_CLS, unpacker_cls=Bolt5x3.UNPACKER_CLS) @@ -391,7 +391,7 @@ def test_hello_supports_notification_filters( "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x3.PACKER_CLS, unpacker_cls=Bolt5x3.UNPACKER_CLS) @@ -416,7 +416,7 @@ def test_user_agent(fake_socket_pair, user_agent): "user_agent", (None, "test user agent", "", BOLT_AGENT) ) def test_sends_bolt_agent(fake_socket_pair, user_agent): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) sockets = fake_socket_pair(address, packer_cls=Bolt5x3.PACKER_CLS, unpacker_cls=Bolt5x3.UNPACKER_CLS) diff --git a/tests/unit/sync/io/test_direct.py b/tests/unit/sync/io/test_direct.py index 5349f5a21..aa294c2fb 100644 --- a/tests/unit/sync/io/test_direct.py +++ b/tests/unit/sync/io/test_direct.py @@ -18,6 +18,7 @@ import pytest +import neo4j from neo4j import PreviewWarning from neo4j._conf import ( Config, @@ -161,7 +162,7 @@ def assert_pool_size( address, expected_active, expected_inactive, pool): @mark_sync_test def test_pool_can_acquire(pool): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) connection = pool._acquire(address, None, Deadline(3), None) assert connection.address == address assert_pool_size(address, 1, 0, pool) @@ -169,7 +170,7 @@ def test_pool_can_acquire(pool): @mark_sync_test def test_pool_can_acquire_twice(pool): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) connection_1 = pool._acquire(address, None, Deadline(3), None) connection_2 = pool._acquire(address, None, Deadline(3), None) assert connection_1.address == address @@ -180,8 +181,8 @@ def test_pool_can_acquire_twice(pool): @mark_sync_test def test_pool_can_acquire_two_addresses(pool): - address_1 = ("127.0.0.1", 7687) - address_2 = ("127.0.0.1", 7474) + address_1 = neo4j.Address(("127.0.0.1", 7687)) + address_2 = neo4j.Address(("127.0.0.1", 7474)) connection_1 = pool._acquire(address_1, None, Deadline(3), None) connection_2 = pool._acquire(address_2, None, Deadline(3), None) assert connection_1.address == address_1 @@ -192,7 +193,7 @@ def test_pool_can_acquire_two_addresses(pool): @mark_sync_test def test_pool_can_acquire_and_release(pool): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) connection = pool._acquire(address, None, Deadline(3), None) assert_pool_size(address, 1, 0, pool) pool.release(connection) @@ -201,7 +202,7 @@ def test_pool_can_acquire_and_release(pool): @mark_sync_test def test_pool_releasing_twice(pool): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) connection = pool._acquire(address, None, Deadline(3), None) pool.release(connection) assert_pool_size(address, 0, 1, pool) @@ -211,7 +212,7 @@ def test_pool_releasing_twice(pool): @mark_sync_test def test_pool_in_use_count(pool): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) assert pool.in_use_connection_count(address) == 0 connection = pool._acquire(address, None, Deadline(3), None) assert pool.in_use_connection_count(address) == 1 @@ -222,7 +223,7 @@ def test_pool_in_use_count(pool): @mark_sync_test def test_pool_max_conn_pool_size(pool): with FakeBoltPool((), max_connection_pool_size=1) as pool: - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) pool._acquire(address, None, Deadline(0), None) assert pool.in_use_connection_count(address) == 1 with pytest.raises(ClientError): @@ -233,7 +234,7 @@ def test_pool_max_conn_pool_size(pool): @pytest.mark.parametrize("is_reset", (True, False)) @mark_sync_test def test_pool_reset_when_released(is_reset, pool, mocker): - address = ("127.0.0.1", 7687) + address = neo4j.Address(("127.0.0.1", 7687)) quick_connection_name = QuickConnection.__name__ is_reset_mock = mocker.patch( f"{__name__}.{quick_connection_name}.is_reset", From b2d5e6437daef95c3e17917e0399d7fbde404b59 Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Mon, 15 May 2023 15:48:49 +0200 Subject: [PATCH 3/5] Make bolt_agent a dictionary Align the implementation with the ADR changes: * The default `user_agent` remains untouched * `bolt_agent` becomes a dictionary instead of a string --- src/neo4j/_async/io/_bolt.py | 8 +++- src/neo4j/_async/io/_bolt3.py | 6 +-- src/neo4j/_async/io/_bolt4.py | 11 +----- src/neo4j/_async/io/_bolt5.py | 11 ++---- src/neo4j/_conf.py | 1 - src/neo4j/_meta.py | 43 +++++++++++++--------- src/neo4j/_sync/io/_bolt.py | 8 +++- src/neo4j/_sync/io/_bolt3.py | 6 +-- src/neo4j/_sync/io/_bolt4.py | 11 +----- src/neo4j/_sync/io/_bolt5.py | 11 ++---- tests/unit/async_/io/test_class_bolt3.py | 8 ++-- tests/unit/async_/io/test_class_bolt4x0.py | 9 ++--- tests/unit/async_/io/test_class_bolt4x1.py | 8 ++-- tests/unit/async_/io/test_class_bolt4x2.py | 8 ++-- tests/unit/async_/io/test_class_bolt4x3.py | 8 ++-- tests/unit/async_/io/test_class_bolt4x4.py | 8 ++-- tests/unit/async_/io/test_class_bolt5x0.py | 8 ++-- tests/unit/async_/io/test_class_bolt5x1.py | 8 ++-- tests/unit/async_/io/test_class_bolt5x2.py | 8 ++-- tests/unit/async_/io/test_class_bolt5x3.py | 13 ++++--- tests/unit/sync/io/test_class_bolt3.py | 8 ++-- tests/unit/sync/io/test_class_bolt4x0.py | 9 ++--- tests/unit/sync/io/test_class_bolt4x1.py | 8 ++-- tests/unit/sync/io/test_class_bolt4x2.py | 8 ++-- tests/unit/sync/io/test_class_bolt4x3.py | 8 ++-- tests/unit/sync/io/test_class_bolt4x4.py | 8 ++-- tests/unit/sync/io/test_class_bolt5x0.py | 8 ++-- tests/unit/sync/io/test_class_bolt5x1.py | 8 ++-- tests/unit/sync/io/test_class_bolt5x2.py | 8 ++-- tests/unit/sync/io/test_class_bolt5x3.py | 13 ++++--- 30 files changed, 138 insertions(+), 150 deletions(-) diff --git a/src/neo4j/_async/io/_bolt.py b/src/neo4j/_async/io/_bolt.py index cb5254535..ad058e690 100644 --- a/src/neo4j/_async/io/_bolt.py +++ b/src/neo4j/_async/io/_bolt.py @@ -34,7 +34,7 @@ BoltError, BoltHandshakeError, ) -from ..._meta import BOLT_AGENT +from ..._meta import USER_AGENT from ...addressing import ResolvedAddress from ...api import ( ServerInfo, @@ -150,7 +150,11 @@ def __init__(self, unresolved_address, sock, max_connection_lifetime, *, self.routing_context = routing_context self.idle_since = perf_counter() - self.user_agent = user_agent + # Determine the user agent + if user_agent is not None: + self.user_agent = user_agent + else: + self.user_agent = USER_AGENT self.auth = auth self.auth_dict = self._to_auth_dict(auth) diff --git a/src/neo4j/_async/io/_bolt3.py b/src/neo4j/_async/io/_bolt3.py index a900e844b..a3629c5ff 100644 --- a/src/neo4j/_async/io/_bolt3.py +++ b/src/neo4j/_async/io/_bolt3.py @@ -24,7 +24,6 @@ from ssl import SSLSocket from ..._exceptions import BoltProtocolError -from ..._meta import BOLT_AGENT from ...api import ( READ_ACCESS, Version, @@ -150,11 +149,8 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): - user_agent = self.user_agent - if user_agent is None: - user_agent = BOLT_AGENT return { - "user_agent": user_agent, + "user_agent": self.user_agent, } async def hello(self, dehydration_hooks=None, hydration_hooks=None): diff --git a/src/neo4j/_async/io/_bolt4.py b/src/neo4j/_async/io/_bolt4.py index 389d676fe..2c5dfb785 100644 --- a/src/neo4j/_async/io/_bolt4.py +++ b/src/neo4j/_async/io/_bolt4.py @@ -20,7 +20,6 @@ from ssl import SSLSocket from ..._exceptions import BoltProtocolError -from ..._meta import BOLT_AGENT from ...api import ( READ_ACCESS, SYSTEM_DATABASE, @@ -101,11 +100,8 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): - user_agent = self.user_agent - if user_agent is None: - user_agent = BOLT_AGENT return { - "user_agent": user_agent, + "user_agent": self.user_agent, } async def hello(self, dehydration_hooks=None, hydration_hooks=None): @@ -396,11 +392,8 @@ def get_base_headers(self): enables server-side routing to propagate the same behaviour through its driver. """ - user_agent = self.user_agent - if user_agent is None: - user_agent = BOLT_AGENT headers = { - "user_agent": user_agent, + "user_agent": self.user_agent, } if self.routing_context is not None: headers["routing"] = self.routing_context diff --git a/src/neo4j/_async/io/_bolt5.py b/src/neo4j/_async/io/_bolt5.py index 3ec09c8ba..4502a14a2 100644 --- a/src/neo4j/_async/io/_bolt5.py +++ b/src/neo4j/_async/io/_bolt5.py @@ -23,7 +23,7 @@ from ..._codec.hydration import v2 as hydration_v2 from ..._exceptions import BoltProtocolError -from ..._meta import BOLT_AGENT +from ..._meta import BOLT_AGENT_DICT from ...api import ( READ_ACCESS, Version, @@ -105,10 +105,7 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): - user_agent = self.user_agent - if user_agent is None: - user_agent = BOLT_AGENT - headers = {"user_agent": user_agent} + headers = {"user_agent": self.user_agent} if self.routing_context is not None: headers["routing"] = self.routing_context return headers @@ -630,7 +627,5 @@ class AsyncBolt5x3(AsyncBolt5x2): def get_base_headers(self): headers = super().get_base_headers() - if self.user_agent is None: - del headers["user_agent"] - headers["bolt_agent"] = BOLT_AGENT + headers["bolt_agent"] = BOLT_AGENT_DICT return headers diff --git a/src/neo4j/_conf.py b/src/neo4j/_conf.py index d559b3de2..b9b1d35f1 100644 --- a/src/neo4j/_conf.py +++ b/src/neo4j/_conf.py @@ -26,7 +26,6 @@ deprecation_warn, experimental_warn, ExperimentalWarning, - get_user_agent, ) from .api import ( DEFAULT_DATABASE, diff --git a/src/neo4j/_meta.py b/src/neo4j/_meta.py index a4bf6f604..9885dbe4d 100644 --- a/src/neo4j/_meta.py +++ b/src/neo4j/_meta.py @@ -38,30 +38,39 @@ def _compute_bolt_agent() -> str: def format_version_info(version_info): return "{}.{}.{}-{}-{}".format(*version_info) - return ( - # product/version - f"neo4j-python/{version} " - # platform - f"({platform.system() or 'Unknown'} {platform.release() or 'unknown'}" - f"; {platform.machine() or 'unknown'}) " - # language/version - f"Python/{format_version_info(sys.version_info)} " - # language details - f"({platform.python_implementation()}; " - f"{format_version_info(sys.implementation.version)} " - f"({', '.join(platform.python_build())}) " - f"[{platform.python_compiler()}])" - ) + return { + "product": f"neo4j-python/{version}", + "platform": + f"{platform.system() or 'Unknown'} " + f"{platform.release() or 'unknown'}; " + f"{platform.machine() or 'unknown'}", + "language": f"Python/{format_version_info(sys.version_info)}", + "language_details": + f"{platform.python_implementation()}; " + f"{format_version_info(sys.implementation.version)} " + f"({', '.join(platform.python_build())}) " + f"[{platform.python_compiler()}]" + } + + +BOLT_AGENT_DICT = _compute_bolt_agent() + + +def _compute_user_agent(): + template = "neo4j-python/{} Python/{}.{}.{}-{}-{} ({})" + fields = (version,) + tuple(sys.version_info) + (sys.platform,) + return template.format(*fields) -BOLT_AGENT = _compute_bolt_agent() +USER_AGENT = _compute_user_agent() -def get_user_agent() -> str: +# TODO: 6.0 - remove this function +def get_user_agent(): """ Obtain the default user agent string sent to the server after a successful handshake. """ - return BOLT_AGENT + return USER_AGENT def _id(x): diff --git a/src/neo4j/_sync/io/_bolt.py b/src/neo4j/_sync/io/_bolt.py index 6963c219b..ca16e63e0 100644 --- a/src/neo4j/_sync/io/_bolt.py +++ b/src/neo4j/_sync/io/_bolt.py @@ -34,7 +34,7 @@ BoltError, BoltHandshakeError, ) -from ..._meta import BOLT_AGENT +from ..._meta import USER_AGENT from ...addressing import ResolvedAddress from ...api import ( ServerInfo, @@ -150,7 +150,11 @@ def __init__(self, unresolved_address, sock, max_connection_lifetime, *, self.routing_context = routing_context self.idle_since = perf_counter() - self.user_agent = user_agent + # Determine the user agent + if user_agent is not None: + self.user_agent = user_agent + else: + self.user_agent = USER_AGENT self.auth = auth self.auth_dict = self._to_auth_dict(auth) diff --git a/src/neo4j/_sync/io/_bolt3.py b/src/neo4j/_sync/io/_bolt3.py index 73956afce..4a125797f 100644 --- a/src/neo4j/_sync/io/_bolt3.py +++ b/src/neo4j/_sync/io/_bolt3.py @@ -24,7 +24,6 @@ from ssl import SSLSocket from ..._exceptions import BoltProtocolError -from ..._meta import BOLT_AGENT from ...api import ( READ_ACCESS, Version, @@ -150,11 +149,8 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): - user_agent = self.user_agent - if user_agent is None: - user_agent = BOLT_AGENT return { - "user_agent": user_agent, + "user_agent": self.user_agent, } def hello(self, dehydration_hooks=None, hydration_hooks=None): diff --git a/src/neo4j/_sync/io/_bolt4.py b/src/neo4j/_sync/io/_bolt4.py index 965316bfc..96cc8167f 100644 --- a/src/neo4j/_sync/io/_bolt4.py +++ b/src/neo4j/_sync/io/_bolt4.py @@ -20,7 +20,6 @@ from ssl import SSLSocket from ..._exceptions import BoltProtocolError -from ..._meta import BOLT_AGENT from ...api import ( READ_ACCESS, SYSTEM_DATABASE, @@ -101,11 +100,8 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): - user_agent = self.user_agent - if user_agent is None: - user_agent = BOLT_AGENT return { - "user_agent": user_agent, + "user_agent": self.user_agent, } def hello(self, dehydration_hooks=None, hydration_hooks=None): @@ -396,11 +392,8 @@ def get_base_headers(self): enables server-side routing to propagate the same behaviour through its driver. """ - user_agent = self.user_agent - if user_agent is None: - user_agent = BOLT_AGENT headers = { - "user_agent": user_agent, + "user_agent": self.user_agent, } if self.routing_context is not None: headers["routing"] = self.routing_context diff --git a/src/neo4j/_sync/io/_bolt5.py b/src/neo4j/_sync/io/_bolt5.py index bd51e62d5..1740d22d9 100644 --- a/src/neo4j/_sync/io/_bolt5.py +++ b/src/neo4j/_sync/io/_bolt5.py @@ -23,7 +23,7 @@ from ..._codec.hydration import v2 as hydration_v2 from ..._exceptions import BoltProtocolError -from ..._meta import BOLT_AGENT +from ..._meta import BOLT_AGENT_DICT from ...api import ( READ_ACCESS, Version, @@ -105,10 +105,7 @@ def der_encoded_server_certificate(self): return self.socket.getpeercert(binary_form=True) def get_base_headers(self): - user_agent = self.user_agent - if user_agent is None: - user_agent = BOLT_AGENT - headers = {"user_agent": user_agent} + headers = {"user_agent": self.user_agent} if self.routing_context is not None: headers["routing"] = self.routing_context return headers @@ -630,7 +627,5 @@ class Bolt5x3(Bolt5x2): def get_base_headers(self): headers = super().get_base_headers() - if self.user_agent is None: - del headers["user_agent"] - headers["bolt_agent"] = BOLT_AGENT + headers["bolt_agent"] = BOLT_AGENT_DICT return headers diff --git a/tests/unit/async_/io/test_class_bolt3.py b/tests/unit/async_/io/test_class_bolt3.py index c65b0d771..c23e45080 100644 --- a/tests/unit/async_/io/test_class_bolt3.py +++ b/tests/unit/async_/io/test_class_bolt3.py @@ -24,7 +24,7 @@ import neo4j from neo4j._async.io._bolt3 import AsyncBolt3 from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j.exceptions import ConfigurationError from ...._async_compat import mark_async_test @@ -254,7 +254,7 @@ async def test_hello_does_not_support_notification_filters( @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -272,14 +272,14 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/async_/io/test_class_bolt4x0.py b/tests/unit/async_/io/test_class_bolt4x0.py index 1faf595f7..3b143d48d 100644 --- a/tests/unit/async_/io/test_class_bolt4x0.py +++ b/tests/unit/async_/io/test_class_bolt4x0.py @@ -24,8 +24,7 @@ import neo4j from neo4j._async.io._bolt4 import AsyncBolt4x0 from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT -from neo4j.api import Auth +from neo4j._meta import USER_AGENT from neo4j.exceptions import ConfigurationError from ...._async_compat import mark_async_test @@ -351,7 +350,7 @@ async def test_hello_does_not_support_notification_filters( @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -369,14 +368,14 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/async_/io/test_class_bolt4x1.py b/tests/unit/async_/io/test_class_bolt4x1.py index a4d162bf6..366ccdce6 100644 --- a/tests/unit/async_/io/test_class_bolt4x1.py +++ b/tests/unit/async_/io/test_class_bolt4x1.py @@ -24,7 +24,7 @@ import neo4j from neo4j._async.io._bolt4 import AsyncBolt4x1 from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j.exceptions import ConfigurationError from ...._async_compat import mark_async_test @@ -367,7 +367,7 @@ async def test_hello_does_not_support_notification_filters( @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -385,14 +385,14 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/async_/io/test_class_bolt4x2.py b/tests/unit/async_/io/test_class_bolt4x2.py index d090c5415..45321bfa0 100644 --- a/tests/unit/async_/io/test_class_bolt4x2.py +++ b/tests/unit/async_/io/test_class_bolt4x2.py @@ -24,7 +24,7 @@ import neo4j from neo4j._async.io._bolt4 import AsyncBolt4x2 from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j.exceptions import ConfigurationError from ...._async_compat import mark_async_test @@ -368,7 +368,7 @@ async def test_hello_does_not_support_notification_filters( @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -386,14 +386,14 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/async_/io/test_class_bolt4x3.py b/tests/unit/async_/io/test_class_bolt4x3.py index 525836c5d..ef432f011 100644 --- a/tests/unit/async_/io/test_class_bolt4x3.py +++ b/tests/unit/async_/io/test_class_bolt4x3.py @@ -24,7 +24,7 @@ import neo4j from neo4j._async.io._bolt4 import AsyncBolt4x3 from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j.exceptions import ConfigurationError from ...._async_compat import mark_async_test @@ -395,7 +395,7 @@ async def test_hello_does_not_support_notification_filters( @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -413,14 +413,14 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/async_/io/test_class_bolt4x4.py b/tests/unit/async_/io/test_class_bolt4x4.py index 5eb2fd39a..d2c3962fe 100644 --- a/tests/unit/async_/io/test_class_bolt4x4.py +++ b/tests/unit/async_/io/test_class_bolt4x4.py @@ -24,7 +24,7 @@ import neo4j from neo4j._async.io._bolt4 import AsyncBolt4x4 from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j.exceptions import ConfigurationError from ...._async_compat import mark_async_test @@ -408,7 +408,7 @@ async def test_hello_does_not_support_notification_filters( @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -426,14 +426,14 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/async_/io/test_class_bolt5x0.py b/tests/unit/async_/io/test_class_bolt5x0.py index cd14cc26e..2f4cc781c 100644 --- a/tests/unit/async_/io/test_class_bolt5x0.py +++ b/tests/unit/async_/io/test_class_bolt5x0.py @@ -24,7 +24,7 @@ import neo4j from neo4j._async.io._bolt5 import AsyncBolt5x0 from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j.exceptions import ConfigurationError from ...._async_compat import mark_async_test @@ -408,7 +408,7 @@ async def test_hello_does_not_support_notification_filters( @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -426,14 +426,14 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/async_/io/test_class_bolt5x1.py b/tests/unit/async_/io/test_class_bolt5x1.py index 6cb6392fc..d2e13201b 100644 --- a/tests/unit/async_/io/test_class_bolt5x1.py +++ b/tests/unit/async_/io/test_class_bolt5x1.py @@ -24,7 +24,7 @@ import neo4j.exceptions from neo4j._async.io._bolt5 import AsyncBolt5x1 from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j.exceptions import ConfigurationError from ...._async_compat import mark_async_test @@ -462,7 +462,7 @@ async def test_hello_does_not_support_notification_filters( @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -480,14 +480,14 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/async_/io/test_class_bolt5x2.py b/tests/unit/async_/io/test_class_bolt5x2.py index 84ffdab94..56ff97117 100644 --- a/tests/unit/async_/io/test_class_bolt5x2.py +++ b/tests/unit/async_/io/test_class_bolt5x2.py @@ -24,7 +24,7 @@ import neo4j from neo4j._async.io._bolt5 import AsyncBolt5x2 from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from ...._async_compat import mark_async_test @@ -480,7 +480,7 @@ async def test_hello_supports_notification_filters( @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -498,14 +498,14 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/async_/io/test_class_bolt5x3.py b/tests/unit/async_/io/test_class_bolt5x3.py index 26c7e5fa9..bb9a16f7d 100644 --- a/tests/unit/async_/io/test_class_bolt5x3.py +++ b/tests/unit/async_/io/test_class_bolt5x3.py @@ -24,7 +24,10 @@ import neo4j from neo4j._async.io._bolt5 import AsyncBolt5x3 from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import ( + BOLT_AGENT_DICT, + USER_AGENT, +) from ...._async_compat import mark_async_test @@ -388,7 +391,7 @@ async def test_hello_supports_notification_filters( @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -406,14 +409,14 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert "user_agent" not in extra + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_async_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) async def test_sends_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -430,4 +433,4 @@ async def test_sends_bolt_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - assert extra["bolt_agent"] == BOLT_AGENT + assert extra["bolt_agent"] == BOLT_AGENT_DICT diff --git a/tests/unit/sync/io/test_class_bolt3.py b/tests/unit/sync/io/test_class_bolt3.py index ec52e729e..a8262c878 100644 --- a/tests/unit/sync/io/test_class_bolt3.py +++ b/tests/unit/sync/io/test_class_bolt3.py @@ -23,7 +23,7 @@ import neo4j from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j._sync.io._bolt3 import Bolt3 from neo4j.exceptions import ConfigurationError @@ -254,7 +254,7 @@ def test_hello_does_not_support_notification_filters( @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -272,14 +272,14 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/sync/io/test_class_bolt4x0.py b/tests/unit/sync/io/test_class_bolt4x0.py index 3fd3a11ff..4bc33294b 100644 --- a/tests/unit/sync/io/test_class_bolt4x0.py +++ b/tests/unit/sync/io/test_class_bolt4x0.py @@ -23,9 +23,8 @@ import neo4j from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j._sync.io._bolt4 import Bolt4x0 -from neo4j.api import Auth from neo4j.exceptions import ConfigurationError from ...._async_compat import mark_sync_test @@ -351,7 +350,7 @@ def test_hello_does_not_support_notification_filters( @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -369,14 +368,14 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/sync/io/test_class_bolt4x1.py b/tests/unit/sync/io/test_class_bolt4x1.py index 09d262bff..ac92ef666 100644 --- a/tests/unit/sync/io/test_class_bolt4x1.py +++ b/tests/unit/sync/io/test_class_bolt4x1.py @@ -23,7 +23,7 @@ import neo4j from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j._sync.io._bolt4 import Bolt4x1 from neo4j.exceptions import ConfigurationError @@ -367,7 +367,7 @@ def test_hello_does_not_support_notification_filters( @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -385,14 +385,14 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/sync/io/test_class_bolt4x2.py b/tests/unit/sync/io/test_class_bolt4x2.py index 121aeaddd..92e84be2c 100644 --- a/tests/unit/sync/io/test_class_bolt4x2.py +++ b/tests/unit/sync/io/test_class_bolt4x2.py @@ -23,7 +23,7 @@ import neo4j from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j._sync.io._bolt4 import Bolt4x2 from neo4j.exceptions import ConfigurationError @@ -368,7 +368,7 @@ def test_hello_does_not_support_notification_filters( @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -386,14 +386,14 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/sync/io/test_class_bolt4x3.py b/tests/unit/sync/io/test_class_bolt4x3.py index c5a738175..5b410f6a1 100644 --- a/tests/unit/sync/io/test_class_bolt4x3.py +++ b/tests/unit/sync/io/test_class_bolt4x3.py @@ -23,7 +23,7 @@ import neo4j from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j._sync.io._bolt4 import Bolt4x3 from neo4j.exceptions import ConfigurationError @@ -395,7 +395,7 @@ def test_hello_does_not_support_notification_filters( @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -413,14 +413,14 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/sync/io/test_class_bolt4x4.py b/tests/unit/sync/io/test_class_bolt4x4.py index b8783a275..58de9a5cb 100644 --- a/tests/unit/sync/io/test_class_bolt4x4.py +++ b/tests/unit/sync/io/test_class_bolt4x4.py @@ -23,7 +23,7 @@ import neo4j from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j._sync.io._bolt4 import Bolt4x4 from neo4j.exceptions import ConfigurationError @@ -408,7 +408,7 @@ def test_hello_does_not_support_notification_filters( @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -426,14 +426,14 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/sync/io/test_class_bolt5x0.py b/tests/unit/sync/io/test_class_bolt5x0.py index 7df6b064c..f83fbf6cd 100644 --- a/tests/unit/sync/io/test_class_bolt5x0.py +++ b/tests/unit/sync/io/test_class_bolt5x0.py @@ -23,7 +23,7 @@ import neo4j from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j._sync.io._bolt5 import Bolt5x0 from neo4j.exceptions import ConfigurationError @@ -408,7 +408,7 @@ def test_hello_does_not_support_notification_filters( @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -426,14 +426,14 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/sync/io/test_class_bolt5x1.py b/tests/unit/sync/io/test_class_bolt5x1.py index 570262585..8271d134b 100644 --- a/tests/unit/sync/io/test_class_bolt5x1.py +++ b/tests/unit/sync/io/test_class_bolt5x1.py @@ -23,7 +23,7 @@ import neo4j import neo4j.exceptions from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j._sync.io._bolt5 import Bolt5x1 from neo4j.exceptions import ConfigurationError @@ -462,7 +462,7 @@ def test_hello_does_not_support_notification_filters( @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -480,14 +480,14 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/sync/io/test_class_bolt5x2.py b/tests/unit/sync/io/test_class_bolt5x2.py index 3390100fc..d1f276276 100644 --- a/tests/unit/sync/io/test_class_bolt5x2.py +++ b/tests/unit/sync/io/test_class_bolt5x2.py @@ -23,7 +23,7 @@ import neo4j from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import USER_AGENT from neo4j._sync.io._bolt5 import Bolt5x2 from ...._async_compat import mark_sync_test @@ -480,7 +480,7 @@ def test_hello_supports_notification_filters( @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -498,14 +498,14 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert extra["user_agent"] == BOLT_AGENT + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_does_not_send_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) diff --git a/tests/unit/sync/io/test_class_bolt5x3.py b/tests/unit/sync/io/test_class_bolt5x3.py index c35520702..ae5a7f3ef 100644 --- a/tests/unit/sync/io/test_class_bolt5x3.py +++ b/tests/unit/sync/io/test_class_bolt5x3.py @@ -23,7 +23,10 @@ import neo4j from neo4j._conf import PoolConfig -from neo4j._meta import BOLT_AGENT +from neo4j._meta import ( + BOLT_AGENT_DICT, + USER_AGENT, +) from neo4j._sync.io._bolt5 import Bolt5x3 from ...._async_compat import mark_sync_test @@ -388,7 +391,7 @@ def test_hello_supports_notification_filters( @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_user_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -406,14 +409,14 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] if user_agent is None: - assert "user_agent" not in extra + assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent @mark_sync_test @pytest.mark.parametrize( - "user_agent", (None, "test user agent", "", BOLT_AGENT) + "user_agent", (None, "test user agent", "", USER_AGENT) ) def test_sends_bolt_agent(fake_socket_pair, user_agent): address = neo4j.Address(("127.0.0.1", 7687)) @@ -430,4 +433,4 @@ def test_sends_bolt_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - assert extra["bolt_agent"] == BOLT_AGENT + assert extra["bolt_agent"] == BOLT_AGENT_DICT From a1d99fc6ff01826001e01d31370ea5b1a8f087fd Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Mon, 15 May 2023 18:19:00 +0200 Subject: [PATCH 4/5] Revert sending empty `user_agent` as is This would constitute a breaking change. So we go back to replacing an empty string (or any falsy value) with the driver's default user_agent. --- src/neo4j/_async/io/_bolt.py | 2 +- src/neo4j/_sync/io/_bolt.py | 2 +- tests/unit/async_/io/test_class_bolt3.py | 2 +- tests/unit/async_/io/test_class_bolt4x0.py | 2 +- tests/unit/async_/io/test_class_bolt4x1.py | 2 +- tests/unit/async_/io/test_class_bolt4x2.py | 2 +- tests/unit/async_/io/test_class_bolt4x3.py | 2 +- tests/unit/async_/io/test_class_bolt4x4.py | 2 +- tests/unit/async_/io/test_class_bolt5x0.py | 2 +- tests/unit/async_/io/test_class_bolt5x1.py | 2 +- tests/unit/async_/io/test_class_bolt5x2.py | 2 +- tests/unit/async_/io/test_class_bolt5x3.py | 2 +- tests/unit/sync/io/test_class_bolt3.py | 2 +- tests/unit/sync/io/test_class_bolt4x0.py | 2 +- tests/unit/sync/io/test_class_bolt4x1.py | 2 +- tests/unit/sync/io/test_class_bolt4x2.py | 2 +- tests/unit/sync/io/test_class_bolt4x3.py | 2 +- tests/unit/sync/io/test_class_bolt4x4.py | 2 +- tests/unit/sync/io/test_class_bolt5x0.py | 2 +- tests/unit/sync/io/test_class_bolt5x1.py | 2 +- tests/unit/sync/io/test_class_bolt5x2.py | 2 +- tests/unit/sync/io/test_class_bolt5x3.py | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/neo4j/_async/io/_bolt.py b/src/neo4j/_async/io/_bolt.py index ad058e690..9c954d33e 100644 --- a/src/neo4j/_async/io/_bolt.py +++ b/src/neo4j/_async/io/_bolt.py @@ -151,7 +151,7 @@ def __init__(self, unresolved_address, sock, max_connection_lifetime, *, self.idle_since = perf_counter() # Determine the user agent - if user_agent is not None: + if user_agent: self.user_agent = user_agent else: self.user_agent = USER_AGENT diff --git a/src/neo4j/_sync/io/_bolt.py b/src/neo4j/_sync/io/_bolt.py index ca16e63e0..2f347c154 100644 --- a/src/neo4j/_sync/io/_bolt.py +++ b/src/neo4j/_sync/io/_bolt.py @@ -151,7 +151,7 @@ def __init__(self, unresolved_address, sock, max_connection_lifetime, *, self.idle_since = perf_counter() # Determine the user agent - if user_agent is not None: + if user_agent: self.user_agent = user_agent else: self.user_agent = USER_AGENT diff --git a/tests/unit/async_/io/test_class_bolt3.py b/tests/unit/async_/io/test_class_bolt3.py index c23e45080..56b400c68 100644 --- a/tests/unit/async_/io/test_class_bolt3.py +++ b/tests/unit/async_/io/test_class_bolt3.py @@ -271,7 +271,7 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/async_/io/test_class_bolt4x0.py b/tests/unit/async_/io/test_class_bolt4x0.py index 3b143d48d..d194f12a0 100644 --- a/tests/unit/async_/io/test_class_bolt4x0.py +++ b/tests/unit/async_/io/test_class_bolt4x0.py @@ -367,7 +367,7 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/async_/io/test_class_bolt4x1.py b/tests/unit/async_/io/test_class_bolt4x1.py index 366ccdce6..7a1fa2d24 100644 --- a/tests/unit/async_/io/test_class_bolt4x1.py +++ b/tests/unit/async_/io/test_class_bolt4x1.py @@ -384,7 +384,7 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/async_/io/test_class_bolt4x2.py b/tests/unit/async_/io/test_class_bolt4x2.py index 45321bfa0..f9af5ea20 100644 --- a/tests/unit/async_/io/test_class_bolt4x2.py +++ b/tests/unit/async_/io/test_class_bolt4x2.py @@ -385,7 +385,7 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/async_/io/test_class_bolt4x3.py b/tests/unit/async_/io/test_class_bolt4x3.py index ef432f011..f09e1f724 100644 --- a/tests/unit/async_/io/test_class_bolt4x3.py +++ b/tests/unit/async_/io/test_class_bolt4x3.py @@ -412,7 +412,7 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/async_/io/test_class_bolt4x4.py b/tests/unit/async_/io/test_class_bolt4x4.py index d2c3962fe..135790540 100644 --- a/tests/unit/async_/io/test_class_bolt4x4.py +++ b/tests/unit/async_/io/test_class_bolt4x4.py @@ -425,7 +425,7 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/async_/io/test_class_bolt5x0.py b/tests/unit/async_/io/test_class_bolt5x0.py index 2f4cc781c..30b42963c 100644 --- a/tests/unit/async_/io/test_class_bolt5x0.py +++ b/tests/unit/async_/io/test_class_bolt5x0.py @@ -425,7 +425,7 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/async_/io/test_class_bolt5x1.py b/tests/unit/async_/io/test_class_bolt5x1.py index d2e13201b..831a7d9dd 100644 --- a/tests/unit/async_/io/test_class_bolt5x1.py +++ b/tests/unit/async_/io/test_class_bolt5x1.py @@ -479,7 +479,7 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/async_/io/test_class_bolt5x2.py b/tests/unit/async_/io/test_class_bolt5x2.py index 56ff97117..770e3016b 100644 --- a/tests/unit/async_/io/test_class_bolt5x2.py +++ b/tests/unit/async_/io/test_class_bolt5x2.py @@ -497,7 +497,7 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/async_/io/test_class_bolt5x3.py b/tests/unit/async_/io/test_class_bolt5x3.py index bb9a16f7d..ad671583c 100644 --- a/tests/unit/async_/io/test_class_bolt5x3.py +++ b/tests/unit/async_/io/test_class_bolt5x3.py @@ -408,7 +408,7 @@ async def test_user_agent(fake_socket_pair, user_agent): tag, fields = await sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/sync/io/test_class_bolt3.py b/tests/unit/sync/io/test_class_bolt3.py index a8262c878..8c209434b 100644 --- a/tests/unit/sync/io/test_class_bolt3.py +++ b/tests/unit/sync/io/test_class_bolt3.py @@ -271,7 +271,7 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/sync/io/test_class_bolt4x0.py b/tests/unit/sync/io/test_class_bolt4x0.py index 4bc33294b..e1831cb2e 100644 --- a/tests/unit/sync/io/test_class_bolt4x0.py +++ b/tests/unit/sync/io/test_class_bolt4x0.py @@ -367,7 +367,7 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/sync/io/test_class_bolt4x1.py b/tests/unit/sync/io/test_class_bolt4x1.py index ac92ef666..132212915 100644 --- a/tests/unit/sync/io/test_class_bolt4x1.py +++ b/tests/unit/sync/io/test_class_bolt4x1.py @@ -384,7 +384,7 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/sync/io/test_class_bolt4x2.py b/tests/unit/sync/io/test_class_bolt4x2.py index 92e84be2c..ed19ee522 100644 --- a/tests/unit/sync/io/test_class_bolt4x2.py +++ b/tests/unit/sync/io/test_class_bolt4x2.py @@ -385,7 +385,7 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/sync/io/test_class_bolt4x3.py b/tests/unit/sync/io/test_class_bolt4x3.py index 5b410f6a1..0721172a0 100644 --- a/tests/unit/sync/io/test_class_bolt4x3.py +++ b/tests/unit/sync/io/test_class_bolt4x3.py @@ -412,7 +412,7 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/sync/io/test_class_bolt4x4.py b/tests/unit/sync/io/test_class_bolt4x4.py index 58de9a5cb..b33eaaf54 100644 --- a/tests/unit/sync/io/test_class_bolt4x4.py +++ b/tests/unit/sync/io/test_class_bolt4x4.py @@ -425,7 +425,7 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/sync/io/test_class_bolt5x0.py b/tests/unit/sync/io/test_class_bolt5x0.py index f83fbf6cd..9ae410f18 100644 --- a/tests/unit/sync/io/test_class_bolt5x0.py +++ b/tests/unit/sync/io/test_class_bolt5x0.py @@ -425,7 +425,7 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/sync/io/test_class_bolt5x1.py b/tests/unit/sync/io/test_class_bolt5x1.py index 8271d134b..68eaf7b33 100644 --- a/tests/unit/sync/io/test_class_bolt5x1.py +++ b/tests/unit/sync/io/test_class_bolt5x1.py @@ -479,7 +479,7 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/sync/io/test_class_bolt5x2.py b/tests/unit/sync/io/test_class_bolt5x2.py index d1f276276..69384b9c4 100644 --- a/tests/unit/sync/io/test_class_bolt5x2.py +++ b/tests/unit/sync/io/test_class_bolt5x2.py @@ -497,7 +497,7 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent diff --git a/tests/unit/sync/io/test_class_bolt5x3.py b/tests/unit/sync/io/test_class_bolt5x3.py index ae5a7f3ef..f2a5fae4d 100644 --- a/tests/unit/sync/io/test_class_bolt5x3.py +++ b/tests/unit/sync/io/test_class_bolt5x3.py @@ -408,7 +408,7 @@ def test_user_agent(fake_socket_pair, user_agent): tag, fields = sockets.server.pop_message() extra = fields[0] - if user_agent is None: + if not user_agent: assert extra["user_agent"] == USER_AGENT else: assert extra["user_agent"] == user_agent From 54010de7dd52868014030f2bead90afdcf43ff07 Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Wed, 24 May 2023 14:31:05 +0200 Subject: [PATCH 5/5] Fix type hints --- src/neo4j/_meta.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/neo4j/_meta.py b/src/neo4j/_meta.py index 493b4a108..868982914 100644 --- a/src/neo4j/_meta.py +++ b/src/neo4j/_meta.py @@ -37,7 +37,7 @@ deprecated_package = False -def _compute_bolt_agent() -> str: +def _compute_bolt_agent() -> t.Dict[str, str]: def format_version_info(version_info): return "{}.{}.{}-{}-{}".format(*version_info) @@ -59,7 +59,7 @@ def format_version_info(version_info): BOLT_AGENT_DICT = _compute_bolt_agent() -def _compute_user_agent(): +def _compute_user_agent() -> str: template = "neo4j-python/{} Python/{}.{}.{}-{}-{} ({})" fields = (version,) + tuple(sys.version_info) + (sys.platform,) return template.format(*fields)