blob: 2ae1f6f76edfee440166a58086f9247661b6e2e5 [file] [log] [blame]
#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);
}
}
}