@@ -143,6 +143,115 @@ public async Task Intercept_WrapClientStream_ClientStreamWrapperExecuted()
143143 Assert . IsNotNull ( call . GetTrailers ( ) ) ;
144144 }
145145
146+ [ TestCase ( StatusCode . OK ) ]
147+ [ TestCase ( StatusCode . Internal ) ]
148+ public async Task Intercept_OnCompleted_StatusReturned ( StatusCode statusCode )
149+ {
150+ await StatusReturnedCore ( new OnCompletedInterceptor ( ) , statusCode ) ;
151+ }
152+
153+ [ TestCase ( StatusCode . OK ) ]
154+ [ TestCase ( StatusCode . Internal ) ]
155+ public async Task Intercept_Await_StatusReturned ( StatusCode statusCode )
156+ {
157+ await StatusReturnedCore ( new AwaitInterceptor ( ) , statusCode ) ;
158+ }
159+
160+ private static async Task StatusReturnedCore ( StatusInterceptor interceptor , StatusCode statusCode )
161+ {
162+ // Arrange
163+ var httpClient = ClientTestHelpers . CreateTestClient ( async request =>
164+ {
165+ if ( statusCode == StatusCode . OK )
166+ {
167+ var streamContent = await ClientTestHelpers . CreateResponseContent ( new HelloReply { Message = "PASS" } ) . DefaultTimeout ( ) ;
168+ return ResponseUtils . CreateResponse ( HttpStatusCode . OK , streamContent ) ;
169+ }
170+ else
171+ {
172+ return ResponseUtils . CreateHeadersOnlyResponse ( HttpStatusCode . OK , statusCode ) ;
173+ }
174+ } ) ;
175+
176+ var invoker = HttpClientCallInvokerFactory . Create ( httpClient ) ;
177+
178+ // Act
179+ var callInvoker = invoker . Intercept ( interceptor ) ;
180+
181+ var call = callInvoker . AsyncUnaryCall ( ClientTestHelpers . ServiceMethod , Host , new CallOptions ( ) , new HelloRequest ( ) ) ;
182+
183+ // Assert
184+ if ( statusCode == StatusCode . OK )
185+ {
186+ var result = await call . ResponseAsync . DefaultTimeout ( ) ;
187+ Assert . AreEqual ( "PASS" , result . Message ) ;
188+ }
189+ else
190+ {
191+ var ex = await ExceptionAssert . ThrowsAsync < RpcException > ( ( ) => call . ResponseAsync ) . DefaultTimeout ( ) ;
192+ Assert . AreEqual ( statusCode , ex . StatusCode ) ;
193+ }
194+
195+ var interceptorStatusCode = await interceptor . GetStatusCodeAsync ( ) . DefaultTimeout ( ) ;
196+ Assert . AreEqual ( statusCode , interceptorStatusCode ) ;
197+ }
198+
199+ private abstract class StatusInterceptor : Interceptor
200+ {
201+ protected readonly TaskCompletionSource < StatusCode > StatusTcs = new TaskCompletionSource < StatusCode > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
202+
203+ public Task < StatusCode > GetStatusCodeAsync ( ) => StatusTcs . Task ;
204+ }
205+
206+ private class OnCompletedInterceptor : StatusInterceptor
207+ {
208+ public override AsyncUnaryCall < TResponse > AsyncUnaryCall < TRequest , TResponse > ( TRequest request , ClientInterceptorContext < TRequest , TResponse > context , AsyncUnaryCallContinuation < TRequest , TResponse > continuation )
209+ {
210+ var result = continuation ( request , context ) ;
211+ result . GetAwaiter ( ) . OnCompleted ( ( ) =>
212+ {
213+ try
214+ {
215+ StatusTcs . SetResult ( result . GetStatus ( ) . StatusCode ) ;
216+ }
217+ catch ( Exception ex )
218+ {
219+ StatusTcs . SetException ( ex ) ;
220+ }
221+ } ) ;
222+ return result ;
223+ }
224+ }
225+
226+ private class AwaitInterceptor : StatusInterceptor
227+ {
228+ public override AsyncUnaryCall < TResponse > AsyncUnaryCall < TRequest , TResponse > ( TRequest request , ClientInterceptorContext < TRequest , TResponse > context , AsyncUnaryCallContinuation < TRequest , TResponse > continuation )
229+ {
230+ var call = continuation ( request , context ) ;
231+
232+ return new AsyncUnaryCall < TResponse > ( HandleResponse ( call ) , call . ResponseHeadersAsync , call . GetStatus , call . GetTrailers , call . Dispose ) ;
233+
234+ async Task < TResponse > HandleResponse ( AsyncUnaryCall < TResponse > call )
235+ {
236+ try
237+ {
238+ return await call . ResponseAsync ;
239+ }
240+ finally
241+ {
242+ try
243+ {
244+ StatusTcs . SetResult ( call . GetStatus ( ) . StatusCode ) ;
245+ }
246+ catch ( Exception ex )
247+ {
248+ StatusTcs . SetException ( ex ) ;
249+ }
250+ }
251+ }
252+ }
253+ }
254+
146255 private class ClientStreamingCountingInterceptor : Interceptor
147256 {
148257 public override AsyncClientStreamingCall < TRequest , TResponse > AsyncClientStreamingCall < TRequest , TResponse > ( ClientInterceptorContext < TRequest , TResponse > context , AsyncClientStreamingCallContinuation < TRequest , TResponse > continuation )
0 commit comments