1 #region Copyright notice and license 2 3 // Copyright 2015 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 NUnit.Framework; 21 using System.Threading; 22 using System.Threading.Tasks; 23 24 namespace Grpc.Core.Tests 25 { 26 public class ThreadingModelTest 27 { 28 const string Host = "127.0.0.1"; 29 30 MockServiceHelper helper; 31 Server server; 32 Channel channel; 33 34 [SetUp] Init()35 public void Init() 36 { 37 helper = new MockServiceHelper(Host); 38 server = helper.GetServer(); 39 server.Start(); 40 channel = helper.GetChannel(); 41 } 42 43 [TearDown] Cleanup()44 public void Cleanup() 45 { 46 channel.ShutdownAsync().Wait(); 47 server.ShutdownAsync().Wait(); 48 } 49 50 [Test] BlockingCallInServerHandlerDoesNotDeadlock()51 public void BlockingCallInServerHandlerDoesNotDeadlock() 52 { 53 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) => 54 { 55 int recursionDepth = int.Parse(request); 56 if (recursionDepth <= 0) { 57 return Task.FromResult("SUCCESS"); 58 } 59 var response = Calls.BlockingUnaryCall(helper.CreateUnaryCall(), (recursionDepth - 1).ToString()); 60 return Task.FromResult(response); 61 }); 62 63 int maxRecursionDepth = Environment.ProcessorCount * 2; // make sure we have more pending blocking calls than threads in GrpcThreadPool 64 Assert.AreEqual("SUCCESS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), maxRecursionDepth.ToString())); 65 } 66 67 [Test] HandlerDoesNotRunOnGrpcThread()68 public void HandlerDoesNotRunOnGrpcThread() 69 { 70 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) => 71 { 72 if (IsRunningOnGrpcThreadPool()) { 73 return Task.FromResult("Server handler should not run on gRPC threadpool thread."); 74 } 75 return Task.FromResult(request); 76 }); 77 78 Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC")); 79 } 80 81 [Test] ContinuationDoesNotRunOnGrpcThread()82 public async Task ContinuationDoesNotRunOnGrpcThread() 83 { 84 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) => 85 { 86 return Task.FromResult(request); 87 }); 88 89 await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "ABC"); 90 Assert.IsFalse(IsRunningOnGrpcThreadPool()); 91 } 92 IsRunningOnGrpcThreadPool()93 private static bool IsRunningOnGrpcThreadPool() 94 { 95 var threadName = Thread.CurrentThread.Name ?? ""; 96 return threadName.Contains("grpc"); 97 } 98 } 99 } 100