From 9a9813bc4b89b58400adbcfdb4eab6a12165f563 Mon Sep 17 00:00:00 2001
From: Jan Tattermusch <jtattermusch@google.com>
Date: Tue, 3 May 2016 12:57:41 -0700
Subject: [PATCH] add more tests

---
 .../Internal/AsyncCallServerTest.cs           | 83 ++++++++++++++++---
 .../Internal/FakeNativeCall.cs                |  8 +-
 2 files changed, 80 insertions(+), 11 deletions(-)

diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
index a1671c97d5..169de5a780 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
@@ -75,7 +75,6 @@ namespace Grpc.Core.Internal.Tests
         {
             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();
@@ -91,7 +90,6 @@ namespace Grpc.Core.Internal.Tests
         {
             var finishedTask = asyncCallServer.ServerSideCallAsync();
             var requestStream = new ServerRequestStream<string, string>(asyncCallServer);
-            var responseStream = new ServerResponseStream<string, string>(asyncCallServer);
 
             fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true);
 
@@ -103,24 +101,89 @@ namespace Grpc.Core.Internal.Tests
             AssertFinished(asyncCallServer, fakeCall, finishedTask);
         }
 
+        [Test]
+        public void ReadCompletionFailureClosesRequestStream()
+        {
+            var finishedTask = asyncCallServer.ServerSideCallAsync();
+            var requestStream = new ServerRequestStream<string, string>(asyncCallServer);
+
+            // if a read completion's success==false, the request stream will silently finish
+            // and we rely on C core cancelling the call.
+            var moveNextTask = requestStream.MoveNext();
+            fakeCall.ReceivedMessageHandler(false, null);
+            Assert.IsFalse(moveNextTask.Result);
+
+            fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true);
+            AssertFinished(asyncCallServer, fakeCall, finishedTask);
+        }
+
+        [Test]
+        public void WriteAfterCancelNotificationFails()
+        {
+            var finishedTask = asyncCallServer.ServerSideCallAsync();
+            var requestStream = new ServerRequestStream<string, string>(asyncCallServer);
+            var responseStream = new ServerResponseStream<string, string>(asyncCallServer);
+
+            fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true);
+
+            // TODO(jtattermusch): should we throw a different exception type instead?
+            Assert.Throws(typeof(InvalidOperationException), () => responseStream.WriteAsync("request1"));
+
+            // Finishing requestStream is needed for dispose to happen.
+            var moveNextTask = requestStream.MoveNext();
+            fakeCall.ReceivedMessageHandler(true, null);
+            Assert.IsFalse(moveNextTask.Result);
+
+            AssertFinished(asyncCallServer, fakeCall, finishedTask);
+        }
+
+        [Test]
+        public void WriteCompletionFailureThrows()
+        {
+            var finishedTask = asyncCallServer.ServerSideCallAsync();
+            var requestStream = new ServerRequestStream<string, string>(asyncCallServer);
+            var responseStream = new ServerResponseStream<string, string>(asyncCallServer);
+
+            var writeTask = responseStream.WriteAsync("request1");
+            fakeCall.SendCompletionHandler(false);
+            // TODO(jtattermusch): should we throw a different exception type instead?
+            Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await writeTask);
 
-        // TODO: read completion failure ...
+            // 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);
 
+            AssertFinished(asyncCallServer, fakeCall, finishedTask);
+        }
 
-        // TODO: write fails...
+        [Test]
+        public void WriteAndWriteStatusCanRunConcurrently()
+        {
+            var finishedTask = asyncCallServer.ServerSideCallAsync();
+            var requestStream = new ServerRequestStream<string, string>(asyncCallServer);
+            var responseStream = new ServerResponseStream<string, string>(asyncCallServer);
 
-        // TODO: write completion fails...
+            var writeTask = responseStream.WriteAsync("request1");
+            var writeStatusTask = asyncCallServer.SendStatusFromServerAsync(Status.DefaultSuccess, new Metadata());
 
-        // TODO: cancellation delivered...
+            fakeCall.SendCompletionHandler(true);
+            fakeCall.SendStatusFromServerHandler(true);
 
-        // TODO: cancel notification in the middle of a read...
+            Assert.DoesNotThrowAsync(async () => await writeTask);
+            Assert.DoesNotThrowAsync(async () => await writeStatusTask);
 
-        // TODO: cancel notification in the middle of a write...
+            // Finishing requestStream is needed for dispose to happen.
+            var moveNextTask = requestStream.MoveNext();
+            fakeCall.ReceivedMessageHandler(true, null);
+            Assert.IsFalse(moveNextTask.Result);
 
-        // TODO: cancellation delivered...
+            fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true);
 
-        // TODO: what does writing status do to reads?
+            AssertFinished(asyncCallServer, fakeCall, finishedTask);
+        }
 
         static void AssertFinished(AsyncCallServer<string, string> asyncCallServer, FakeNativeCall fakeCall, Task finishedTask)
         {
diff --git a/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs b/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs
index 441bf9660b..1bec258ca2 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs
@@ -76,6 +76,12 @@ namespace Grpc.Core.Internal.Tests
             set;
         }
 
+        public SendCompletionHandler SendStatusFromServerHandler
+        {
+            get;
+            set;
+        }
+
         public ReceivedCloseOnServerHandler ReceivedCloseOnServerHandler
         {
             get;
@@ -161,7 +167,7 @@ namespace Grpc.Core.Internal.Tests
 
         public void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata)
         {
-            SendCompletionHandler = callback;
+            SendStatusFromServerHandler = callback;
         }
 
         public void StartServerSide(ReceivedCloseOnServerHandler callback)
-- 
GitLab