Allow creating instances of ServerCallContext in tests

pull/15214/head
Jan Tattermusch 7 years ago
parent 198d0f56ce
commit 4ea4727ac5
  1. 58
      src/csharp/Grpc.Core.Testing/TestServerCallContext.cs
  2. 34
      src/csharp/Grpc.Core/ServerCallContext.cs

@ -0,0 +1,58 @@
#region Copyright notice and license
// Copyright 2015 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;
using System.Threading.Tasks;
using Grpc.Core;
namespace Grpc.Core.Testing
{
/// <summary>
/// Creates test doubles for <c>ServerCallContext</c>.
/// </summary>
public static class TestServerCallContext
{
/// <summary>
/// Creates a test double for <c>ServerCallContext</c>. Only for testing.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
public static ServerCallContext Create(string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
string peer, AuthContext authContext, ContextPropagationToken contextPropagationToken,
Func<Metadata, Task> writeHeadersFunc, Func<WriteOptions> writeOptionsGetter, Action<WriteOptions> writeOptionsSetter)
{
return new ServerCallContext(null, method, host, deadline, requestHeaders, cancellationToken,
writeHeadersFunc, new WriteOptionsHolder(writeOptionsGetter, writeOptionsSetter),
() => peer, () => authContext, () => contextPropagationToken);
}
private class WriteOptionsHolder : IHasWriteOptions
{
Func<WriteOptions> writeOptionsGetter;
Action<WriteOptions> writeOptionsSetter;
public WriteOptionsHolder(Func<WriteOptions> writeOptionsGetter, Action<WriteOptions> writeOptionsSetter)
{
this.writeOptionsGetter = writeOptionsGetter;
this.writeOptionsSetter = writeOptionsSetter;
}
public WriteOptions WriteOptions { get => writeOptionsGetter(); set => writeOptionsSetter(value); }
}
}
}

@ -36,14 +36,25 @@ namespace Grpc.Core
private readonly Metadata requestHeaders;
private readonly CancellationToken cancellationToken;
private readonly Metadata responseTrailers = new Metadata();
private readonly Func<Metadata, Task> writeHeadersFunc;
private readonly IHasWriteOptions writeOptionsHolder;
private readonly Lazy<AuthContext> authContext;
private readonly Func<string> testingOnlyPeerGetter;
private readonly Func<AuthContext> testingOnlyAuthContextGetter;
private readonly Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory;
private Status status = Status.DefaultSuccess;
private Func<Metadata, Task> writeHeadersFunc;
private IHasWriteOptions writeOptionsHolder;
private Lazy<AuthContext> authContext;
internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder)
: this(callHandle, method, host, deadline, requestHeaders, cancellationToken, writeHeadersFunc, writeOptionsHolder, null, null, null)
{
}
// Additional constructor params should be used for testing only
internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder,
Func<string> testingOnlyPeerGetter, Func<AuthContext> testingOnlyAuthContextGetter, Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory)
{
this.callHandle = callHandle;
this.method = method;
@ -54,6 +65,9 @@ namespace Grpc.Core
this.writeHeadersFunc = writeHeadersFunc;
this.writeOptionsHolder = writeOptionsHolder;
this.authContext = new Lazy<AuthContext>(GetAuthContextEager);
this.testingOnlyPeerGetter = testingOnlyPeerGetter;
this.testingOnlyAuthContextGetter = testingOnlyAuthContextGetter;
this.testingOnlyContextPropagationTokenFactory = testingOnlyContextPropagationTokenFactory;
}
/// <summary>
@ -73,6 +87,10 @@ namespace Grpc.Core
/// </summary>
public ContextPropagationToken CreatePropagationToken(ContextPropagationOptions options = null)
{
if (testingOnlyContextPropagationTokenFactory != null)
{
return testingOnlyContextPropagationTokenFactory();
}
return new ContextPropagationToken(callHandle, deadline, cancellationToken, options);
}
@ -99,6 +117,10 @@ namespace Grpc.Core
{
get
{
if (testingOnlyPeerGetter != null)
{
return testingOnlyPeerGetter();
}
// Getting the peer lazily is fine as the native call is guaranteed
// not to be disposed before user-supplied server side handler returns.
// Most users won't need to read this field anyway.
@ -182,6 +204,10 @@ namespace Grpc.Core
{
get
{
if (testingOnlyAuthContextGetter != null)
{
return testingOnlyAuthContextGetter();
}
return authContext.Value;
}
}
@ -198,7 +224,7 @@ namespace Grpc.Core
/// <summary>
/// Allows sharing write options between ServerCallContext and other objects.
/// </summary>
public interface IHasWriteOptions
internal interface IHasWriteOptions
{
/// <summary>
/// Gets or sets the write options.

Loading…
Cancel
Save