131 lines
4.2 KiB
C#
Raw Normal View History

2019-06-12 21:56:55 +02:00
using Capnp.Rpc;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
2019-06-12 21:56:55 +02:00
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Capnp.Net.Runtime.Tests
{
public class TestBase
{
public static int TcpPort = 49152;
2019-06-12 21:56:55 +02:00
public static int MediumNonDbgTimeout => Debugger.IsAttached ? Timeout.Infinite : 5000;
2019-08-22 20:53:03 +02:00
public static int LargeNonDbgTimeout => Debugger.IsAttached ? Timeout.Infinite : 20000;
2019-06-12 21:56:55 +02:00
public static int ShortTimeout => 500;
protected ILogger Logger { get; set; }
2020-02-22 23:47:56 +01:00
protected TcpRpcClient SetupClient()
{
2020-02-23 18:24:16 +01:00
var client = new TcpRpcClient();
2020-02-22 23:47:56 +01:00
client.AddBuffering();
2020-02-23 18:24:16 +01:00
client.Connect("localhost", TcpPort);
2020-02-22 23:47:56 +01:00
return client;
}
protected TcpRpcServer SetupServer()
{
int attempt = 0;
while (true)
{
try
{
2020-02-22 23:47:56 +01:00
var server = new TcpRpcServer(IPAddress.Any, TcpPort);
server.AddBuffering();
return server;
}
catch (SocketException)
{
// If the TCP listening port is occupied by some other process,
// retry with a different one
if (attempt == 5)
throw;
}
IncrementTcpPort();
++attempt;
}
}
2019-06-12 21:56:55 +02:00
protected (TcpRpcServer, TcpRpcClient) SetupClientServerPair()
{
var server = SetupServer();
var client = SetupClient();
return (server, client);
}
2019-08-24 00:29:42 +02:00
public static void IncrementTcpPort()
{
if (++TcpPort > 49200)
{
TcpPort = 49152;
}
}
2019-06-12 21:56:55 +02:00
[TestInitialize]
public void InitConsoleLogging()
{
2019-07-14 15:28:50 +02:00
Logging.LoggerFactory?.Dispose();
2019-06-12 21:56:55 +02:00
Logging.LoggerFactory = new LoggerFactory().AddConsole((msg, level) => true);
Logger = Logging.CreateLogger<TcpRpcStress>();
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = $"Test Thread {Thread.CurrentThread.ManagedThreadId}";
}
/// <summary>
/// Somewhat ugly helper method which ensures that both Tcp client and server
/// are waiting for data reception from each other. This is a "balanced" state, meaning
/// that nothing will ever happen in the RcpEngines without some other thread requesting
/// anything.
/// </summary>
protected void WaitClientServerIdle(TcpRpcServer server, TcpRpcClient client)
{
var conn = server.Connections[0];
SpinWait.SpinUntil(() => conn.IsWaitingForData && client.IsWaitingForData &&
conn.RecvCount == client.SendCount &&
conn.SendCount == client.RecvCount,
MediumNonDbgTimeout);
}
protected void ExpectPromiseThrows(Task task)
{
async Task ExpectPromiseThrowsAsync(Task t)
{
try
{
await t;
Assert.Fail("Did not throw");
}
catch (InvalidOperationException)
{
// Happens if the call went to the resolution
// (thus, locally). In this case, the original
// exception is routed here.
}
catch (RpcException)
{
// Happens if the call went to the promise
// (thus, remotely). In this case, the original
// exception had to be serialized, so we receive
// the wrapped version.
}
catch (System.Exception exception)
{
Assert.Fail($"Got wrong kind of exception: {exception}");
}
}
Assert.IsTrue(ExpectPromiseThrowsAsync(task).Wait(MediumNonDbgTimeout));
}
}
}