blob: c8bc372202d87bb84c9f0d0987f702d98a55833f [file] [log] [blame]
Jan Tattermuschdad17242015-08-08 23:27:04 -07001#region Copyright notice and license
2
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003// Copyright 2015 gRPC authors.
Jan Tattermuschdad17242015-08-08 23:27:04 -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 Tattermuschdad17242015-08-08 23:27:04 -07008//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009// http://www.apache.org/licenses/LICENSE-2.0
Jan Tattermuschdad17242015-08-08 23:27:04 -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 Tattermuschdad17242015-08-08 23:27:04 -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 public class ContextPropagationTest
32 {
33 MockServiceHelper helper;
34 Server server;
35 Channel channel;
36
37 [SetUp]
38 public void Init()
39 {
40 helper = new MockServiceHelper();
41
42 server = helper.GetServer();
43 server.Start();
44 channel = helper.GetChannel();
45 }
46
47 [TearDown]
48 public void Cleanup()
49 {
Jan Tattermusch2b357952015-08-20 14:54:33 -070050 channel.ShutdownAsync().Wait();
Jan Tattermuschdad17242015-08-08 23:27:04 -070051 server.ShutdownAsync().Wait();
52 }
53
Jan Tattermuschdad17242015-08-08 23:27:04 -070054 [Test]
55 public async Task PropagateCancellation()
56 {
Jan Tattermuschde0d8b52015-12-10 18:53:55 -080057 var readyToCancelTcs = new TaskCompletionSource<object>();
58 var successTcs = new TaskCompletionSource<string>();
59
Jan Tattermuschdad17242015-08-08 23:27:04 -070060 helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
61 {
Jan Tattermuschde0d8b52015-12-10 18:53:55 -080062 readyToCancelTcs.SetResult(null); // child call running, ready to parent call
63
64 while (!context.CancellationToken.IsCancellationRequested)
65 {
66 await Task.Delay(10);
67 }
68 successTcs.SetResult("CHILD_CALL_CANCELLED");
69 return "";
Jan Tattermuschdad17242015-08-08 23:27:04 -070070 });
71
72 helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
73 {
74 var propagationToken = context.CreatePropagationToken();
75 Assert.IsNotNull(propagationToken.ParentCall);
76
77 var callOptions = new CallOptions(propagationToken: propagationToken);
Jan Tattermuschde0d8b52015-12-10 18:53:55 -080078 try
79 {
80 await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz");
81 }
82 catch(RpcException)
83 {
84 // Child call will get cancelled, eat the exception.
85 }
86 return "";
Jan Tattermuschdad17242015-08-08 23:27:04 -070087 });
88
89 var cts = new CancellationTokenSource();
Jan Tattermuschde0d8b52015-12-10 18:53:55 -080090 var parentCall = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token)));
91 await readyToCancelTcs.Task;
92 cts.Cancel();
Jan Tattermusch71702b12016-05-25 20:48:38 -070093 try
94 {
95 // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock.
96 await parentCall;
97 Assert.Fail();
98 }
99 catch (RpcException)
100 {
101 }
Jan Tattermuschde0d8b52015-12-10 18:53:55 -0800102 Assert.AreEqual("CHILD_CALL_CANCELLED", await successTcs.Task);
Jan Tattermuschdad17242015-08-08 23:27:04 -0700103 }
104
105 [Test]
106 public async Task PropagateDeadline()
107 {
108 var deadline = DateTime.UtcNow.AddDays(7);
Jan Tattermusch2fb313c2017-08-09 09:41:25 +0200109 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
Jan Tattermuschdad17242015-08-08 23:27:04 -0700110 {
111 Assert.IsTrue(context.Deadline < deadline.AddMinutes(1));
112 Assert.IsTrue(context.Deadline > deadline.AddMinutes(-1));
Jan Tattermusch2fb313c2017-08-09 09:41:25 +0200113 return Task.FromResult("PASS");
Jan Tattermuschdad17242015-08-08 23:27:04 -0700114 });
115
116 helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
117 {
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700118 Assert.Throws(typeof(ArgumentException), () =>
119 {
120 // Trying to override deadline while propagating deadline from parent call will throw.
121 Calls.BlockingUnaryCall(helper.CreateUnaryCall(
122 new CallOptions(deadline: DateTime.UtcNow.AddDays(8),
123 propagationToken: context.CreatePropagationToken())), "");
124 });
125
Jan Tattermuschdad17242015-08-08 23:27:04 -0700126 var callOptions = new CallOptions(propagationToken: context.CreatePropagationToken());
127 return await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz");
128 });
129
130 var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(deadline: deadline)));
131 await call.RequestStream.CompleteAsync();
132 Assert.AreEqual("PASS", await call);
133 }
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700134
135 [Test]
136 public async Task SuppressDeadlinePropagation()
137 {
Jan Tattermusch2fb313c2017-08-09 09:41:25 +0200138 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700139 {
140 Assert.AreEqual(DateTime.MaxValue, context.Deadline);
Jan Tattermusch2fb313c2017-08-09 09:41:25 +0200141 return Task.FromResult("PASS");
Jan Tattermusch9698b5b2015-08-10 16:40:19 -0700142 });
143
144 helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
145 {
146 Assert.IsTrue(context.CancellationToken.CanBeCanceled);
147
148 var callOptions = new CallOptions(propagationToken: context.CreatePropagationToken(new ContextPropagationOptions(propagateDeadline: false)));
149 return await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz");
150 });
151
152 var cts = new CancellationTokenSource();
153 var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(deadline: DateTime.UtcNow.AddDays(7))));
154 await call.RequestStream.CompleteAsync();
155 Assert.AreEqual("PASS", await call);
156 }
Jan Tattermuschdad17242015-08-08 23:27:04 -0700157 }
158}