• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 System.Diagnostics;
21 using System.Linq;
22 using System.Threading;
23 using System.Threading.Tasks;
24 using Grpc.Core;
25 using Grpc.Core.Internal;
26 using Grpc.Core.Utils;
27 using NUnit.Framework;
28 
29 namespace Grpc.Core.Tests
30 {
31     /// <summary>
32     /// Tests for Deadline support.
33     /// </summary>
34     public class TimeoutsTest
35     {
36         MockServiceHelper helper;
37         Server server;
38         Channel channel;
39 
40         [SetUp]
Init()41         public void Init()
42         {
43             helper = new MockServiceHelper();
44 
45             server = helper.GetServer();
46             server.Start();
47             channel = helper.GetChannel();
48         }
49 
50         [TearDown]
Cleanup()51         public void Cleanup()
52         {
53             channel.ShutdownAsync().Wait();
54             server.ShutdownAsync().Wait();
55         }
56 
57         [Test]
InfiniteDeadline()58         public void InfiniteDeadline()
59         {
60             helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
61             {
62                 Assert.AreEqual(DateTime.MaxValue, context.Deadline);
63                 return Task.FromResult("PASS");
64             });
65 
66             // no deadline specified, check server sees infinite deadline
67             Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
68 
69             // DateTime.MaxValue deadline specified, check server sees infinite deadline
70             Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.MaxValue)), "abc"));
71         }
72 
73         [Test]
DeadlineTransferredToServer()74         public void DeadlineTransferredToServer()
75         {
76             var clientDeadline = DateTime.UtcNow + TimeSpan.FromDays(7);
77 
78             helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
79             {
80                 // A fairly relaxed check that the deadline set by client and deadline seen by server
81                 // are in agreement. C core takes care of the work with transferring deadline over the wire,
82                 // so we don't need an exact check here.
83                 Assert.IsTrue(Math.Abs((clientDeadline - context.Deadline).TotalMilliseconds) < 5000);
84                 return Task.FromResult("PASS");
85             });
86             Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: clientDeadline)), "abc");
87         }
88 
89         [Test]
DeadlineInThePast()90         public void DeadlineInThePast()
91         {
92             helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
93             {
94                 await Task.Delay(60000);
95                 return "FAIL";
96             });
97 
98             var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.MinValue)), "abc"));
99             // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
100             Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
101         }
102 
103         [Test]
DeadlineExceededStatusOnTimeout()104         public void DeadlineExceededStatusOnTimeout()
105         {
106             helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
107             {
108                 await Task.Delay(60000);
109                 return "FAIL";
110             });
111 
112             var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.UtcNow.Add(TimeSpan.FromSeconds(5)))), "abc"));
113             // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
114             Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
115         }
116 
117         [Test]
ServerReceivesCancellationOnTimeout()118         public async Task ServerReceivesCancellationOnTimeout()
119         {
120             var serverReceivedCancellationTcs = new TaskCompletionSource<bool>();
121 
122             helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
123             {
124                 // wait until cancellation token is fired.
125                 var tcs = new TaskCompletionSource<object>();
126                 context.CancellationToken.Register(() => { tcs.SetResult(null); });
127                 await tcs.Task;
128                 serverReceivedCancellationTcs.SetResult(true);
129                 return "";
130             });
131 
132             var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.UtcNow.Add(TimeSpan.FromSeconds(5)))), "abc"));
133             // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
134             Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
135 
136             Assert.IsTrue(await serverReceivedCancellationTcs.Task);
137         }
138     }
139 }
140