blob: e797dd82f2498a80bd648857de21b2cfb9d1c52a [file] [log] [blame]
Jan Tattermuscha7fff862015-02-13 11:08:08 -08001#region Copyright notice and license
2
Jan Tattermuschaf77b3d2015-02-13 11:22:21 -08003// Copyright 2015, Google Inc.
Jan Tattermuscha7fff862015-02-13 11:08:08 -08004// All rights reserved.
Craig Tiller190d3602015-02-18 09:23:38 -08005//
Jan Tattermuscha7fff862015-02-13 11:08:08 -08006// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
Craig Tiller190d3602015-02-18 09:23:38 -08009//
Jan Tattermuscha7fff862015-02-13 11:08:08 -080010// * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12// * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16// * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
Craig Tiller190d3602015-02-18 09:23:38 -080019//
Jan Tattermuscha7fff862015-02-13 11:08:08 -080020// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32#endregion
33
Jan Tattermuscha7608b02015-02-03 17:54:38 -080034using System;
Jan Tattermusch337a2dd2015-02-13 15:41:41 -080035using System.Diagnostics;
Jan Tattermusch30868622015-02-19 09:22:33 -080036using System.Threading;
Jan Tattermuscha7608b02015-02-03 17:54:38 -080037using System.Threading.Tasks;
Jan Tattermusch30868622015-02-19 09:22:33 -080038using Grpc.Core;
39using Grpc.Core.Internal;
40using Grpc.Core.Utils;
41using NUnit.Framework;
Jan Tattermuscha7608b02015-02-03 17:54:38 -080042
Jan Tattermusch30868622015-02-19 09:22:33 -080043namespace Grpc.Core.Tests
Jan Tattermuscha7608b02015-02-03 17:54:38 -080044{
45 public class ClientServerTest
46 {
Jan Tattermuscha5272b62015-04-30 11:56:46 -070047 const string Host = "localhost";
48 const string ServiceName = "/tests.Test";
Jan Tattermuscha7608b02015-02-03 17:54:38 -080049
Jan Tattermusche5c44602015-05-01 11:12:34 -070050 static readonly Method<string, string> EchoMethod = new Method<string, string>(
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080051 MethodType.Unary,
Jan Tattermusche5c44602015-05-01 11:12:34 -070052 "/tests.Test/Echo",
53 Marshallers.StringMarshaller,
54 Marshallers.StringMarshaller);
55
56 static readonly Method<string, string> ConcatAndEchoMethod = new Method<string, string>(
57 MethodType.ClientStreaming,
58 "/tests.Test/ConcatAndEcho",
59 Marshallers.StringMarshaller,
60 Marshallers.StringMarshaller);
61
62 static readonly Method<string, string> NonexistentMethod = new Method<string, string>(
63 MethodType.Unary,
64 "/tests.Test/NonexistentMethod",
Jan Tattermusch15111f52015-02-05 18:15:14 -080065 Marshallers.StringMarshaller,
66 Marshallers.StringMarshaller);
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -080067
Jan Tattermuscha5272b62015-04-30 11:56:46 -070068 static readonly ServerServiceDefinition ServiceDefinition = ServerServiceDefinition.CreateBuilder(ServiceName)
Jan Tattermusche5c44602015-05-01 11:12:34 -070069 .AddMethod(EchoMethod, EchoHandler)
70 .AddMethod(ConcatAndEchoMethod, ConcatAndEchoHandler)
71 .Build();
72
73 Server server;
74 Channel channel;
Jan Tattermuscha5272b62015-04-30 11:56:46 -070075
Jan Tattermusche5c44602015-05-01 11:12:34 -070076 [SetUp]
77 public void Init()
78 {
Jan Tattermusche5c44602015-05-01 11:12:34 -070079 server = new Server();
80 server.AddServiceDefinition(ServiceDefinition);
Jan Tattermusch03e82e22015-05-06 16:37:12 -070081 int port = server.AddListeningPort(Host, Server.PickUnusedPort);
Jan Tattermusche5c44602015-05-01 11:12:34 -070082 server.Start();
Jan Tattermuschda71a4d2015-06-08 15:36:53 -070083 channel = new Channel(Host, port);
Jan Tattermusche5c44602015-05-01 11:12:34 -070084 }
85
86 [TearDown]
Jan Tattermusch607307d2015-02-18 11:05:45 -080087 public void Cleanup()
88 {
Jan Tattermusche5c44602015-05-01 11:12:34 -070089 channel.Dispose();
90 server.ShutdownAsync().Wait();
91 }
92
93 [TestFixtureTearDown]
94 public void CleanupClass()
95 {
Jan Tattermuschec776242015-02-18 14:06:56 -080096 GrpcEnvironment.Shutdown();
Jan Tattermusch607307d2015-02-18 11:05:45 -080097 }
98
Jan Tattermuscha7608b02015-02-03 17:54:38 -080099 [Test]
Jan Tattermusch337a2dd2015-02-13 15:41:41 -0800100 public void UnaryCall()
Jan Tattermuscha7608b02015-02-03 17:54:38 -0800101 {
Jan Tattermusche5c44602015-05-01 11:12:34 -0700102 var call = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
103 Assert.AreEqual("ABC", Calls.BlockingUnaryCall(call, "ABC", CancellationToken.None));
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700104 }
105
106 [Test]
Jan Tattermusche5c44602015-05-01 11:12:34 -0700107 public void UnaryCall_ServerHandlerThrows()
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700108 {
Jan Tattermusche5c44602015-05-01 11:12:34 -0700109 var call = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700110 try
111 {
Jan Tattermusche5c44602015-05-01 11:12:34 -0700112 Calls.BlockingUnaryCall(call, "THROW", CancellationToken.None);
113 Assert.Fail();
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700114 }
Jan Tattermusche5c44602015-05-01 11:12:34 -0700115 catch (RpcException e)
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700116 {
Jan Tattermusche5c44602015-05-01 11:12:34 -0700117 Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
Jan Tattermuscha7608b02015-02-03 17:54:38 -0800118 }
Jan Tattermusche5c44602015-05-01 11:12:34 -0700119 }
Craig Tiller190d3602015-02-18 09:23:38 -0800120
Jan Tattermusche5c44602015-05-01 11:12:34 -0700121 [Test]
122 public void AsyncUnaryCall()
123 {
124 var call = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
125 var result = Calls.AsyncUnaryCall(call, "ABC", CancellationToken.None).Result;
126 Assert.AreEqual("ABC", result);
127 }
128
129 [Test]
130 public void AsyncUnaryCall_ServerHandlerThrows()
131 {
Jan Tattermusch32d95b92015-05-04 17:56:32 -0700132 Task.Run(async () =>
Jan Tattermusche5c44602015-05-01 11:12:34 -0700133 {
134 var call = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
135 try
136 {
137 await Calls.AsyncUnaryCall(call, "THROW", CancellationToken.None);
138 Assert.Fail();
139 }
140 catch (RpcException e)
141 {
Jan Tattermusch32d95b92015-05-04 17:56:32 -0700142 Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700143 }
144 }).Wait();
145 }
146
147 [Test]
148 public void ClientStreamingCall()
149 {
150 Task.Run(async () =>
151 {
152 var call = new Call<string, string>(ServiceName, ConcatAndEchoMethod, channel, Metadata.Empty);
153 var callResult = Calls.AsyncClientStreamingCall(call, CancellationToken.None);
154
155 await callResult.RequestStream.WriteAll(new string[] { "A", "B", "C" });
156 Assert.AreEqual("ABC", await callResult.Result);
157 }).Wait();
158 }
159
160 [Test]
Jan Tattermusche5c44602015-05-01 11:12:34 -0700161 public void ClientStreamingCall_CancelAfterBegin()
162 {
163 Task.Run(async () =>
164 {
165 var call = new Call<string, string>(ServiceName, ConcatAndEchoMethod, channel, Metadata.Empty);
166
167 var cts = new CancellationTokenSource();
168 var callResult = Calls.AsyncClientStreamingCall(call, cts.Token);
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700169
170 // TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it.
171 await Task.Delay(1000);
Jan Tattermusche5c44602015-05-01 11:12:34 -0700172 cts.Cancel();
173
174 try
175 {
176 await callResult.Result;
177 }
Jan Tattermusch618647d2015-05-01 11:23:28 -0700178 catch (RpcException e)
Jan Tattermusche5c44602015-05-01 11:12:34 -0700179 {
180 Assert.AreEqual(StatusCode.Cancelled, e.Status.StatusCode);
181 }
182 }).Wait();
183 }
184
185 [Test]
186 public void UnaryCall_DisposedChannel()
187 {
188 channel.Dispose();
189
190 var call = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
191 Assert.Throws(typeof(ObjectDisposedException), () => Calls.BlockingUnaryCall(call, "ABC", CancellationToken.None));
Jan Tattermuscha7608b02015-02-03 17:54:38 -0800192 }
193
Jan Tattermusch337a2dd2015-02-13 15:41:41 -0800194 [Test]
195 public void UnaryCallPerformance()
196 {
Jan Tattermusche5c44602015-05-01 11:12:34 -0700197 var call = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
198 BenchmarkUtil.RunBenchmark(100, 100,
199 () => { Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)); });
Jan Tattermusch337a2dd2015-02-13 15:41:41 -0800200 }
Jan Tattermusch797b8752015-06-17 10:53:59 -0700201
202 [Test]
203 public void UnknownMethodHandler()
204 {
205 var call = new Call<string, string>(ServiceName, NonexistentMethod, channel, Metadata.Empty);
206 try
207 {
208 Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken));
209 Assert.Fail();
210 }
211 catch (RpcException e)
212 {
213 Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
214 }
215 }
Jan Tattermusch337a2dd2015-02-13 15:41:41 -0800216
Jan Tattermusch8ab1f7e2015-05-06 15:56:30 -0700217 private static async Task<string> EchoHandler(ServerCallContext context, string request)
Jan Tattermusch8d7ce432015-02-18 11:20:43 -0800218 {
Jan Tattermusche5c44602015-05-01 11:12:34 -0700219 if (request == "THROW")
220 {
221 throw new Exception("This was thrown on purpose by a test");
222 }
223 return request;
224 }
225
Jan Tattermusch8ab1f7e2015-05-06 15:56:30 -0700226 private static async Task<string> ConcatAndEchoHandler(ServerCallContext context, IAsyncStreamReader<string> requestStream)
Jan Tattermusche5c44602015-05-01 11:12:34 -0700227 {
228 string result = "";
229 await requestStream.ForEach(async (request) =>
230 {
231 if (request == "THROW")
232 {
233 throw new Exception("This was thrown on purpose by a test");
234 }
235 result += request;
236 });
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700237 // simulate processing takes some time.
238 await Task.Delay(250);
239 return result;
Jan Tattermusch8ce5e8b2015-02-05 10:56:49 -0800240 }
Jan Tattermuscha7608b02015-02-03 17:54:38 -0800241 }
242}