diff options
Diffstat (limited to 'src/csharp/Grpc.Core.Tests')
-rw-r--r-- | src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj | 1 | ||||
-rw-r--r-- | src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs | 7 | ||||
-rw-r--r-- | src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs | 222 | ||||
-rw-r--r-- | src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs | 77 |
4 files changed, 305 insertions, 2 deletions
diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj index ad4e94a695..b571fe9025 100644 --- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj +++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj @@ -65,6 +65,7 @@ </Compile> <Compile Include="ClientBaseTest.cs" /> <Compile Include="ShutdownTest.cs" /> + <Compile Include="Internal\AsyncCallTest.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="ClientServerTest.cs" /> <Compile Include="ServerTest.cs" /> diff --git a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs index 4fdfab5a99..78295cf6d4 100644 --- a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs +++ b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs @@ -53,7 +53,7 @@ namespace Grpc.Core.Tests { var env1 = GrpcEnvironment.AddRef(); var env2 = GrpcEnvironment.AddRef(); - Assert.IsTrue(object.ReferenceEquals(env1, env2)); + Assert.AreSame(env1, env2); GrpcEnvironment.Release(); GrpcEnvironment.Release(); } @@ -61,18 +61,21 @@ namespace Grpc.Core.Tests [Test] public void InitializeAfterShutdown() { + Assert.AreEqual(0, GrpcEnvironment.GetRefCount()); + var env1 = GrpcEnvironment.AddRef(); GrpcEnvironment.Release(); var env2 = GrpcEnvironment.AddRef(); GrpcEnvironment.Release(); - Assert.IsFalse(object.ReferenceEquals(env1, env2)); + Assert.AreNotSame(env1, env2); } [Test] public void ReleaseWithoutAddRef() { + Assert.AreEqual(0, GrpcEnvironment.GetRefCount()); Assert.Throws(typeof(InvalidOperationException), () => GrpcEnvironment.Release()); } diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs new file mode 100644 index 0000000000..685c5f7d6c --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs @@ -0,0 +1,222 @@ +#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.Runtime.InteropServices; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class AsyncCallTest + { + Channel channel; + FakeNativeCall fakeCall; + AsyncCall<string, string> asyncCall; + + [SetUp] + public void Init() + { + channel = new Channel("localhost", Credentials.Insecure); + + fakeCall = new FakeNativeCall(); + + var callDetails = new CallInvocationDetails<string, string>(channel, "someMethod", null, Marshallers.StringMarshaller, Marshallers.StringMarshaller, new CallOptions()); + asyncCall = new AsyncCall<string, string>(callDetails, fakeCall); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + } + + [Test] + public void AsyncUnary_CompletionSuccess() + { + var resultTask = asyncCall.UnaryCallAsync("abc"); + fakeCall.UnaryResponseClientHandler(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata()), new byte[] { 1, 2, 3 }, new Metadata()); + Assert.IsTrue(resultTask.IsCompleted); + Assert.IsTrue(fakeCall.IsDisposed); + Assert.AreEqual(Status.DefaultSuccess, asyncCall.GetStatus()); + } + + [Test] + public void AsyncUnary_CompletionFailure() + { + var resultTask = asyncCall.UnaryCallAsync("abc"); + fakeCall.UnaryResponseClientHandler(false, new ClientSideStatus(new Status(StatusCode.Internal, ""), null), new byte[] { 1, 2, 3 }, new Metadata()); + + Assert.IsTrue(resultTask.IsCompleted); + Assert.IsTrue(fakeCall.IsDisposed); + + Assert.AreEqual(StatusCode.Internal, asyncCall.GetStatus().StatusCode); + Assert.IsNull(asyncCall.GetTrailers()); + var ex = Assert.Throws<RpcException>(() => resultTask.GetAwaiter().GetResult()); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + } + + 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; + } + } + } +}
\ No newline at end of file diff --git a/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs b/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs index 706006702e..a1648f3671 100644 --- a/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs +++ b/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs @@ -32,13 +32,16 @@ #endregion using System; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; + using Grpc.Core; using Grpc.Core.Internal; using Grpc.Core.Utils; + using NUnit.Framework; namespace Grpc.Core.Tests @@ -74,6 +77,80 @@ namespace Grpc.Core.Tests } [Test] + public async Task ResponseHeadersAsync_UnaryCall() + { + helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) => + { + await context.WriteResponseHeadersAsync(headers); + return "PASS"; + }); + + var call = Calls.AsyncUnaryCall(helper.CreateUnaryCall(), ""); + var responseHeaders = await call.ResponseHeadersAsync; + + Assert.AreEqual(headers.Count, responseHeaders.Count); + Assert.AreEqual("ascii-header", responseHeaders[0].Key); + Assert.AreEqual("abcdefg", responseHeaders[0].Value); + + Assert.AreEqual("PASS", await call.ResponseAsync); + } + + [Test] + public async Task ResponseHeadersAsync_ClientStreamingCall() + { + helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) => + { + await context.WriteResponseHeadersAsync(headers); + return "PASS"; + }); + + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); + await call.RequestStream.CompleteAsync(); + var responseHeaders = await call.ResponseHeadersAsync; + + Assert.AreEqual("ascii-header", responseHeaders[0].Key); + Assert.AreEqual("PASS", await call.ResponseAsync); + } + + [Test] + public async Task ResponseHeadersAsync_ServerStreamingCall() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod<string, string>(async (request, responseStream, context) => + { + await context.WriteResponseHeadersAsync(headers); + await responseStream.WriteAsync("PASS"); + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); + var responseHeaders = await call.ResponseHeadersAsync; + + Assert.AreEqual("ascii-header", responseHeaders[0].Key); + CollectionAssert.AreEqual(new[] { "PASS" }, await call.ResponseStream.ToListAsync()); + } + + [Test] + public async Task ResponseHeadersAsync_DuplexStreamingCall() + { + helper.DuplexStreamingHandler = new DuplexStreamingServerMethod<string, string>(async (requestStream, responseStream, context) => + { + await context.WriteResponseHeadersAsync(headers); + while (await requestStream.MoveNext()) + { + await responseStream.WriteAsync(requestStream.Current); + } + }); + + var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); + var responseHeaders = await call.ResponseHeadersAsync; + + var messages = new[] { "PASS" }; + await call.RequestStream.WriteAllAsync(messages); + + Assert.AreEqual("ascii-header", responseHeaders[0].Key); + CollectionAssert.AreEqual(messages, await call.ResponseStream.ToListAsync()); + } + + [Test] public void WriteResponseHeaders_NullNotAllowed() { helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) => |