mirror of https://github.com/grpc/grpc.git
Merge pull request #23858 from jtattermusch/csharp_fix18100
Fix C# server start when not all ports have been bound.pull/23820/head
commit
f154cac6c6
3 changed files with 103 additions and 4 deletions
@ -0,0 +1,90 @@ |
||||
#region Copyright notice and license |
||||
|
||||
// Copyright 2020 The gRPC Authors |
||||
// |
||||
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||
// you may not use this file except in compliance with the License. |
||||
// You may obtain a copy of the License at |
||||
// |
||||
// http://www.apache.org/licenses/LICENSE-2.0 |
||||
// |
||||
// Unless required by applicable law or agreed to in writing, software |
||||
// distributed under the License is distributed on an "AS IS" BASIS, |
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
// See the License for the specific language governing permissions and |
||||
// limitations under the License. |
||||
|
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Threading.Tasks; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using Grpc.Core; |
||||
using Grpc.Core.Internal; |
||||
using Grpc.Core.Utils; |
||||
using NUnit.Framework; |
||||
|
||||
namespace Grpc.Core.Tests |
||||
{ |
||||
public class ServerBindFailedTest |
||||
{ |
||||
Method<string, string> UnimplementedMethod = new Method<string, string>( |
||||
MethodType.Unary, |
||||
"FooService", |
||||
"SomeNonExistentMethod", |
||||
Marshallers.StringMarshaller, |
||||
Marshallers.StringMarshaller); |
||||
|
||||
// https://github.com/grpc/grpc/issues/18100 |
||||
[Test] |
||||
public async Task Issue18100() |
||||
{ |
||||
var server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }); |
||||
|
||||
// this port will successfully bind |
||||
int successfullyBoundPort = server.Ports.Add(new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure)); |
||||
Assert.AreNotEqual(0, successfullyBoundPort); |
||||
|
||||
// use bad ssl server credentials so this port is guaranteed to fail to bind |
||||
Assert.AreEqual(0, server.Ports.Add(new ServerPort("localhost", ServerPort.PickUnused, MakeBadSslServerCredentials()))); |
||||
|
||||
try |
||||
{ |
||||
server.Start(); |
||||
} |
||||
catch (IOException ex) |
||||
{ |
||||
// eat the expected "Failed to bind port" exception. |
||||
Console.Error.WriteLine($"Ignoring expected exception when starting the server: {ex}"); |
||||
} |
||||
|
||||
// Create a channel to the port that has been bound successfully |
||||
var channel = new Channel("localhost", successfullyBoundPort, ChannelCredentials.Insecure); |
||||
|
||||
var callDeadline = DateTime.UtcNow.AddSeconds(5); // set deadline to make sure we fail quickly if the server doesn't respond |
||||
|
||||
// call a method that's not implemented on the server. |
||||
var call = Calls.AsyncUnaryCall(new CallInvocationDetails<string, string>(channel, UnimplementedMethod, new CallOptions(deadline: callDeadline)), "someRequest"); |
||||
try |
||||
{ |
||||
await call; |
||||
Assert.Fail("the call should have failed."); |
||||
} |
||||
catch (RpcException) |
||||
{ |
||||
// We called a nonexistent method. A healthy server should immediately respond with StatusCode.Unimplemented |
||||
Assert.AreEqual(StatusCode.Unimplemented, call.GetStatus().StatusCode); |
||||
} |
||||
|
||||
await channel.ShutdownAsync(); |
||||
await server.ShutdownAsync(); |
||||
} |
||||
|
||||
private static SslServerCredentials MakeBadSslServerCredentials() |
||||
{ |
||||
var serverCert = new[] { new KeyCertificatePair("this is a bad certificate chain", "this is a bad private key") }; |
||||
return new SslServerCredentials(serverCert, "this is a bad root set", forceClientAuth: false); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue