1 #region Copyright notice and license 2 3 // Copyright 2018 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #endregion 18 19 using System; 20 using System.Collections.Generic; 21 using System.Linq; 22 using System.Text; 23 using System.Threading; 24 using System.Threading.Tasks; 25 using Grpc.Core; 26 using Grpc.Core.Interceptors; 27 using Grpc.Core.Internal; 28 using Grpc.Core.Tests; 29 using Grpc.Core.Utils; 30 using NUnit.Framework; 31 32 namespace Grpc.Core.Interceptors.Tests 33 { 34 public class ServerInterceptorTest 35 { 36 const string Host = "127.0.0.1"; 37 38 [Test] AddRequestHeaderInServerInterceptor()39 public void AddRequestHeaderInServerInterceptor() 40 { 41 var helper = new MockServiceHelper(Host); 42 const string MetadataKey = "x-interceptor"; 43 const string MetadataValue = "hello world"; 44 var interceptor = new ServerCallContextInterceptor(ctx => ctx.RequestHeaders.Add(new Metadata.Entry(MetadataKey, MetadataValue))); 45 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) => 46 { 47 var interceptorHeader = context.RequestHeaders.Last(m => (m.Key == MetadataKey)).Value; 48 Assert.AreEqual(interceptorHeader, MetadataValue); 49 return Task.FromResult("PASS"); 50 }); 51 helper.ServiceDefinition = helper.ServiceDefinition.Intercept(interceptor); 52 var server = helper.GetServer(); 53 server.Start(); 54 var channel = helper.GetChannel(); 55 Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); 56 } 57 58 [Test] VerifyInterceptorOrdering()59 public void VerifyInterceptorOrdering() 60 { 61 var helper = new MockServiceHelper(Host); 62 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) => 63 { 64 return Task.FromResult("PASS"); 65 }); 66 var stringBuilder = new StringBuilder(); 67 helper.ServiceDefinition = helper.ServiceDefinition 68 .Intercept(new ServerCallContextInterceptor(ctx => stringBuilder.Append("A"))) 69 .Intercept(new ServerCallContextInterceptor(ctx => stringBuilder.Append("B1")), 70 new ServerCallContextInterceptor(ctx => stringBuilder.Append("B2")), 71 new ServerCallContextInterceptor(ctx => stringBuilder.Append("B3"))) 72 .Intercept(new ServerCallContextInterceptor(ctx => stringBuilder.Append("C"))); 73 var server = helper.GetServer(); 74 server.Start(); 75 var channel = helper.GetChannel(); 76 Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); 77 Assert.AreEqual("CB1B2B3A", stringBuilder.ToString()); 78 } 79 80 [Test] CheckNullInterceptorRegistrationFails()81 public void CheckNullInterceptorRegistrationFails() 82 { 83 var helper = new MockServiceHelper(Host); 84 var sd = helper.ServiceDefinition; 85 Assert.Throws<ArgumentNullException>(() => sd.Intercept(default(Interceptor))); 86 Assert.Throws<ArgumentNullException>(() => sd.Intercept(new[]{default(Interceptor)})); 87 Assert.Throws<ArgumentNullException>(() => sd.Intercept(new[]{new ServerCallContextInterceptor(ctx=>{}), null})); 88 Assert.Throws<ArgumentNullException>(() => sd.Intercept(default(Interceptor[]))); 89 } 90 91 private class ServerCallContextInterceptor : Interceptor 92 { 93 readonly Action<ServerCallContext> interceptor; 94 ServerCallContextInterceptor(Action<ServerCallContext> interceptor)95 public ServerCallContextInterceptor(Action<ServerCallContext> interceptor) 96 { 97 GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); 98 this.interceptor = interceptor; 99 } 100 UnaryServerHandler(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)101 public override Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation) 102 { 103 interceptor(context); 104 return continuation(request, context); 105 } 106 ClientStreamingServerHandler(IAsyncStreamReader<TRequest> requestStream, ServerCallContext context, ClientStreamingServerMethod<TRequest, TResponse> continuation)107 public override Task<TResponse> ClientStreamingServerHandler<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream, ServerCallContext context, ClientStreamingServerMethod<TRequest, TResponse> continuation) 108 { 109 interceptor(context); 110 return continuation(requestStream, context); 111 } 112 ServerStreamingServerHandler(TRequest request, IServerStreamWriter<TResponse> responseStream, ServerCallContext context, ServerStreamingServerMethod<TRequest, TResponse> continuation)113 public override Task ServerStreamingServerHandler<TRequest, TResponse>(TRequest request, IServerStreamWriter<TResponse> responseStream, ServerCallContext context, ServerStreamingServerMethod<TRequest, TResponse> continuation) 114 { 115 interceptor(context); 116 return continuation(request, responseStream, context); 117 } 118 DuplexStreamingServerHandler(IAsyncStreamReader<TRequest> requestStream, IServerStreamWriter<TResponse> responseStream, ServerCallContext context, DuplexStreamingServerMethod<TRequest, TResponse> continuation)119 public override Task DuplexStreamingServerHandler<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream, IServerStreamWriter<TResponse> responseStream, ServerCallContext context, DuplexStreamingServerMethod<TRequest, TResponse> continuation) 120 { 121 interceptor(context); 122 return continuation(requestStream, responseStream, context); 123 } 124 } 125 } 126 } 127