blob: 9a828f307e245384a83f07cb960134a965c65eb3 [file] [log] [blame]
Jan Tattermusch633434a2017-07-24 17:11:35 +02001#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
19using System;
20using NUnit.Framework;
21using System.Threading;
22using System.Threading.Tasks;
23
24namespace 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]
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]
44 public void Cleanup()
45 {
46 channel.ShutdownAsync().Wait();
47 server.ShutdownAsync().Wait();
48 }
49
50 [Test]
51 public void BlockingCallInServerHandlerDoesNotDeadlock()
52 {
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020053 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
Jan Tattermusch633434a2017-07-24 17:11:35 +020054 {
55 int recursionDepth = int.Parse(request);
56 if (recursionDepth <= 0) {
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020057 return Task.FromResult("SUCCESS");
Jan Tattermusch633434a2017-07-24 17:11:35 +020058 }
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020059 var response = Calls.BlockingUnaryCall(helper.CreateUnaryCall(), (recursionDepth - 1).ToString());
60 return Task.FromResult(response);
Jan Tattermusch633434a2017-07-24 17:11:35 +020061 });
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]
68 public void HandlerDoesNotRunOnGrpcThread()
69 {
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020070 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
Jan Tattermusch633434a2017-07-24 17:11:35 +020071 {
72 if (IsRunningOnGrpcThreadPool()) {
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020073 return Task.FromResult("Server handler should not run on gRPC threadpool thread.");
Jan Tattermusch633434a2017-07-24 17:11:35 +020074 }
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020075 return Task.FromResult(request);
Jan Tattermusch633434a2017-07-24 17:11:35 +020076 });
77
78 Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC"));
79 }
80
81 [Test]
82 public async Task ContinuationDoesNotRunOnGrpcThread()
83 {
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020084 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
Jan Tattermusch633434a2017-07-24 17:11:35 +020085 {
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020086 return Task.FromResult(request);
Jan Tattermusch633434a2017-07-24 17:11:35 +020087 });
88
89 await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "ABC");
90 Assert.IsFalse(IsRunningOnGrpcThreadPool());
91 }
92
93 private static bool IsRunningOnGrpcThreadPool()
94 {
95 var threadName = Thread.CurrentThread.Name ?? "";
96 return threadName.Contains("grpc");
97 }
98 }
99}