• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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