blob: b89c1afcc35c6db0e814ec53de3723a327e0db5d [file] [log] [blame]
Jan Tattermusch0846b682015-07-23 17:02:12 -07001#region Copyright notice and license
2
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003// Copyright 2015 gRPC authors.
Jan Tattermusch0846b682015-07-23 17:02:12 -07004//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005// 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
Jan Tattermusch0846b682015-07-23 17:02:12 -07008//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009// http://www.apache.org/licenses/LICENSE-2.0
Jan Tattermusch0846b682015-07-23 17:02:12 -070010//
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011// 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.
Jan Tattermusch0846b682015-07-23 17:02:12 -070016
17#endregion
18
19using System;
20using System.Diagnostics;
21using System.Linq;
22using System.Threading;
23using System.Threading.Tasks;
24using Grpc.Core;
25using Grpc.Core.Internal;
26using Grpc.Core.Utils;
27using NUnit.Framework;
28
29namespace Grpc.Core.Tests
30{
31 /// <summary>
32 /// Tests for Deadline support.
33 /// </summary>
34 public class TimeoutsTest
35 {
Jan Tattermuscha4291e72015-08-07 19:13:31 -070036 MockServiceHelper helper;
Jan Tattermusch0846b682015-07-23 17:02:12 -070037 Server server;
38 Channel channel;
39
40 [SetUp]
41 public void Init()
42 {
Jan Tattermuscha4291e72015-08-07 19:13:31 -070043 helper = new MockServiceHelper();
44
Jan Tattermusch5b0b3922015-08-07 19:07:14 -070045 server = helper.GetServer();
Jan Tattermuscha4291e72015-08-07 19:13:31 -070046 server.Start();
Jan Tattermusch5b0b3922015-08-07 19:07:14 -070047 channel = helper.GetChannel();
Jan Tattermusch0846b682015-07-23 17:02:12 -070048 }
49
50 [TearDown]
51 public void Cleanup()
52 {
Jan Tattermusch2b357952015-08-20 14:54:33 -070053 channel.ShutdownAsync().Wait();
Jan Tattermusch0846b682015-07-23 17:02:12 -070054 server.ShutdownAsync().Wait();
55 }
56
Jan Tattermusch0846b682015-07-23 17:02:12 -070057 [Test]
58 public void InfiniteDeadline()
59 {
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020060 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070061 {
Jan Tattermusch5b0b3922015-08-07 19:07:14 -070062 Assert.AreEqual(DateTime.MaxValue, context.Deadline);
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020063 return Task.FromResult("PASS");
Jan Tattermusch5b0b3922015-08-07 19:07:14 -070064 });
65
Jan Tattermusch0846b682015-07-23 17:02:12 -070066 // no deadline specified, check server sees infinite deadline
Jan Tattermusch5b0b3922015-08-07 19:07:14 -070067 Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
Jan Tattermusch0846b682015-07-23 17:02:12 -070068
69 // DateTime.MaxValue deadline specified, check server sees infinite deadline
Jan Tattermusch5b0b3922015-08-07 19:07:14 -070070 Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.MaxValue)), "abc"));
Jan Tattermusch0846b682015-07-23 17:02:12 -070071 }
72
73 [Test]
74 public void DeadlineTransferredToServer()
75 {
Jan Tattermusch5b0b3922015-08-07 19:07:14 -070076 var clientDeadline = DateTime.UtcNow + TimeSpan.FromDays(7);
Jan Tattermusch0846b682015-07-23 17:02:12 -070077
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020078 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070079 {
Jan Tattermusch5b0b3922015-08-07 19:07:14 -070080 // 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);
Jan Tattermusch2fb313c2017-08-09 09:41:25 +020084 return Task.FromResult("PASS");
Jan Tattermusch5b0b3922015-08-07 19:07:14 -070085 });
86 Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: clientDeadline)), "abc");
Jan Tattermusch0846b682015-07-23 17:02:12 -070087 }
88
89 [Test]
Jan Tattermusch49313ce2015-07-23 19:17:30 -070090 public void DeadlineInThePast()
91 {
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070092 helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
93 {
Jan Tattermusch5b0b3922015-08-07 19:07:14 -070094 await Task.Delay(60000);
95 return "FAIL";
96 });
Jan Tattermusch49313ce2015-07-23 19:17:30 -070097
Jan Tattermusch0abb8472015-08-07 20:28:44 -070098 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 });
Jan Tattermusch49313ce2015-07-23 19:17:30 -0700101 }
102
103 [Test]
Jan Tattermusch0846b682015-07-23 17:02:12 -0700104 public void DeadlineExceededStatusOnTimeout()
105 {
Jan Tattermuschc75c57c2015-08-07 22:07:40 -0700106 helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
107 {
Jan Tattermusch5b0b3922015-08-07 19:07:14 -0700108 await Task.Delay(60000);
109 return "FAIL";
110 });
Jan Tattermusch0846b682015-07-23 17:02:12 -0700111
Jan Tattermusch0abb8472015-08-07 20:28:44 -0700112 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 });
Jan Tattermusch0846b682015-07-23 17:02:12 -0700115 }
116
117 [Test]
Jan Tattermusch2615f392015-08-07 20:41:26 -0700118 public async Task ServerReceivesCancellationOnTimeout()
Jan Tattermusch0846b682015-07-23 17:02:12 -0700119 {
Jan Tattermusch2615f392015-08-07 20:41:26 -0700120 var serverReceivedCancellationTcs = new TaskCompletionSource<bool>();
Jan Tattermusch5b0b3922015-08-07 19:07:14 -0700121
Jan Tattermuschc75c57c2015-08-07 22:07:40 -0700122 helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
123 {
Jan Tattermusch5b0b3922015-08-07 19:07:14 -0700124 // wait until cancellation token is fired.
125 var tcs = new TaskCompletionSource<object>();
126 context.CancellationToken.Register(() => { tcs.SetResult(null); });
127 await tcs.Task;
Jan Tattermusch2615f392015-08-07 20:41:26 -0700128 serverReceivedCancellationTcs.SetResult(true);
Jan Tattermusch5b0b3922015-08-07 19:07:14 -0700129 return "";
130 });
Jan Tattermusch0846b682015-07-23 17:02:12 -0700131
Jan Tattermusch0abb8472015-08-07 20:28:44 -0700132 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 });
Jan Tattermuscha4291e72015-08-07 19:13:31 -0700135
Jan Tattermusch2615f392015-08-07 20:41:26 -0700136 Assert.IsTrue(await serverReceivedCancellationTcs.Task);
Jan Tattermusch0846b682015-07-23 17:02:12 -0700137 }
138 }
139}