Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 1 | #region Copyright notice and license |
| 2 | |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 3 | // Copyright 2015 gRPC authors. |
Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 4 | // |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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 |
Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 8 | // |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 9 | // http://www.apache.org/licenses/LICENSE-2.0 |
Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 10 | // |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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. |
Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 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 | 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 Tattermusch | 2b35795 | 2015-08-20 14:54:33 -0700 | [diff] [blame] | 50 | channel.ShutdownAsync().Wait(); |
Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 51 | server.ShutdownAsync().Wait(); |
| 52 | } |
| 53 | |
Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 54 | [Test] |
| 55 | public async Task PropagateCancellation() |
| 56 | { |
Jan Tattermusch | de0d8b5 | 2015-12-10 18:53:55 -0800 | [diff] [blame] | 57 | var readyToCancelTcs = new TaskCompletionSource<object>(); |
| 58 | var successTcs = new TaskCompletionSource<string>(); |
| 59 | |
Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 60 | helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) => |
| 61 | { |
Jan Tattermusch | de0d8b5 | 2015-12-10 18:53:55 -0800 | [diff] [blame] | 62 | 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 Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 70 | }); |
| 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 Tattermusch | de0d8b5 | 2015-12-10 18:53:55 -0800 | [diff] [blame] | 78 | 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 Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 87 | }); |
| 88 | |
| 89 | var cts = new CancellationTokenSource(); |
Jan Tattermusch | de0d8b5 | 2015-12-10 18:53:55 -0800 | [diff] [blame] | 90 | var parentCall = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token))); |
| 91 | await readyToCancelTcs.Task; |
| 92 | cts.Cancel(); |
Jan Tattermusch | 71702b1 | 2016-05-25 20:48:38 -0700 | [diff] [blame] | 93 | 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 Tattermusch | de0d8b5 | 2015-12-10 18:53:55 -0800 | [diff] [blame] | 102 | Assert.AreEqual("CHILD_CALL_CANCELLED", await successTcs.Task); |
Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | [Test] |
| 106 | public async Task PropagateDeadline() |
| 107 | { |
| 108 | var deadline = DateTime.UtcNow.AddDays(7); |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 109 | helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) => |
Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 110 | { |
| 111 | Assert.IsTrue(context.Deadline < deadline.AddMinutes(1)); |
| 112 | Assert.IsTrue(context.Deadline > deadline.AddMinutes(-1)); |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 113 | return Task.FromResult("PASS"); |
Jan Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 114 | }); |
| 115 | |
| 116 | helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) => |
| 117 | { |
Jan Tattermusch | 9698b5b | 2015-08-10 16:40:19 -0700 | [diff] [blame] | 118 | 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 Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 126 | 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 Tattermusch | 9698b5b | 2015-08-10 16:40:19 -0700 | [diff] [blame] | 134 | |
| 135 | [Test] |
| 136 | public async Task SuppressDeadlinePropagation() |
| 137 | { |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 138 | helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) => |
Jan Tattermusch | 9698b5b | 2015-08-10 16:40:19 -0700 | [diff] [blame] | 139 | { |
| 140 | Assert.AreEqual(DateTime.MaxValue, context.Deadline); |
Jan Tattermusch | 2fb313c | 2017-08-09 09:41:25 +0200 | [diff] [blame] | 141 | return Task.FromResult("PASS"); |
Jan Tattermusch | 9698b5b | 2015-08-10 16:40:19 -0700 | [diff] [blame] | 142 | }); |
| 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 Tattermusch | dad1724 | 2015-08-08 23:27:04 -0700 | [diff] [blame] | 157 | } |
| 158 | } |