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"""Test of RPCs made against gRPC Python's application-layer API.""" 15 16import itertools 17import threading 18import unittest 19import logging 20from concurrent import futures 21 22import grpc 23from grpc.framework.foundation import logging_pool 24 25from tests.unit._rpc_test_helpers import ( 26 TIMEOUT_SHORT, Callback, unary_unary_multi_callable, 27 unary_stream_multi_callable, unary_stream_non_blocking_multi_callable, 28 stream_unary_multi_callable, stream_stream_multi_callable, 29 stream_stream_non_blocking_multi_callable, BaseRPCTest) 30from tests.unit.framework.common import test_constants 31 32 33class RPCPart1Test(BaseRPCTest, unittest.TestCase): 34 35 def testExpiredStreamRequestBlockingUnaryResponse(self): 36 requests = tuple( 37 b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) 38 request_iterator = iter(requests) 39 40 multi_callable = stream_unary_multi_callable(self._channel) 41 with self._control.pause(): 42 with self.assertRaises(grpc.RpcError) as exception_context: 43 multi_callable( 44 request_iterator, 45 timeout=TIMEOUT_SHORT, 46 metadata=(('test', 47 'ExpiredStreamRequestBlockingUnaryResponse'),)) 48 49 self.assertIsInstance(exception_context.exception, grpc.RpcError) 50 self.assertIsInstance(exception_context.exception, grpc.Call) 51 self.assertIsNotNone(exception_context.exception.initial_metadata()) 52 self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, 53 exception_context.exception.code()) 54 self.assertIsNotNone(exception_context.exception.details()) 55 self.assertIsNotNone(exception_context.exception.trailing_metadata()) 56 57 def testExpiredStreamRequestFutureUnaryResponse(self): 58 requests = tuple( 59 b'\x07\x18' for _ in range(test_constants.STREAM_LENGTH)) 60 request_iterator = iter(requests) 61 callback = Callback() 62 63 multi_callable = stream_unary_multi_callable(self._channel) 64 with self._control.pause(): 65 response_future = multi_callable.future( 66 request_iterator, 67 timeout=TIMEOUT_SHORT, 68 metadata=(('test', 'ExpiredStreamRequestFutureUnaryResponse'),)) 69 with self.assertRaises(grpc.FutureTimeoutError): 70 response_future.result(timeout=TIMEOUT_SHORT / 2.0) 71 response_future.add_done_callback(callback) 72 value_passed_to_callback = callback.value() 73 74 with self.assertRaises(grpc.RpcError) as exception_context: 75 response_future.result() 76 self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) 77 self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, 78 exception_context.exception.code()) 79 self.assertIsInstance(response_future.exception(), grpc.RpcError) 80 self.assertIsNotNone(response_future.traceback()) 81 self.assertIs(response_future, value_passed_to_callback) 82 self.assertIsNotNone(response_future.initial_metadata()) 83 self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) 84 self.assertIsNotNone(response_future.details()) 85 self.assertIsNotNone(response_future.trailing_metadata()) 86 87 def testExpiredStreamRequestStreamResponse(self): 88 self._expired_stream_request_stream_response( 89 stream_stream_multi_callable(self._channel)) 90 91 def testExpiredStreamRequestStreamResponseNonBlocking(self): 92 self._expired_stream_request_stream_response( 93 stream_stream_non_blocking_multi_callable(self._channel)) 94 95 def testFailedUnaryRequestBlockingUnaryResponse(self): 96 request = b'\x37\x17' 97 98 multi_callable = unary_unary_multi_callable(self._channel) 99 with self._control.fail(): 100 with self.assertRaises(grpc.RpcError) as exception_context: 101 multi_callable.with_call( 102 request, 103 metadata=(('test', 104 'FailedUnaryRequestBlockingUnaryResponse'),)) 105 106 self.assertIs(grpc.StatusCode.UNKNOWN, 107 exception_context.exception.code()) 108 # sanity checks on to make sure returned string contains default members 109 # of the error 110 debug_error_string = exception_context.exception.debug_error_string() 111 self.assertIn('created', debug_error_string) 112 self.assertIn('description', debug_error_string) 113 self.assertIn('file', debug_error_string) 114 self.assertIn('file_line', debug_error_string) 115 116 def testFailedUnaryRequestFutureUnaryResponse(self): 117 request = b'\x37\x17' 118 callback = Callback() 119 120 multi_callable = unary_unary_multi_callable(self._channel) 121 with self._control.fail(): 122 response_future = multi_callable.future( 123 request, 124 metadata=(('test', 'FailedUnaryRequestFutureUnaryResponse'),)) 125 response_future.add_done_callback(callback) 126 value_passed_to_callback = callback.value() 127 128 self.assertIsInstance(response_future, grpc.Future) 129 self.assertIsInstance(response_future, grpc.Call) 130 with self.assertRaises(grpc.RpcError) as exception_context: 131 response_future.result() 132 self.assertIs(grpc.StatusCode.UNKNOWN, 133 exception_context.exception.code()) 134 self.assertIsInstance(response_future.exception(), grpc.RpcError) 135 self.assertIsNotNone(response_future.traceback()) 136 self.assertIs(grpc.StatusCode.UNKNOWN, 137 response_future.exception().code()) 138 self.assertIs(response_future, value_passed_to_callback) 139 140 def testFailedUnaryRequestStreamResponse(self): 141 self._failed_unary_request_stream_response( 142 unary_stream_multi_callable(self._channel)) 143 144 def testFailedUnaryRequestStreamResponseNonBlocking(self): 145 self._failed_unary_request_stream_response( 146 unary_stream_non_blocking_multi_callable(self._channel)) 147 148 def testFailedStreamRequestBlockingUnaryResponse(self): 149 requests = tuple( 150 b'\x47\x58' for _ in range(test_constants.STREAM_LENGTH)) 151 request_iterator = iter(requests) 152 153 multi_callable = stream_unary_multi_callable(self._channel) 154 with self._control.fail(): 155 with self.assertRaises(grpc.RpcError) as exception_context: 156 multi_callable( 157 request_iterator, 158 metadata=(('test', 159 'FailedStreamRequestBlockingUnaryResponse'),)) 160 161 self.assertIs(grpc.StatusCode.UNKNOWN, 162 exception_context.exception.code()) 163 164 def testFailedStreamRequestFutureUnaryResponse(self): 165 requests = tuple( 166 b'\x07\x18' for _ in range(test_constants.STREAM_LENGTH)) 167 request_iterator = iter(requests) 168 callback = Callback() 169 170 multi_callable = stream_unary_multi_callable(self._channel) 171 with self._control.fail(): 172 response_future = multi_callable.future( 173 request_iterator, 174 metadata=(('test', 'FailedStreamRequestFutureUnaryResponse'),)) 175 response_future.add_done_callback(callback) 176 value_passed_to_callback = callback.value() 177 178 with self.assertRaises(grpc.RpcError) as exception_context: 179 response_future.result() 180 self.assertIs(grpc.StatusCode.UNKNOWN, response_future.code()) 181 self.assertIs(grpc.StatusCode.UNKNOWN, 182 exception_context.exception.code()) 183 self.assertIsInstance(response_future.exception(), grpc.RpcError) 184 self.assertIsNotNone(response_future.traceback()) 185 self.assertIs(response_future, value_passed_to_callback) 186 187 def testFailedStreamRequestStreamResponse(self): 188 self._failed_stream_request_stream_response( 189 stream_stream_multi_callable(self._channel)) 190 191 def testFailedStreamRequestStreamResponseNonBlocking(self): 192 self._failed_stream_request_stream_response( 193 stream_stream_non_blocking_multi_callable(self._channel)) 194 195 def testIgnoredUnaryRequestFutureUnaryResponse(self): 196 request = b'\x37\x17' 197 198 multi_callable = unary_unary_multi_callable(self._channel) 199 multi_callable.future( 200 request, 201 metadata=(('test', 'IgnoredUnaryRequestFutureUnaryResponse'),)) 202 203 def testIgnoredUnaryRequestStreamResponse(self): 204 self._ignored_unary_stream_request_future_unary_response( 205 unary_stream_multi_callable(self._channel)) 206 207 def testIgnoredUnaryRequestStreamResponseNonBlocking(self): 208 self._ignored_unary_stream_request_future_unary_response( 209 unary_stream_non_blocking_multi_callable(self._channel)) 210 211 def testIgnoredStreamRequestFutureUnaryResponse(self): 212 requests = tuple( 213 b'\x07\x18' for _ in range(test_constants.STREAM_LENGTH)) 214 request_iterator = iter(requests) 215 216 multi_callable = stream_unary_multi_callable(self._channel) 217 multi_callable.future( 218 request_iterator, 219 metadata=(('test', 'IgnoredStreamRequestFutureUnaryResponse'),)) 220 221 def testIgnoredStreamRequestStreamResponse(self): 222 self._ignored_stream_request_stream_response( 223 stream_stream_multi_callable(self._channel)) 224 225 def testIgnoredStreamRequestStreamResponseNonBlocking(self): 226 self._ignored_stream_request_stream_response( 227 stream_stream_non_blocking_multi_callable(self._channel)) 228 229 230if __name__ == '__main__': 231 logging.basicConfig() 232 unittest.main(verbosity=2) 233