Files
csharp/tests/Mock/Server/WebSocketTestAdapter.cs
Adam Friedman c0a42ad884 Custom validation of server certificate for WebSockets (#103)
* Improve SSL customisation for WebSockets

kubernetes-client/csharp#102

* First test for exec-in-pod over WebSockets.

Also, implement basic mock server for testing WebSockets.

kubernetes-client/csharp#102

* Attempt to handle raciness of Watcher tests.

kubernetes-client/csharp#102

* Attempt to handle raciness of ByteBuffer test.

kubernetes-client/csharp#102
2018-03-19 22:03:28 -07:00

99 lines
4.1 KiB
C#

using System;
using System.Net.WebSockets;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace k8s.Tests.Mock.Server
{
/// <summary>
/// Adapter used to capture WebSockets accepted by the test server and provide them to calling test.
/// </summary>
/// <remarks>
/// Each AcceptedXXXConnection property returns an awaitable object that yields a the server-side WebSocket once a connection has been accepted.
///
/// All server-side WebSockets will be closed when <see cref="CompleteTest"/> is called.
/// </remarks>
public class WebSocketTestAdapter
{
/// <summary>
/// Completion source for the <see cref="TestCompleted"/> task.
/// </summary>
readonly TaskCompletionSource<object> _testCompletion = new TaskCompletionSource<object>();
/// <summary>
/// A <see cref="Task"/> that completes when the test is complete (providing <see cref="CompleteTest"/> is called).
/// </summary>
public Task TestCompleted => _testCompletion.Task;
/// <summary>
/// <c>await</c> server-side acceptance of a WebSocket connection for the exec-in-pod (v1) API.
/// </summary>
public ServerSocketAcceptance AcceptedPodExecV1Connection { get; } = new ServerSocketAcceptance();
/// <summary>
/// <c>await</c> server-side acceptance of a WebSocket connection for the pod-port-forward (v1) API.
/// </summary>
public ServerSocketAcceptance AcceptedPodPortForwardV1Connection { get; } = new ServerSocketAcceptance();
/// <summary>
/// Mark the current test as complete, closing all server-side sockets.
/// </summary>
public void CompleteTest() => _testCompletion.SetResult(true);
/// <summary>
/// An object that enables awaiting server-side acceptance of a WebSocket connection.
/// </summary>
/// <remarks>
/// Simply <c>await</c> this object to wait for the server socket to be accepted.
/// </remarks>
public class ServerSocketAcceptance
{
/// <summary>
/// Completion source for the <see cref="ServerSocketAccepted"/> task.
/// </summary>
readonly TaskCompletionSource<WebSocket> _completion = new TaskCompletionSource<WebSocket>();
/// <summary>
/// A <see cref="Task"/> that completes when the server accepts a WebSocket connection (i.e. when <see cref="AcceptServerSocket"/> or <see cref="RejectServerSocket"/> is called).
/// </summary>
public Task<WebSocket> Task => _completion.Task;
/// <summary>
/// Notify the calling test that the server has accepted a WebSocket connection.
/// </summary>
/// <param name="serverSocket">
/// The server-side <see cref="WebSocket"/>.
/// </param>
public void AcceptServerSocket(WebSocket serverSocket)
{
if (serverSocket == null)
throw new ArgumentNullException(nameof(serverSocket));
_completion.SetResult(serverSocket);
}
/// <summary>
/// Notify the calling test that the server has rejected a WebSocket connection.
/// </summary>
/// <param name="reason">
/// An <see cref="Exception"/> representing the reason that the connection was rejected.
/// </param>
public void RejectServerSocket(Exception reason)
{
if (reason == null)
throw new ArgumentNullException(nameof(reason));
_completion.SetException(reason);
}
/// <summary>
/// Get an awaiter for the socket-acceptance task.
/// </summary>
/// <returns>
/// The <see cref="TaskAwaiter{TResult}"/>.
/// </returns>
public TaskAwaiter<WebSocket> GetAwaiter() => Task.GetAwaiter();
}
}
}