aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jan Tattermusch <jtattermusch@google.com>2016-05-03 09:41:15 -0700
committerGravatar Jan Tattermusch <jtattermusch@google.com>2016-05-03 12:58:04 -0700
commitb6a9016fc234714632a20cb25dc2e822a72243f8 (patch)
tree58428e4ad8e6f0672d45a2c1b05f9ff05e6848d7
parent230c93279f753164db49e46db7204a1b8408ee09 (diff)
add tests for AsyncCallServer
-rw-r--r--src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj2
-rw-r--r--src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs134
-rw-r--r--src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs134
-rw-r--r--src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs177
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCallServer.cs9
5 files changed, 324 insertions, 132 deletions
diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
index 0cd059c232..47131fc454 100644
--- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
+++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
@@ -84,6 +84,8 @@
<Compile Include="SanityTest.cs" />
<Compile Include="HalfcloseTest.cs" />
<Compile Include="NUnitMain.cs" />
+ <Compile Include="Internal\FakeNativeCall.cs" />
+ <Compile Include="Internal\AsyncCallServerTest.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
new file mode 100644
index 0000000000..8c178657a1
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
@@ -0,0 +1,134 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+using Grpc.Core.Internal;
+using NUnit.Framework;
+
+namespace Grpc.Core.Internal.Tests
+{
+ /// <summary>
+ /// Uses fake native call to test interaction of <c>AsyncCallServer</c> wrapping code with C core in different situations.
+ /// </summary>
+ public class AsyncCallServerTest
+ {
+ Server server;
+ FakeNativeCall fakeCall;
+ AsyncCallServer<string, string> asyncCallServer;
+
+ [SetUp]
+ public void Init()
+ {
+ var environment = GrpcEnvironment.AddRef();
+ server = new Server();
+
+ fakeCall = new FakeNativeCall();
+ asyncCallServer = new AsyncCallServer<string, string>(
+ Marshallers.StringMarshaller.Serializer, Marshallers.StringMarshaller.Deserializer,
+ environment,
+ server);
+ asyncCallServer.InitializeForTesting(fakeCall);
+ }
+
+ [TearDown]
+ public void Cleanup()
+ {
+ GrpcEnvironment.Release();
+ }
+
+ [Test]
+ public void CancelNotificationAfterStartDisposes()
+ {
+ var finishedTask = asyncCallServer.ServerSideCallAsync();
+ var requestStream = new ServerRequestStream<string, string>(asyncCallServer);
+ var responseStream = new ServerResponseStream<string, string>(asyncCallServer);
+
+ // Finishing requestStream is needed for dispose to happen.
+ var moveNextTask = requestStream.MoveNext();
+ fakeCall.ReceivedMessageHandler(true, null);
+ Assert.IsFalse(moveNextTask.Result);
+
+ fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true);
+ AssertDisposed(asyncCallServer, fakeCall, finishedTask);
+ }
+
+ [Test]
+ public void ReadAfterCancelNotificationCanSucceed()
+ {
+ var finishedTask = asyncCallServer.ServerSideCallAsync();
+ var requestStream = new ServerRequestStream<string, string>(asyncCallServer);
+ var responseStream = new ServerResponseStream<string, string>(asyncCallServer);
+
+ fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true);
+
+ // Check that startin a read after cancel notification has been processed is legal.
+ var moveNextTask = requestStream.MoveNext();
+ fakeCall.ReceivedMessageHandler(true, null);
+ Assert.IsFalse(moveNextTask.Result);
+
+ AssertDisposed(asyncCallServer, fakeCall, finishedTask);
+ }
+
+
+ // TODO: read completion failure ...
+
+ // TODO:
+
+
+
+ // TODO: write fails...
+
+ // TODO: write completion fails...
+
+ // TODO: cancellation delivered...
+
+ // TODO: cancel notification in the middle of a read...
+
+ // TODO: cancel notification in the middle of a write...
+
+ // TODO: cancellation delivered...
+
+ // TODO: what does writing status do to reads?
+
+ static void AssertDisposed(AsyncCallServer<string, string> asyncCallServer, FakeNativeCall fakeCall, Task finishedTask)
+ {
+ Assert.IsTrue(fakeCall.IsDisposed);
+ Assert.IsTrue(finishedTask.IsCompleted);
+ Assert.DoesNotThrow(() => finishedTask.Wait());
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
index ed2d22815b..abe9d4a2e6 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
@@ -42,7 +42,7 @@ using NUnit.Framework;
namespace Grpc.Core.Internal.Tests
{
/// <summary>
- /// Uses fake native call to test interaction of wrapping code with C core in different situations.
+ /// Uses fake native call to test interaction of <c>AsyncCall</c> wrapping code with C core in different situations.
/// </summary>
public class AsyncCallTest
{
@@ -480,139 +480,9 @@ namespace Grpc.Core.Internal.Tests
Assert.IsTrue(fakeCall.IsDisposed);
var ex = Assert.ThrowsAsync<RpcException>(async () => await moveNextTask);
+ Assert.AreEqual(expectedStatusCode, ex.Status.StatusCode);
Assert.AreEqual(expectedStatusCode, asyncCall.GetStatus().StatusCode);
Assert.AreEqual(0, asyncCall.GetTrailers().Count);
}
-
- internal class FakeNativeCall : INativeCall
- {
- public UnaryResponseClientHandler UnaryResponseClientHandler
- {
- get;
- set;
- }
-
- public ReceivedStatusOnClientHandler ReceivedStatusOnClientHandler
- {
- get;
- set;
- }
-
- public ReceivedMessageHandler ReceivedMessageHandler
- {
- get;
- set;
- }
-
- public ReceivedResponseHeadersHandler ReceivedResponseHeadersHandler
- {
- get;
- set;
- }
-
- public SendCompletionHandler SendCompletionHandler
- {
- get;
- set;
- }
-
- public ReceivedCloseOnServerHandler ReceivedCloseOnServerHandler
- {
- get;
- set;
- }
-
- public bool IsCancelled
- {
- get;
- set;
- }
-
- public bool IsDisposed
- {
- get;
- set;
- }
-
- public void Cancel()
- {
- IsCancelled = true;
- }
-
- public void CancelWithStatus(Status status)
- {
- IsCancelled = true;
- }
-
- public string GetPeer()
- {
- return "PEER";
- }
-
- public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags)
- {
- UnaryResponseClientHandler = callback;
- }
-
- public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags)
- {
- throw new NotImplementedException();
- }
-
- public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray)
- {
- UnaryResponseClientHandler = callback;
- }
-
- public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags)
- {
- ReceivedStatusOnClientHandler = callback;
- }
-
- public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray)
- {
- ReceivedStatusOnClientHandler = callback;
- }
-
- public void StartReceiveMessage(ReceivedMessageHandler callback)
- {
- ReceivedMessageHandler = callback;
- }
-
- public void StartReceiveInitialMetadata(ReceivedResponseHeadersHandler callback)
- {
- ReceivedResponseHeadersHandler = callback;
- }
-
- public void StartSendInitialMetadata(SendCompletionHandler callback, MetadataArraySafeHandle metadataArray)
- {
- SendCompletionHandler = callback;
- }
-
- public void StartSendMessage(SendCompletionHandler callback, byte[] payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata)
- {
- SendCompletionHandler = callback;
- }
-
- public void StartSendCloseFromClient(SendCompletionHandler callback)
- {
- SendCompletionHandler = callback;
- }
-
- public void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata)
- {
- SendCompletionHandler = callback;
- }
-
- public void StartServerSide(ReceivedCloseOnServerHandler callback)
- {
- ReceivedCloseOnServerHandler = callback;
- }
-
- public void Dispose()
- {
- IsDisposed = true;
- }
- }
}
}
diff --git a/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs b/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs
new file mode 100644
index 0000000000..441bf9660b
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs
@@ -0,0 +1,177 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+using Grpc.Core.Internal;
+using NUnit.Framework;
+
+namespace Grpc.Core.Internal.Tests
+{
+ /// <summary>
+ /// For testing purposes.
+ /// </summary>
+ internal class FakeNativeCall : INativeCall
+ {
+ public UnaryResponseClientHandler UnaryResponseClientHandler
+ {
+ get;
+ set;
+ }
+
+ public ReceivedStatusOnClientHandler ReceivedStatusOnClientHandler
+ {
+ get;
+ set;
+ }
+
+ public ReceivedMessageHandler ReceivedMessageHandler
+ {
+ get;
+ set;
+ }
+
+ public ReceivedResponseHeadersHandler ReceivedResponseHeadersHandler
+ {
+ get;
+ set;
+ }
+
+ public SendCompletionHandler SendCompletionHandler
+ {
+ get;
+ set;
+ }
+
+ public ReceivedCloseOnServerHandler ReceivedCloseOnServerHandler
+ {
+ get;
+ set;
+ }
+
+ public bool IsCancelled
+ {
+ get;
+ set;
+ }
+
+ public bool IsDisposed
+ {
+ get;
+ set;
+ }
+
+ public void Cancel()
+ {
+ IsCancelled = true;
+ }
+
+ public void CancelWithStatus(Status status)
+ {
+ IsCancelled = true;
+ }
+
+ public string GetPeer()
+ {
+ return "PEER";
+ }
+
+ public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags)
+ {
+ UnaryResponseClientHandler = callback;
+ }
+
+ public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray)
+ {
+ UnaryResponseClientHandler = callback;
+ }
+
+ public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags)
+ {
+ ReceivedStatusOnClientHandler = callback;
+ }
+
+ public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray)
+ {
+ ReceivedStatusOnClientHandler = callback;
+ }
+
+ public void StartReceiveMessage(ReceivedMessageHandler callback)
+ {
+ ReceivedMessageHandler = callback;
+ }
+
+ public void StartReceiveInitialMetadata(ReceivedResponseHeadersHandler callback)
+ {
+ ReceivedResponseHeadersHandler = callback;
+ }
+
+ public void StartSendInitialMetadata(SendCompletionHandler callback, MetadataArraySafeHandle metadataArray)
+ {
+ SendCompletionHandler = callback;
+ }
+
+ public void StartSendMessage(SendCompletionHandler callback, byte[] payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata)
+ {
+ SendCompletionHandler = callback;
+ }
+
+ public void StartSendCloseFromClient(SendCompletionHandler callback)
+ {
+ SendCompletionHandler = callback;
+ }
+
+ public void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata)
+ {
+ SendCompletionHandler = callback;
+ }
+
+ public void StartServerSide(ReceivedCloseOnServerHandler callback)
+ {
+ ReceivedCloseOnServerHandler = callback;
+ }
+
+ public void Dispose()
+ {
+ IsDisposed = true;
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
index cce480b2c4..efcf4ea7fe 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
@@ -65,6 +65,15 @@ namespace Grpc.Core.Internal
}
/// <summary>
+ /// Only for testing purposes.
+ /// </summary>
+ public void InitializeForTesting(INativeCall call)
+ {
+ server.AddCallReference(this);
+ InitializeInternal(call);
+ }
+
+ /// <summary>
/// Starts a server side call.
/// </summary>
public Task ServerSideCallAsync()