1# Copyright 2016 gRPC authors. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Tests application-provided metadata, status code, and details.""" 15 16import threading 17import unittest 18import logging 19 20import grpc 21 22from tests.unit import test_common 23from tests.unit.framework.common import test_constants 24from tests.unit.framework.common import test_control 25 26_SERIALIZED_REQUEST = b'\x46\x47\x48' 27_SERIALIZED_RESPONSE = b'\x49\x50\x51' 28 29_REQUEST_SERIALIZER = lambda unused_request: _SERIALIZED_REQUEST 30_REQUEST_DESERIALIZER = lambda unused_serialized_request: object() 31_RESPONSE_SERIALIZER = lambda unused_response: _SERIALIZED_RESPONSE 32_RESPONSE_DESERIALIZER = lambda unused_serialized_response: object() 33 34_SERVICE = 'test.TestService' 35_UNARY_UNARY = 'UnaryUnary' 36_UNARY_STREAM = 'UnaryStream' 37_STREAM_UNARY = 'StreamUnary' 38_STREAM_STREAM = 'StreamStream' 39 40_CLIENT_METADATA = (('client-md-key', 'client-md-key'), ('client-md-key-bin', 41 b'\x00\x01')) 42 43_SERVER_INITIAL_METADATA = (('server-initial-md-key', 44 'server-initial-md-value'), 45 ('server-initial-md-key-bin', b'\x00\x02')) 46 47_SERVER_TRAILING_METADATA = (('server-trailing-md-key', 48 'server-trailing-md-value'), 49 ('server-trailing-md-key-bin', b'\x00\x03')) 50 51_NON_OK_CODE = grpc.StatusCode.NOT_FOUND 52_DETAILS = 'Test details!' 53 54# calling abort should always fail an RPC, even for "invalid" codes 55_ABORT_CODES = (_NON_OK_CODE, 3, grpc.StatusCode.OK) 56_EXPECTED_CLIENT_CODES = (_NON_OK_CODE, grpc.StatusCode.UNKNOWN, 57 grpc.StatusCode.UNKNOWN) 58_EXPECTED_DETAILS = (_DETAILS, _DETAILS, '') 59 60 61class _Servicer(object): 62 63 def __init__(self): 64 self._lock = threading.Lock() 65 self._abort_call = False 66 self._code = None 67 self._details = None 68 self._exception = False 69 self._return_none = False 70 self._received_client_metadata = None 71 72 def unary_unary(self, request, context): 73 with self._lock: 74 self._received_client_metadata = context.invocation_metadata() 75 context.send_initial_metadata(_SERVER_INITIAL_METADATA) 76 context.set_trailing_metadata(_SERVER_TRAILING_METADATA) 77 if self._abort_call: 78 context.abort(self._code, self._details) 79 else: 80 if self._code is not None: 81 context.set_code(self._code) 82 if self._details is not None: 83 context.set_details(self._details) 84 if self._exception: 85 raise test_control.Defect() 86 else: 87 return None if self._return_none else object() 88 89 def unary_stream(self, request, context): 90 with self._lock: 91 self._received_client_metadata = context.invocation_metadata() 92 context.send_initial_metadata(_SERVER_INITIAL_METADATA) 93 context.set_trailing_metadata(_SERVER_TRAILING_METADATA) 94 if self._abort_call: 95 context.abort(self._code, self._details) 96 else: 97 if self._code is not None: 98 context.set_code(self._code) 99 if self._details is not None: 100 context.set_details(self._details) 101 for _ in range(test_constants.STREAM_LENGTH // 2): 102 yield _SERIALIZED_RESPONSE 103 if self._exception: 104 raise test_control.Defect() 105 106 def stream_unary(self, request_iterator, context): 107 with self._lock: 108 self._received_client_metadata = context.invocation_metadata() 109 context.send_initial_metadata(_SERVER_INITIAL_METADATA) 110 context.set_trailing_metadata(_SERVER_TRAILING_METADATA) 111 # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the 112 # request iterator. 113 list(request_iterator) 114 if self._abort_call: 115 context.abort(self._code, self._details) 116 else: 117 if self._code is not None: 118 context.set_code(self._code) 119 if self._details is not None: 120 context.set_details(self._details) 121 if self._exception: 122 raise test_control.Defect() 123 else: 124 return None if self._return_none else _SERIALIZED_RESPONSE 125 126 def stream_stream(self, request_iterator, context): 127 with self._lock: 128 self._received_client_metadata = context.invocation_metadata() 129 context.send_initial_metadata(_SERVER_INITIAL_METADATA) 130 context.set_trailing_metadata(_SERVER_TRAILING_METADATA) 131 # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the 132 # request iterator. 133 list(request_iterator) 134 if self._abort_call: 135 context.abort(self._code, self._details) 136 else: 137 if self._code is not None: 138 context.set_code(self._code) 139 if self._details is not None: 140 context.set_details(self._details) 141 for _ in range(test_constants.STREAM_LENGTH // 3): 142 yield object() 143 if self._exception: 144 raise test_control.Defect() 145 146 def set_abort_call(self): 147 with self._lock: 148 self._abort_call = True 149 150 def set_code(self, code): 151 with self._lock: 152 self._code = code 153 154 def set_details(self, details): 155 with self._lock: 156 self._details = details 157 158 def set_exception(self): 159 with self._lock: 160 self._exception = True 161 162 def set_return_none(self): 163 with self._lock: 164 self._return_none = True 165 166 def received_client_metadata(self): 167 with self._lock: 168 return self._received_client_metadata 169 170 171def _generic_handler(servicer): 172 method_handlers = { 173 _UNARY_UNARY: 174 grpc.unary_unary_rpc_method_handler( 175 servicer.unary_unary, 176 request_deserializer=_REQUEST_DESERIALIZER, 177 response_serializer=_RESPONSE_SERIALIZER), 178 _UNARY_STREAM: 179 grpc.unary_stream_rpc_method_handler(servicer.unary_stream), 180 _STREAM_UNARY: 181 grpc.stream_unary_rpc_method_handler(servicer.stream_unary), 182 _STREAM_STREAM: 183 grpc.stream_stream_rpc_method_handler( 184 servicer.stream_stream, 185 request_deserializer=_REQUEST_DESERIALIZER, 186 response_serializer=_RESPONSE_SERIALIZER), 187 } 188 return grpc.method_handlers_generic_handler(_SERVICE, method_handlers) 189 190 191class MetadataCodeDetailsTest(unittest.TestCase): 192 193 def setUp(self): 194 self._servicer = _Servicer() 195 self._server = test_common.test_server() 196 self._server.add_generic_rpc_handlers( 197 (_generic_handler(self._servicer),)) 198 port = self._server.add_insecure_port('[::]:0') 199 self._server.start() 200 201 self._channel = grpc.insecure_channel('localhost:{}'.format(port)) 202 self._unary_unary = self._channel.unary_unary( 203 '/'.join(( 204 '', 205 _SERVICE, 206 _UNARY_UNARY, 207 )), 208 request_serializer=_REQUEST_SERIALIZER, 209 response_deserializer=_RESPONSE_DESERIALIZER, 210 ) 211 self._unary_stream = self._channel.unary_stream( 212 '/'.join(( 213 '', 214 _SERVICE, 215 _UNARY_STREAM, 216 )),) 217 self._stream_unary = self._channel.stream_unary( 218 '/'.join(( 219 '', 220 _SERVICE, 221 _STREAM_UNARY, 222 )),) 223 self._stream_stream = self._channel.stream_stream( 224 '/'.join(( 225 '', 226 _SERVICE, 227 _STREAM_STREAM, 228 )), 229 request_serializer=_REQUEST_SERIALIZER, 230 response_deserializer=_RESPONSE_DESERIALIZER, 231 ) 232 233 def tearDown(self): 234 self._server.stop(None) 235 self._channel.close() 236 237 def testSuccessfulUnaryUnary(self): 238 self._servicer.set_details(_DETAILS) 239 240 unused_response, call = self._unary_unary.with_call( 241 object(), metadata=_CLIENT_METADATA) 242 243 self.assertTrue( 244 test_common.metadata_transmitted( 245 _CLIENT_METADATA, self._servicer.received_client_metadata())) 246 self.assertTrue( 247 test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, 248 call.initial_metadata())) 249 self.assertTrue( 250 test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, 251 call.trailing_metadata())) 252 self.assertIs(grpc.StatusCode.OK, call.code()) 253 254 def testSuccessfulUnaryStream(self): 255 self._servicer.set_details(_DETAILS) 256 257 response_iterator_call = self._unary_stream(_SERIALIZED_REQUEST, 258 metadata=_CLIENT_METADATA) 259 received_initial_metadata = response_iterator_call.initial_metadata() 260 list(response_iterator_call) 261 262 self.assertTrue( 263 test_common.metadata_transmitted( 264 _CLIENT_METADATA, self._servicer.received_client_metadata())) 265 self.assertTrue( 266 test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, 267 received_initial_metadata)) 268 self.assertTrue( 269 test_common.metadata_transmitted( 270 _SERVER_TRAILING_METADATA, 271 response_iterator_call.trailing_metadata())) 272 self.assertIs(grpc.StatusCode.OK, response_iterator_call.code()) 273 274 def testSuccessfulStreamUnary(self): 275 self._servicer.set_details(_DETAILS) 276 277 unused_response, call = self._stream_unary.with_call( 278 iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), 279 metadata=_CLIENT_METADATA) 280 281 self.assertTrue( 282 test_common.metadata_transmitted( 283 _CLIENT_METADATA, self._servicer.received_client_metadata())) 284 self.assertTrue( 285 test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, 286 call.initial_metadata())) 287 self.assertTrue( 288 test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, 289 call.trailing_metadata())) 290 self.assertIs(grpc.StatusCode.OK, call.code()) 291 292 def testSuccessfulStreamStream(self): 293 self._servicer.set_details(_DETAILS) 294 295 response_iterator_call = self._stream_stream(iter( 296 [object()] * test_constants.STREAM_LENGTH), 297 metadata=_CLIENT_METADATA) 298 received_initial_metadata = response_iterator_call.initial_metadata() 299 list(response_iterator_call) 300 301 self.assertTrue( 302 test_common.metadata_transmitted( 303 _CLIENT_METADATA, self._servicer.received_client_metadata())) 304 self.assertTrue( 305 test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, 306 received_initial_metadata)) 307 self.assertTrue( 308 test_common.metadata_transmitted( 309 _SERVER_TRAILING_METADATA, 310 response_iterator_call.trailing_metadata())) 311 self.assertIs(grpc.StatusCode.OK, response_iterator_call.code()) 312 313 def testAbortedUnaryUnary(self): 314 test_cases = zip(_ABORT_CODES, _EXPECTED_CLIENT_CODES, 315 _EXPECTED_DETAILS) 316 for abort_code, expected_code, expected_details in test_cases: 317 self._servicer.set_code(abort_code) 318 self._servicer.set_details(_DETAILS) 319 self._servicer.set_abort_call() 320 321 with self.assertRaises(grpc.RpcError) as exception_context: 322 self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) 323 324 self.assertTrue( 325 test_common.metadata_transmitted( 326 _CLIENT_METADATA, 327 self._servicer.received_client_metadata())) 328 self.assertTrue( 329 test_common.metadata_transmitted( 330 _SERVER_INITIAL_METADATA, 331 exception_context.exception.initial_metadata())) 332 self.assertTrue( 333 test_common.metadata_transmitted( 334 _SERVER_TRAILING_METADATA, 335 exception_context.exception.trailing_metadata())) 336 self.assertIs(expected_code, exception_context.exception.code()) 337 self.assertEqual(expected_details, 338 exception_context.exception.details()) 339 340 def testAbortedUnaryStream(self): 341 test_cases = zip(_ABORT_CODES, _EXPECTED_CLIENT_CODES, 342 _EXPECTED_DETAILS) 343 for abort_code, expected_code, expected_details in test_cases: 344 self._servicer.set_code(abort_code) 345 self._servicer.set_details(_DETAILS) 346 self._servicer.set_abort_call() 347 348 response_iterator_call = self._unary_stream( 349 _SERIALIZED_REQUEST, metadata=_CLIENT_METADATA) 350 received_initial_metadata = \ 351 response_iterator_call.initial_metadata() 352 with self.assertRaises(grpc.RpcError): 353 self.assertEqual(len(list(response_iterator_call)), 0) 354 355 self.assertTrue( 356 test_common.metadata_transmitted( 357 _CLIENT_METADATA, 358 self._servicer.received_client_metadata())) 359 self.assertTrue( 360 test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, 361 received_initial_metadata)) 362 self.assertTrue( 363 test_common.metadata_transmitted( 364 _SERVER_TRAILING_METADATA, 365 response_iterator_call.trailing_metadata())) 366 self.assertIs(expected_code, response_iterator_call.code()) 367 self.assertEqual(expected_details, response_iterator_call.details()) 368 369 def testAbortedStreamUnary(self): 370 test_cases = zip(_ABORT_CODES, _EXPECTED_CLIENT_CODES, 371 _EXPECTED_DETAILS) 372 for abort_code, expected_code, expected_details in test_cases: 373 self._servicer.set_code(abort_code) 374 self._servicer.set_details(_DETAILS) 375 self._servicer.set_abort_call() 376 377 with self.assertRaises(grpc.RpcError) as exception_context: 378 self._stream_unary.with_call(iter([_SERIALIZED_REQUEST] * 379 test_constants.STREAM_LENGTH), 380 metadata=_CLIENT_METADATA) 381 382 self.assertTrue( 383 test_common.metadata_transmitted( 384 _CLIENT_METADATA, 385 self._servicer.received_client_metadata())) 386 self.assertTrue( 387 test_common.metadata_transmitted( 388 _SERVER_INITIAL_METADATA, 389 exception_context.exception.initial_metadata())) 390 self.assertTrue( 391 test_common.metadata_transmitted( 392 _SERVER_TRAILING_METADATA, 393 exception_context.exception.trailing_metadata())) 394 self.assertIs(expected_code, exception_context.exception.code()) 395 self.assertEqual(expected_details, 396 exception_context.exception.details()) 397 398 def testAbortedStreamStream(self): 399 test_cases = zip(_ABORT_CODES, _EXPECTED_CLIENT_CODES, 400 _EXPECTED_DETAILS) 401 for abort_code, expected_code, expected_details in test_cases: 402 self._servicer.set_code(abort_code) 403 self._servicer.set_details(_DETAILS) 404 self._servicer.set_abort_call() 405 406 response_iterator_call = self._stream_stream( 407 iter([object()] * test_constants.STREAM_LENGTH), 408 metadata=_CLIENT_METADATA) 409 received_initial_metadata = \ 410 response_iterator_call.initial_metadata() 411 with self.assertRaises(grpc.RpcError): 412 self.assertEqual(len(list(response_iterator_call)), 0) 413 414 self.assertTrue( 415 test_common.metadata_transmitted( 416 _CLIENT_METADATA, 417 self._servicer.received_client_metadata())) 418 self.assertTrue( 419 test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, 420 received_initial_metadata)) 421 self.assertTrue( 422 test_common.metadata_transmitted( 423 _SERVER_TRAILING_METADATA, 424 response_iterator_call.trailing_metadata())) 425 self.assertIs(expected_code, response_iterator_call.code()) 426 self.assertEqual(expected_details, response_iterator_call.details()) 427 428 def testCustomCodeUnaryUnary(self): 429 self._servicer.set_code(_NON_OK_CODE) 430 self._servicer.set_details(_DETAILS) 431 432 with self.assertRaises(grpc.RpcError) as exception_context: 433 self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) 434 435 self.assertTrue( 436 test_common.metadata_transmitted( 437 _CLIENT_METADATA, self._servicer.received_client_metadata())) 438 self.assertTrue( 439 test_common.metadata_transmitted( 440 _SERVER_INITIAL_METADATA, 441 exception_context.exception.initial_metadata())) 442 self.assertTrue( 443 test_common.metadata_transmitted( 444 _SERVER_TRAILING_METADATA, 445 exception_context.exception.trailing_metadata())) 446 self.assertIs(_NON_OK_CODE, exception_context.exception.code()) 447 self.assertEqual(_DETAILS, exception_context.exception.details()) 448 449 def testCustomCodeUnaryStream(self): 450 self._servicer.set_code(_NON_OK_CODE) 451 self._servicer.set_details(_DETAILS) 452 453 response_iterator_call = self._unary_stream(_SERIALIZED_REQUEST, 454 metadata=_CLIENT_METADATA) 455 received_initial_metadata = response_iterator_call.initial_metadata() 456 with self.assertRaises(grpc.RpcError): 457 list(response_iterator_call) 458 459 self.assertTrue( 460 test_common.metadata_transmitted( 461 _CLIENT_METADATA, self._servicer.received_client_metadata())) 462 self.assertTrue( 463 test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, 464 received_initial_metadata)) 465 self.assertTrue( 466 test_common.metadata_transmitted( 467 _SERVER_TRAILING_METADATA, 468 response_iterator_call.trailing_metadata())) 469 self.assertIs(_NON_OK_CODE, response_iterator_call.code()) 470 self.assertEqual(_DETAILS, response_iterator_call.details()) 471 472 def testCustomCodeStreamUnary(self): 473 self._servicer.set_code(_NON_OK_CODE) 474 self._servicer.set_details(_DETAILS) 475 476 with self.assertRaises(grpc.RpcError) as exception_context: 477 self._stream_unary.with_call(iter([_SERIALIZED_REQUEST] * 478 test_constants.STREAM_LENGTH), 479 metadata=_CLIENT_METADATA) 480 481 self.assertTrue( 482 test_common.metadata_transmitted( 483 _CLIENT_METADATA, self._servicer.received_client_metadata())) 484 self.assertTrue( 485 test_common.metadata_transmitted( 486 _SERVER_INITIAL_METADATA, 487 exception_context.exception.initial_metadata())) 488 self.assertTrue( 489 test_common.metadata_transmitted( 490 _SERVER_TRAILING_METADATA, 491 exception_context.exception.trailing_metadata())) 492 self.assertIs(_NON_OK_CODE, exception_context.exception.code()) 493 self.assertEqual(_DETAILS, exception_context.exception.details()) 494 495 def testCustomCodeStreamStream(self): 496 self._servicer.set_code(_NON_OK_CODE) 497 self._servicer.set_details(_DETAILS) 498 499 response_iterator_call = self._stream_stream(iter( 500 [object()] * test_constants.STREAM_LENGTH), 501 metadata=_CLIENT_METADATA) 502 received_initial_metadata = response_iterator_call.initial_metadata() 503 with self.assertRaises(grpc.RpcError) as exception_context: 504 list(response_iterator_call) 505 506 self.assertTrue( 507 test_common.metadata_transmitted( 508 _CLIENT_METADATA, self._servicer.received_client_metadata())) 509 self.assertTrue( 510 test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, 511 received_initial_metadata)) 512 self.assertTrue( 513 test_common.metadata_transmitted( 514 _SERVER_TRAILING_METADATA, 515 exception_context.exception.trailing_metadata())) 516 self.assertIs(_NON_OK_CODE, exception_context.exception.code()) 517 self.assertEqual(_DETAILS, exception_context.exception.details()) 518 519 def testCustomCodeExceptionUnaryUnary(self): 520 self._servicer.set_code(_NON_OK_CODE) 521 self._servicer.set_details(_DETAILS) 522 self._servicer.set_exception() 523 524 with self.assertRaises(grpc.RpcError) as exception_context: 525 self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) 526 527 self.assertTrue( 528 test_common.metadata_transmitted( 529 _CLIENT_METADATA, self._servicer.received_client_metadata())) 530 self.assertTrue( 531 test_common.metadata_transmitted( 532 _SERVER_INITIAL_METADATA, 533 exception_context.exception.initial_metadata())) 534 self.assertTrue( 535 test_common.metadata_transmitted( 536 _SERVER_TRAILING_METADATA, 537 exception_context.exception.trailing_metadata())) 538 self.assertIs(_NON_OK_CODE, exception_context.exception.code()) 539 self.assertEqual(_DETAILS, exception_context.exception.details()) 540 541 def testCustomCodeExceptionUnaryStream(self): 542 self._servicer.set_code(_NON_OK_CODE) 543 self._servicer.set_details(_DETAILS) 544 self._servicer.set_exception() 545 546 response_iterator_call = self._unary_stream(_SERIALIZED_REQUEST, 547 metadata=_CLIENT_METADATA) 548 received_initial_metadata = response_iterator_call.initial_metadata() 549 with self.assertRaises(grpc.RpcError): 550 list(response_iterator_call) 551 552 self.assertTrue( 553 test_common.metadata_transmitted( 554 _CLIENT_METADATA, self._servicer.received_client_metadata())) 555 self.assertTrue( 556 test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, 557 received_initial_metadata)) 558 self.assertTrue( 559 test_common.metadata_transmitted( 560 _SERVER_TRAILING_METADATA, 561 response_iterator_call.trailing_metadata())) 562 self.assertIs(_NON_OK_CODE, response_iterator_call.code()) 563 self.assertEqual(_DETAILS, response_iterator_call.details()) 564 565 def testCustomCodeExceptionStreamUnary(self): 566 self._servicer.set_code(_NON_OK_CODE) 567 self._servicer.set_details(_DETAILS) 568 self._servicer.set_exception() 569 570 with self.assertRaises(grpc.RpcError) as exception_context: 571 self._stream_unary.with_call(iter([_SERIALIZED_REQUEST] * 572 test_constants.STREAM_LENGTH), 573 metadata=_CLIENT_METADATA) 574 575 self.assertTrue( 576 test_common.metadata_transmitted( 577 _CLIENT_METADATA, self._servicer.received_client_metadata())) 578 self.assertTrue( 579 test_common.metadata_transmitted( 580 _SERVER_INITIAL_METADATA, 581 exception_context.exception.initial_metadata())) 582 self.assertTrue( 583 test_common.metadata_transmitted( 584 _SERVER_TRAILING_METADATA, 585 exception_context.exception.trailing_metadata())) 586 self.assertIs(_NON_OK_CODE, exception_context.exception.code()) 587 self.assertEqual(_DETAILS, exception_context.exception.details()) 588 589 def testCustomCodeExceptionStreamStream(self): 590 self._servicer.set_code(_NON_OK_CODE) 591 self._servicer.set_details(_DETAILS) 592 self._servicer.set_exception() 593 594 response_iterator_call = self._stream_stream(iter( 595 [object()] * test_constants.STREAM_LENGTH), 596 metadata=_CLIENT_METADATA) 597 received_initial_metadata = response_iterator_call.initial_metadata() 598 with self.assertRaises(grpc.RpcError): 599 list(response_iterator_call) 600 601 self.assertTrue( 602 test_common.metadata_transmitted( 603 _CLIENT_METADATA, self._servicer.received_client_metadata())) 604 self.assertTrue( 605 test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, 606 received_initial_metadata)) 607 self.assertTrue( 608 test_common.metadata_transmitted( 609 _SERVER_TRAILING_METADATA, 610 response_iterator_call.trailing_metadata())) 611 self.assertIs(_NON_OK_CODE, response_iterator_call.code()) 612 self.assertEqual(_DETAILS, response_iterator_call.details()) 613 614 def testCustomCodeReturnNoneUnaryUnary(self): 615 self._servicer.set_code(_NON_OK_CODE) 616 self._servicer.set_details(_DETAILS) 617 self._servicer.set_return_none() 618 619 with self.assertRaises(grpc.RpcError) as exception_context: 620 self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) 621 622 self.assertTrue( 623 test_common.metadata_transmitted( 624 _CLIENT_METADATA, self._servicer.received_client_metadata())) 625 self.assertTrue( 626 test_common.metadata_transmitted( 627 _SERVER_INITIAL_METADATA, 628 exception_context.exception.initial_metadata())) 629 self.assertTrue( 630 test_common.metadata_transmitted( 631 _SERVER_TRAILING_METADATA, 632 exception_context.exception.trailing_metadata())) 633 self.assertIs(_NON_OK_CODE, exception_context.exception.code()) 634 self.assertEqual(_DETAILS, exception_context.exception.details()) 635 636 def testCustomCodeReturnNoneStreamUnary(self): 637 self._servicer.set_code(_NON_OK_CODE) 638 self._servicer.set_details(_DETAILS) 639 self._servicer.set_return_none() 640 641 with self.assertRaises(grpc.RpcError) as exception_context: 642 self._stream_unary.with_call(iter([_SERIALIZED_REQUEST] * 643 test_constants.STREAM_LENGTH), 644 metadata=_CLIENT_METADATA) 645 646 self.assertTrue( 647 test_common.metadata_transmitted( 648 _CLIENT_METADATA, self._servicer.received_client_metadata())) 649 self.assertTrue( 650 test_common.metadata_transmitted( 651 _SERVER_INITIAL_METADATA, 652 exception_context.exception.initial_metadata())) 653 self.assertTrue( 654 test_common.metadata_transmitted( 655 _SERVER_TRAILING_METADATA, 656 exception_context.exception.trailing_metadata())) 657 self.assertIs(_NON_OK_CODE, exception_context.exception.code()) 658 self.assertEqual(_DETAILS, exception_context.exception.details()) 659 660 661if __name__ == '__main__': 662 logging.basicConfig() 663 unittest.main(verbosity=2) 664