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.Collections.Generic; 21 using System.Linq; 22 using System.Threading; 23 using System.Threading.Tasks; 24 using Grpc.Core; 25 using Grpc.Core.Utils; 26 using NUnit.Framework; 27 28 namespace Math.Tests 29 { 30 /// <summary> 31 /// Math client talks to local math server. 32 /// </summary> 33 public class MathClientServerTest 34 { 35 const string Host = "localhost"; 36 Server server; 37 Channel channel; 38 Math.MathClient client; 39 40 [OneTimeSetUp] Init()41 public void Init() 42 { 43 // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 44 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) 45 { 46 Services = { Math.BindService(new MathServiceImpl()) }, 47 Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } 48 }; 49 server.Start(); 50 channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); 51 client = new Math.MathClient(channel); 52 } 53 54 [OneTimeTearDown] Cleanup()55 public void Cleanup() 56 { 57 channel.ShutdownAsync().Wait(); 58 server.ShutdownAsync().Wait(); 59 } 60 61 [Test] Div1()62 public void Div1() 63 { 64 DivReply response = client.Div(new DivArgs { Dividend = 10, Divisor = 3 }); 65 Assert.AreEqual(3, response.Quotient); 66 Assert.AreEqual(1, response.Remainder); 67 } 68 69 [Test] Div2()70 public void Div2() 71 { 72 DivReply response = client.Div(new DivArgs { Dividend = 0, Divisor = 1 }); 73 Assert.AreEqual(0, response.Quotient); 74 Assert.AreEqual(0, response.Remainder); 75 } 76 77 [Test] DivByZero()78 public void DivByZero() 79 { 80 var ex = Assert.Throws<RpcException>(() => client.Div(new DivArgs { Dividend = 0, Divisor = 0 })); 81 Assert.AreEqual(StatusCode.InvalidArgument, ex.Status.StatusCode); 82 } 83 84 [Test] DivAsync()85 public async Task DivAsync() 86 { 87 DivReply response = await client.DivAsync(new DivArgs { Dividend = 10, Divisor = 3 }); 88 Assert.AreEqual(3, response.Quotient); 89 Assert.AreEqual(1, response.Remainder); 90 } 91 92 [Test] Fib()93 public async Task Fib() 94 { 95 using (var call = client.Fib(new FibArgs { Limit = 6 })) 96 { 97 var responses = await call.ResponseStream.ToListAsync(); 98 CollectionAssert.AreEqual(new List<long> { 1, 1, 2, 3, 5, 8 }, 99 responses.Select((n) => n.Num_)); 100 } 101 } 102 103 [Test] FibWithCancel()104 public async Task FibWithCancel() 105 { 106 var cts = new CancellationTokenSource(); 107 108 using (var call = client.Fib(new FibArgs { Limit = 0 }, cancellationToken: cts.Token)) 109 { 110 List<long> responses = new List<long>(); 111 112 try 113 { 114 while (await call.ResponseStream.MoveNext()) 115 { 116 if (responses.Count == 0) 117 { 118 cts.CancelAfter(500); // make sure we cancel soon 119 } 120 responses.Add(call.ResponseStream.Current.Num_); 121 } 122 Assert.Fail(); 123 } 124 catch (RpcException e) 125 { 126 Assert.IsTrue(responses.Count > 0); 127 Assert.AreEqual(StatusCode.Cancelled, e.Status.StatusCode); 128 } 129 } 130 } 131 132 [Test] FibWithDeadline()133 public void FibWithDeadline() 134 { 135 using (var call = client.Fib(new FibArgs { Limit = 0 }, 136 deadline: DateTime.UtcNow.AddMilliseconds(500))) 137 { 138 var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.ToListAsync()); 139 140 // We can't guarantee the status code always DeadlineExceeded. See issue #2685. 141 Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal }); 142 } 143 } 144 145 // TODO: test Fib with limit=0 and cancellation 146 [Test] Sum()147 public async Task Sum() 148 { 149 using (var call = client.Sum()) 150 { 151 var numbers = new List<long> { 10, 20, 30 }.Select(n => new Num { Num_ = n }); 152 153 await call.RequestStream.WriteAllAsync(numbers); 154 var result = await call.ResponseAsync; 155 Assert.AreEqual(60, result.Num_); 156 } 157 } 158 159 [Test] DivMany()160 public async Task DivMany() 161 { 162 var divArgsList = new List<DivArgs> 163 { 164 new DivArgs { Dividend = 10, Divisor = 3 }, 165 new DivArgs { Dividend = 100, Divisor = 21 }, 166 new DivArgs { Dividend = 7, Divisor = 2 } 167 }; 168 169 using (var call = client.DivMany()) 170 { 171 await call.RequestStream.WriteAllAsync(divArgsList); 172 var result = await call.ResponseStream.ToListAsync(); 173 174 CollectionAssert.AreEqual(new long[] { 3, 4, 3 }, result.Select((divReply) => divReply.Quotient)); 175 CollectionAssert.AreEqual(new long[] { 1, 16, 1 }, result.Select((divReply) => divReply.Remainder)); 176 } 177 } 178 } 179 } 180