Merge github.com:grpc/grpc into optionalize_client_config

pull/6043/head
Craig Tiller 9 years ago
commit c53ac0b59e
  1. 4
      src/csharp/.nuget/packages.config
  2. 1
      src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
  3. 97
      src/csharp/Grpc.Core.Tests/HalfcloseTest.cs
  4. 6
      src/csharp/Grpc.Core.Tests/PInvokeTest.cs
  5. 14
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  6. 38
      src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
  7. 6
      src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
  8. 1
      src/csharp/tests.json
  9. 4
      tools/run_tests/run_csharp.bat

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit.Runners" version="2.6.4" />
<package id="OpenCover" version="4.6.166" />
<package id="ReportGenerator" version="2.3.2.0" />
<package id="OpenCover" version="4.6.519" />
<package id="ReportGenerator" version="2.4.4.0" />
</packages>

@ -93,6 +93,7 @@
<Compile Include="MetadataTest.cs" />
<Compile Include="PerformanceTest.cs" />
<Compile Include="SanityTest.cs" />
<Compile Include="HalfcloseTest.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

@ -0,0 +1,97 @@
#region Copyright notice and license
// Copyright 2016, 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.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
{
public class HalfcloseTest
{
MockServiceHelper helper;
Server server;
Channel channel;
[SetUp]
public void Init()
{
helper = new MockServiceHelper();
server = helper.GetServer();
server.Start();
channel = helper.GetChannel();
}
[TearDown]
public void Cleanup()
{
channel.ShutdownAsync().Wait();
server.ShutdownAsync().Wait();
}
/// <summary>
/// For client streaming and duplex streaming calls, if server does a full close
/// before we halfclose the request stream, an attempt to halfclose
/// (complete the request stream) shouldn't be treated as an error.
/// </summary>
[Test]
public async Task HalfcloseAfterFullclose_ClientStreamingCall()
{
helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
{
return "PASS";
});
var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall());
// make sure server has fullclosed on us
Assert.AreEqual("PASS", await call.ResponseAsync);
// sending close from client should be still fine because server can finish
// the call anytime and we cannot do anything about it on the client side.
await call.RequestStream.CompleteAsync();
// Second attempt to close from client is not allowed.
Assert.Throws(typeof(InvalidOperationException), async () => await call.RequestStream.CompleteAsync());
}
}
}

@ -74,6 +74,8 @@ namespace Grpc.Core.Tests
/// (~110ns .NET Windows)
/// </summary>
[Test]
[Category("Performance")]
[Ignore("Prevent running on Jenkins")]
public void NativeCallbackBenchmark()
{
OpCompletionDelegate handler = Handler;
@ -95,6 +97,8 @@ namespace Grpc.Core.Tests
/// (~1.1us on .NET Windows)
/// </summary>
[Test]
[Category("Performance")]
[Ignore("Prevent running on Jenkins")]
public void NewNativeCallbackBenchmark()
{
counter = 0;
@ -112,6 +116,8 @@ namespace Grpc.Core.Tests
/// (~46ns .NET Windows)
/// </summary>
[Test]
[Category("Performance")]
[Ignore("Prevent running on Jenkins")]
public void NopPInvokeBenchmark()
{
BenchmarkUtil.RunBenchmark(

@ -258,9 +258,19 @@ namespace Grpc.Core.Internal
lock (myLock)
{
GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
CheckSendingAllowed();
CheckSendingAllowed(allowFinished: true);
call.StartSendCloseFromClient(HandleHalfclosed);
if (!disposed && !finished)
{
call.StartSendCloseFromClient(HandleSendCloseFromClientFinished);
}
else
{
// In case the call has already been finished by the serverside,
// the halfclose has already been done implicitly, so we only
// emit the notification for the completion delegate.
Task.Run(() => HandleSendCloseFromClientFinished(true));
}
halfcloseRequested = true;
sendCompletionDelegate = completionDelegate;

@ -136,7 +136,7 @@ namespace Grpc.Core.Internal
lock (myLock)
{
GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
CheckSendingAllowed();
CheckSendingAllowed(allowFinished: false);
call.StartSendMessage(HandleSendFinished, payload, writeFlags, !initialMetadataSent);
@ -202,14 +202,14 @@ namespace Grpc.Core.Internal
{
}
protected void CheckSendingAllowed()
protected void CheckSendingAllowed(bool allowFinished)
{
GrpcPreconditions.CheckState(started);
CheckNotCancelled();
GrpcPreconditions.CheckState(!disposed);
GrpcPreconditions.CheckState(!disposed || allowFinished);
GrpcPreconditions.CheckState(!halfcloseRequested, "Already halfclosed.");
GrpcPreconditions.CheckState(!finished, "Already finished.");
GrpcPreconditions.CheckState(!finished || allowFinished, "Already finished.");
GrpcPreconditions.CheckState(sendCompletionDelegate == null, "Only one write can be pending at a time");
}
@ -294,9 +294,33 @@ namespace Grpc.Core.Internal
}
/// <summary>
/// Handles halfclose completion.
/// Handles halfclose (send close from client) completion.
/// </summary>
protected void HandleSendCloseFromClientFinished(bool success)
{
AsyncCompletionDelegate<object> origCompletionDelegate = null;
lock (myLock)
{
origCompletionDelegate = sendCompletionDelegate;
sendCompletionDelegate = null;
ReleaseResourcesIfPossible();
}
if (!success)
{
FireCompletion(origCompletionDelegate, null, new InvalidOperationException("Sending close from client has failed."));
}
else
{
FireCompletion(origCompletionDelegate, null, null);
}
}
/// <summary>
/// Handles send status from server completion.
/// </summary>
protected void HandleHalfclosed(bool success)
protected void HandleSendStatusFromServerFinished(bool success)
{
AsyncCompletionDelegate<object> origCompletionDelegate = null;
lock (myLock)
@ -309,7 +333,7 @@ namespace Grpc.Core.Internal
if (!success)
{
FireCompletion(origCompletionDelegate, null, new InvalidOperationException("Halfclose failed"));
FireCompletion(origCompletionDelegate, null, new InvalidOperationException("Error sending status from server."));
}
else
{

@ -113,7 +113,7 @@ namespace Grpc.Core.Internal
GrpcPreconditions.CheckState(!initialMetadataSent, "Response headers can only be sent once per call.");
GrpcPreconditions.CheckState(streamingWritesCounter == 0, "Response headers can only be sent before the first write starts.");
CheckSendingAllowed();
CheckSendingAllowed(allowFinished: false);
GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
@ -137,11 +137,11 @@ namespace Grpc.Core.Internal
lock (myLock)
{
GrpcPreconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
CheckSendingAllowed();
CheckSendingAllowed(allowFinished: false);
using (var metadataArray = MetadataArraySafeHandle.Create(trailers))
{
call.StartSendStatusFromServer(HandleHalfclosed, status, metadataArray, !initialMetadataSent);
call.StartSendStatusFromServer(HandleSendStatusFromServerFinished, status, metadataArray, !initialMetadataSent);
}
halfcloseRequested = true;
readingDone = true;

@ -21,6 +21,7 @@
"Grpc.Core.Tests.CompressionTest",
"Grpc.Core.Tests.ContextPropagationTest",
"Grpc.Core.Tests.GrpcEnvironmentTest",
"Grpc.Core.Tests.HalfcloseTest",
"Grpc.Core.Tests.MarshallingErrorsTest",
"Grpc.Core.Tests.MetadataTest",
"Grpc.Core.Tests.NUnitVersionTest",

@ -10,9 +10,9 @@ if not "%CONFIG%" == "gcov" (
) else (
@rem Run all tests with code coverage
packages\OpenCover.4.6.166\tools\OpenCover.Console.exe -target:"packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe" -targetdir:"." -targetargs:"%*" -filter:"+[Grpc.Core]*" -register:user -output:coverage_results.xml || goto :error
packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -target:"packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe" -targetdir:"." -targetargs:"%*" -filter:"+[Grpc.Core]*" -register:user -output:coverage_results.xml || goto :error
packages\ReportGenerator.2.3.2.0\tools\ReportGenerator.exe -reports:"coverage_results.xml" -targetdir:"..\..\reports\csharp_coverage" -reporttypes:"Html;TextSummary" || goto :error
packages\ReportGenerator.2.4.4.0\tools\ReportGenerator.exe -reports:"coverage_results.xml" -targetdir:"..\..\reports\csharp_coverage" -reporttypes:"Html;TextSummary" || goto :error
@rem Generate the index.html file
echo ^<html^>^<head^>^</head^>^<body^>^<a href='csharp_coverage/index.htm'^>csharp coverage^</a^>^<br/^>^</body^>^</html^> >..\..\reports\index.html

Loading…
Cancel
Save