Skip to content

Commit 888e1f8

Browse files
committed
remove simple test in favor of a more thorough check for 'unknown rpc call'
1 parent e427c15 commit 888e1f8

File tree

2 files changed

+81
-30
lines changed

2 files changed

+81
-30
lines changed

tests/test_client.py

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import asyncio
21
import dataclasses
32
import json
43
import os
@@ -8,12 +7,9 @@
87
from unittest import mock
98

109
import google.protobuf.any_pb2
11-
import google.protobuf.message
1210
from google.protobuf import json_format
1311

1412
import temporalio.api.common.v1
15-
import temporalio.api.enums.v1
16-
import temporalio.api.errordetails.v1
1713
import temporalio.api.workflowservice.v1
1814
import temporalio.common
1915
import temporalio.exceptions
@@ -33,9 +29,7 @@
3329
WorkflowTaskFailedCause,
3430
)
3531
from temporalio.api.history.v1 import History
36-
from temporalio.api.workflowservice.v1 import GetSystemInfoRequest, request_response_pb2
37-
from temporalio.api.batch.v1 import message_pb2
38-
from temporalio.api.enums.v1 import reset_pb2
32+
from temporalio.api.workflowservice.v1 import GetSystemInfoRequest
3933
from temporalio.client import (
4034
BuildIdOpAddNewCompatible,
4135
BuildIdOpAddNewDefault,
@@ -44,11 +38,9 @@
4438
BuildIdOpPromoteSetByBuildId,
4539
CancelWorkflowInput,
4640
Client,
47-
ClientConfig,
4841
CloudOperationsClient,
4942
Interceptor,
5043
OutboundInterceptor,
51-
Plugin,
5244
QueryWorkflowInput,
5345
RPCError,
5446
RPCStatusCode,
@@ -93,7 +85,6 @@
9385
from temporalio.testing import WorkflowEnvironment
9486
from tests.helpers import (
9587
assert_eq_eventually,
96-
assert_eventually,
9788
ensure_search_attributes_present,
9889
new_worker,
9990
worker_versioning_enabled,
@@ -1554,22 +1545,3 @@ async def get_schedule_result() -> Tuple[int, Optional[str]]:
15541545
)
15551546

15561547
await handle.delete()
1557-
1558-
1559-
async def test_workflow_client_start_batch_operation(client: Client):
1560-
# This test is used to ensure that the start_batch_operation is wired through
1561-
# the layers of python -> bridge python -> bridge rust -> core
1562-
# https://github.com/temporalio/sdk-python/issues/927
1563-
1564-
request = request_response_pb2.StartBatchOperationRequest(
1565-
namespace="default",
1566-
visibility_query='WorkflowType="test_workflow"',
1567-
job_id=f"batch-reset-{int(datetime.now().timestamp())}",
1568-
reason="test",
1569-
reset_operation=message_pb2.BatchOperationReset(
1570-
reset_type=reset_pb2.RESET_TYPE_LAST_WORKFLOW_TASK
1571-
),
1572-
)
1573-
1574-
response = await client.workflow_service.start_batch_operation(request)
1575-
assert response is not None

tests/test_service.py

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import inspect
22
import os
33
import re
4+
from datetime import timedelta
5+
from importlib import import_module
46
from typing import Any, Callable, Dict, Mapping, Tuple, Type
57

68
import google.protobuf.empty_pb2
79
import google.protobuf.message
10+
import google.protobuf.symbol_database
811
import grpc
912
import pytest
13+
from google.protobuf.descriptor import MethodDescriptor
1014

1115
import temporalio
1216
import temporalio.api.cloud.cloudservice.v1
@@ -19,6 +23,10 @@
1923
from temporalio.testing import WorkflowEnvironment
2024

2125

26+
def _camel_to_snake(name: str) -> str:
27+
return re.sub(r"(?<!^)(?=[A-Z])", "_", name).lower()
28+
29+
2230
def test_all_grpc_calls_present(client: Client):
2331
def assert_all_calls_present(
2432
service: Any,
@@ -111,7 +119,7 @@ def unary_unary(self, method, request_serializer, response_deserializer):
111119
getattr(self.package, name + "Response"),
112120
)
113121
# Camel to snake case
114-
name = re.sub(r"(?<!^)(?=[A-Z])", "_", name).lower()
122+
name = _camel_to_snake(name)
115123
self.calls[name] = req_resp
116124

117125

@@ -157,3 +165,74 @@ async def test_grpc_status(client: Client, env: WorkflowEnvironment):
157165
assert err.value.grpc_status.details[0].Is(
158166
temporalio.api.errordetails.v1.NamespaceNotFoundFailure.DESCRIPTOR
159167
)
168+
169+
170+
async def test_rpc_execution_not_unknown(client: Client):
171+
"""
172+
Execute each rpc method and expect a failure, but ensure the failure is not that the rpc method is unknown
173+
"""
174+
sym_db = google.protobuf.symbol_database.Default()
175+
service_client = client.service_client
176+
177+
async def test_method(
178+
target_service_name: str, method_descriptor: MethodDescriptor
179+
):
180+
if method_descriptor.client_streaming or method_descriptor.server_streaming:
181+
# skip streaming calls
182+
return
183+
184+
method_name = _camel_to_snake(method_descriptor.name)
185+
186+
# get request type and instantiate an empty request
187+
request_type = sym_db.GetSymbol(method_descriptor.input_type.full_name)
188+
request = request_type()
189+
190+
# get the appropriate temporal service from the service_client
191+
target_service = getattr(service_client, target_service_name)
192+
193+
# execute rpc and ensure that any exception that occurs is not the
194+
# "Unknown RPC call" error which indicates the python and rust rpc components
195+
# should be regenerated
196+
rpc_call = getattr(target_service, method_name)
197+
try:
198+
await rpc_call(request, timeout=timedelta(milliseconds=1))
199+
except Exception as err:
200+
assert (
201+
"Unknown RPC call" not in str(err)
202+
), f"Unexpected unknown-RPC error for {target_service_name}.{method_name}: {err}"
203+
204+
async def test_service(
205+
*, proto_module: str, proto_service: str, target_service_name: str
206+
):
207+
# load the module and test each method of the specified service
208+
module = import_module(proto_module)
209+
service_descriptor = module.DESCRIPTOR.services_by_name[proto_service]
210+
211+
for method_descriptor in service_descriptor.methods:
212+
await test_method(target_service_name, method_descriptor)
213+
214+
await test_service(
215+
proto_module="temporalio.api.workflowservice.v1.service_pb2",
216+
proto_service="WorkflowService",
217+
target_service_name="workflow_service",
218+
)
219+
await test_service(
220+
proto_module="temporalio.api.operatorservice.v1.service_pb2",
221+
proto_service="OperatorService",
222+
target_service_name="operator_service",
223+
)
224+
await test_service(
225+
proto_module="temporalio.api.cloud.cloudservice.v1.service_pb2",
226+
proto_service="CloudService",
227+
target_service_name="cloud_service",
228+
)
229+
await test_service(
230+
proto_module="temporalio.api.testservice.v1.service_pb2",
231+
proto_service="TestService",
232+
target_service_name="test_service",
233+
)
234+
await test_service(
235+
proto_module="temporalio.bridge.proto.health.v1.health_pb2",
236+
proto_service="Health",
237+
target_service_name="health_service",
238+
)

0 commit comments

Comments
 (0)