|
| 1 | +from importlib.metadata import PackageNotFoundError |
1 | 2 | from unittest.mock import MagicMock, patch |
2 | 3 |
|
3 | 4 | import pytest |
4 | 5 |
|
5 | 6 | from _tilebox.grpc.channel import ( |
6 | 7 | CHANNEL_OPTIONS, |
| 8 | + CLIENT_SOURCE_HEADER, |
| 9 | + CLIENT_VERSION_HEADER, |
| 10 | + AsyncConnectStubAdapter, |
7 | 11 | ChannelProtocol, |
8 | 12 | ClientCallDetails, |
| 13 | + ConnectStubAdapter, |
| 14 | + _ClientMetadataInterceptor, |
9 | 15 | _RpcMethodPrefixInterceptor, |
10 | 16 | connect_address, |
11 | 17 | open_channel, |
@@ -39,14 +45,80 @@ def test_open_authenticated_channel(open_func: MagicMock, intercept_func: MagicM |
39 | 45 | assert intercept_func.call_args[0][1]._auth == ("authorization", "Bearer very-secret") |
40 | 46 |
|
41 | 47 |
|
| 48 | +@patch("_tilebox.grpc.channel.package_version", return_value="1.2.3") |
| 49 | +def test_client_metadata_interceptor(package_version: MagicMock) -> None: |
| 50 | + interceptor = _ClientMetadataInterceptor() |
| 51 | + continuation = MagicMock() |
| 52 | + |
| 53 | + interceptor.intercept_unary_unary( |
| 54 | + continuation, |
| 55 | + ClientCallDetails("/some-rpc-method", 10, [("authorization", "Bearer token")], None, True), |
| 56 | + MagicMock(), |
| 57 | + ) |
| 58 | + |
| 59 | + package_version.assert_called_once_with("tilebox-grpc") |
| 60 | + metadata = continuation.call_args[0][0].metadata |
| 61 | + assert ("authorization", "Bearer token") in metadata |
| 62 | + assert (CLIENT_SOURCE_HEADER, "python_sdk") in metadata |
| 63 | + assert (CLIENT_VERSION_HEADER, "1.2.3") in metadata |
| 64 | + |
| 65 | + |
| 66 | +def test_client_metadata_uses_dev_version_when_package_is_not_installed() -> None: |
| 67 | + with patch("_tilebox.grpc.channel.package_version", side_effect=PackageNotFoundError): |
| 68 | + interceptor = _ClientMetadataInterceptor() |
| 69 | + |
| 70 | + assert (CLIENT_VERSION_HEADER, "dev") in interceptor._metadata |
| 71 | + |
| 72 | + |
| 73 | +class _ConnectClient: |
| 74 | + def get_value(self, request: str, *, headers: dict[str, str]) -> tuple[str, dict[str, str]]: |
| 75 | + return request, headers |
| 76 | + |
| 77 | + |
| 78 | +class _AsyncConnectClient: |
| 79 | + async def get_value(self, request: str, *, headers: dict[str, str]) -> tuple[str, dict[str, str]]: |
| 80 | + return request, headers |
| 81 | + |
| 82 | + |
| 83 | +@patch("_tilebox.grpc.channel.package_version", return_value="1.2.3") |
| 84 | +def test_connect_stub_adapter_adds_client_metadata(package_version: MagicMock) -> None: |
| 85 | + adapter = ConnectStubAdapter(_ConnectClient(), {"authorization": "Bearer token"}) |
| 86 | + |
| 87 | + request, headers = adapter.GetValue("request") # ty: ignore[unresolved-attribute] # added dynamically |
| 88 | + |
| 89 | + assert request == "request" |
| 90 | + assert headers == { |
| 91 | + "authorization": "Bearer token", |
| 92 | + CLIENT_SOURCE_HEADER: "python_sdk", |
| 93 | + CLIENT_VERSION_HEADER: "1.2.3", |
| 94 | + } |
| 95 | + package_version.assert_called_once_with("tilebox-grpc") |
| 96 | + |
| 97 | + |
| 98 | +@pytest.mark.asyncio |
| 99 | +@patch("_tilebox.grpc.channel.package_version", return_value="1.2.3") |
| 100 | +async def test_async_connect_stub_adapter_adds_client_metadata(package_version: MagicMock) -> None: |
| 101 | + adapter = AsyncConnectStubAdapter(_AsyncConnectClient(), {"authorization": "Bearer token"}) |
| 102 | + |
| 103 | + request, headers = await adapter.GetValue("request") # ty: ignore[unresolved-attribute] # added dynamically |
| 104 | + |
| 105 | + assert request == "request" |
| 106 | + assert headers == { |
| 107 | + "authorization": "Bearer token", |
| 108 | + CLIENT_SOURCE_HEADER: "python_sdk", |
| 109 | + CLIENT_VERSION_HEADER: "1.2.3", |
| 110 | + } |
| 111 | + package_version.assert_called_once_with("tilebox-grpc") |
| 112 | + |
| 113 | + |
42 | 114 | @patch("_tilebox.grpc.channel.intercept_channel") |
43 | 115 | @patch("_tilebox.grpc.channel.secure_channel") |
44 | 116 | def test_open_channel_with_rpc_method_prefix(open_func: MagicMock, intercept_func: MagicMock) -> None: |
45 | 117 | open_channel("api.tilebox.com", rpc_method_prefix="/public") |
46 | 118 | open_func.assert_called_once() |
47 | 119 | intercept_func.assert_called_once() |
48 | 120 |
|
49 | | - assert intercept_func.call_args[0][1]._prefix == "/public" |
| 121 | + assert intercept_func.call_args[0][2]._prefix == "/public" |
50 | 122 |
|
51 | 123 |
|
52 | 124 | def test_rpc_method_prefix_interceptor() -> None: |
|
0 commit comments