diff --git a/Remoting.sln b/Remoting.sln
index df83dca..0494eb9 100644
--- a/Remoting.sln
+++ b/Remoting.sln
@@ -19,6 +19,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
LICENSE = LICENSE
NuGet.Config = NuGet.Config
README.md = README.md
+ testEnvironments.json = testEnvironments.json
.github\workflows\windows.yml = .github\workflows\windows.yml
EndProjectSection
EndProject
@@ -32,7 +33,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Menees.Remoting.Tests", "te
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Menees.Remoting.TestHost", "tests\Menees.Remoting.TestHost\Menees.Remoting.TestHost.csproj", "{A454B747-CAAA-4F97-89D7-996381D5E25C}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Menees.Remoting.TestClient", "tests\Menees.Remoting.TestClient\Menees.Remoting.TestClient.csproj", "{A1DEDBCB-2AA9-4288-8427-9EF357BAF663}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Menees.Remoting.TestClient", "tests\Menees.Remoting.TestClient\Menees.Remoting.TestClient.csproj", "{A1DEDBCB-2AA9-4288-8427-9EF357BAF663}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index d8fa513..a8f6c4d 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -16,7 +16,8 @@
- net48
+
+
net8.0
$(MeneesTargetNetCoreBase);$(MeneesTargetNetFramework)
@@ -81,7 +82,8 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Menees.Remoting/ClientProxy.cs b/src/Menees.Remoting/ClientProxy.cs
index 0067db2..a0a2fa7 100644
--- a/src/Menees.Remoting/ClientProxy.cs
+++ b/src/Menees.Remoting/ClientProxy.cs
@@ -74,10 +74,7 @@ internal void Initialize(RmiClient client)
throw new InvalidOperationException("Client proxy was not initialized.");
}
- if (targetMethod == null)
- {
- throw new ArgumentNullException(nameof(targetMethod));
- }
+ ArgumentNullException.ThrowIfNull(targetMethod);
// This requires a synchronous call from the client to avoid deadlocks since DispatchProxy.Invoke is synchronous.
object? result = this.client.Invoke(targetMethod, args ?? []);
diff --git a/src/Menees.Remoting/Menees.Remoting.csproj b/src/Menees.Remoting/Menees.Remoting.csproj
index 9b740a9..1752c80 100644
--- a/src/Menees.Remoting/Menees.Remoting.csproj
+++ b/src/Menees.Remoting/Menees.Remoting.csproj
@@ -16,8 +16,8 @@
-
-
+
+
diff --git a/src/Menees.Remoting/MessageClient.cs b/src/Menees.Remoting/MessageClient.cs
index 0b281fa..018043e 100644
--- a/src/Menees.Remoting/MessageClient.cs
+++ b/src/Menees.Remoting/MessageClient.cs
@@ -51,10 +51,7 @@ public MessageClient(
public MessageClient(ClientSettings settings)
: base(settings)
{
- if (settings == null)
- {
- throw new ArgumentNullException(nameof(settings));
- }
+ ArgumentNullException.ThrowIfNull(settings);
this.ConnectTimeout = settings.ConnectTimeout;
this.pipe = new(settings.ServerPath, settings.ServerHost, this, (PipeClientSecurity?)settings.Security);
diff --git a/src/Menees.Remoting/MessageServer.cs b/src/Menees.Remoting/MessageServer.cs
index 77bc6b5..90509f7 100644
--- a/src/Menees.Remoting/MessageServer.cs
+++ b/src/Menees.Remoting/MessageServer.cs
@@ -105,10 +105,7 @@ public MessageServer(Func> requestHandler, ServerSettings settin
public MessageServer(Func> requestHandler, ServerSettings settings)
: base(settings)
{
- if (settings == null)
- {
- throw new ArgumentNullException(nameof(settings));
- }
+ ArgumentNullException.ThrowIfNull(settings);
this.requestHandler = requestHandler ?? throw new ArgumentNullException(nameof(requestHandler));
diff --git a/src/Menees.Remoting/Node.cs b/src/Menees.Remoting/Node.cs
index 03f8b15..0a00189 100644
--- a/src/Menees.Remoting/Node.cs
+++ b/src/Menees.Remoting/Node.cs
@@ -117,6 +117,7 @@ protected virtual void Dispose(bool disposing)
#region Private Types
private sealed class ScopedLogger : ILogger
+ where TScope : notnull
{
#region Private Data Members
@@ -137,7 +138,9 @@ public ScopedLogger(ILogger logger, TScope scope)
#region Public Methods
- public IDisposable BeginScope(TState state) => this.logger.BeginScope(state);
+ public IDisposable? BeginScope(TState state)
+ where TState : notnull
+ => this.logger.BeginScope(state);
public bool IsEnabled(LogLevel logLevel) => this.logger.IsEnabled(logLevel);
@@ -150,7 +153,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except
// call context wrapped around one or more local ILogger.Log calls with no intervening Task.Runs or awaits.
// To avoid having to do BeginScope around all our Log calls, it's easier to make this wrapper class that does it.
// https://stackoverflow.com/questions/63851259/since-iloggert-is-a-singleton-how-different-threads-can-use-beginscope-with#comment128022925_63852241
- using IDisposable logScope = this.BeginScope(this.scope);
+ using IDisposable? logScope = this.BeginScope(this.scope);
this.logger.Log(logLevel, eventId, state, exception, formatter);
}
diff --git a/src/Menees.Remoting/RmiClient.cs b/src/Menees.Remoting/RmiClient.cs
index f29d976..740dc5b 100644
--- a/src/Menees.Remoting/RmiClient.cs
+++ b/src/Menees.Remoting/RmiClient.cs
@@ -51,10 +51,7 @@ public RmiClient(
public RmiClient(ClientSettings settings)
: base(settings)
{
- if (settings == null)
- {
- throw new ArgumentNullException(nameof(settings));
- }
+ ArgumentNullException.ThrowIfNull(settings);
this.ConnectTimeout = settings.ConnectTimeout;
this.pipe = new(settings.ServerPath, settings.ServerHost, this, (PipeClientSecurity?)settings.Security);
diff --git a/src/Menees.Remoting/RmiServer.cs b/src/Menees.Remoting/RmiServer.cs
index ca99eac..26cd291 100644
--- a/src/Menees.Remoting/RmiServer.cs
+++ b/src/Menees.Remoting/RmiServer.cs
@@ -63,10 +63,7 @@ public RmiServer(
public RmiServer(TServiceInterface serviceInstance, ServerSettings settings)
: base(settings)
{
- if (settings == null)
- {
- throw new ArgumentNullException(nameof(settings));
- }
+ ArgumentNullException.ThrowIfNull(settings);
this.serviceInstance = serviceInstance ?? throw new ArgumentNullException(nameof(serviceInstance));
diff --git a/src/Menees.Remoting/ServerHost.cs b/src/Menees.Remoting/ServerHost.cs
index 5383b3b..4b44ad7 100644
--- a/src/Menees.Remoting/ServerHost.cs
+++ b/src/Menees.Remoting/ServerHost.cs
@@ -94,10 +94,7 @@ public void Dispose()
/// If has started already.
public void Add(IServer server)
{
- if (server == null)
- {
- throw new ArgumentNullException(nameof(server));
- }
+ ArgumentNullException.ThrowIfNull(server);
this.EnsureReady();
@@ -209,10 +206,7 @@ private void Dispose(bool disposing)
private void EnsureReady([CallerMemberName] string? callerMemberName = null)
{
- if (this.isDisposed)
- {
- throw new ObjectDisposedException(nameof(ServerHost));
- }
+ ObjectDisposedException.ThrowIf(this.isDisposed, this);
if (this.isExiting)
{
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index aa7e7a1..ada3dfa 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -14,13 +14,11 @@
-
-
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
\ No newline at end of file
diff --git a/tests/Menees.Remoting.TestHost/Menees.Remoting.TestHost.csproj b/tests/Menees.Remoting.TestHost/Menees.Remoting.TestHost.csproj
index 3046401..f1604f3 100644
--- a/tests/Menees.Remoting.TestHost/Menees.Remoting.TestHost.csproj
+++ b/tests/Menees.Remoting.TestHost/Menees.Remoting.TestHost.csproj
@@ -11,8 +11,8 @@
-
-
-
+
+
+
diff --git a/tests/Menees.Remoting.Tests/BaseTests.cs b/tests/Menees.Remoting.Tests/BaseTests.cs
index e7c53c8..452a77d 100644
--- a/tests/Menees.Remoting.Tests/BaseTests.cs
+++ b/tests/Menees.Remoting.Tests/BaseTests.cs
@@ -11,7 +11,9 @@
#endregion
[TestClass]
+#pragma warning disable MSTEST0016 // Test class should have test method. This is used as a base class with init and cleanup.
public class BaseTests
+#pragma warning restore MSTEST0016 // Test class should have test method
{
#region Private Data Members
@@ -70,10 +72,7 @@ protected static Task TestCrossProcessClientAsync(int clientCount, string server
protected string GenerateServerPath([CallerMemberName] string? callerMemberName = null)
{
- if (callerMemberName == null)
- {
- throw new ArgumentNullException(nameof(callerMemberName));
- }
+ ArgumentNullException.ThrowIfNull(callerMemberName);
string result = $"{this.GetType().FullName}.{callerMemberName}";
return result;
diff --git a/tests/Menees.Remoting.Tests/RmiServerTests.cs b/tests/Menees.Remoting.Tests/RmiServerTests.cs
index 138a3ce..261208a 100644
--- a/tests/Menees.Remoting.Tests/RmiServerTests.cs
+++ b/tests/Menees.Remoting.Tests/RmiServerTests.cs
@@ -66,6 +66,13 @@ public void CloneString()
actual.ShouldBe(expected);
}
+ [TestMethod]
+ public void OneShot()
+ {
+ // Run 1 client with a single server listener.
+ this.TestClient(1, 1, 1);
+ }
+
[TestMethod]
public void SingleServer()
{
@@ -222,7 +229,7 @@ private void TestClient(
// Make sure all the servers have completely exited in case another TestClient
// starts up immediately using the same serverPath. We don't want a new client
- // to race in an grab an old server listener just as its shutting down.
+ // to race in and grab an old server listener just as its shutting down.
((IServerHost)host).Exit();
host.WaitForExit();
}
@@ -230,9 +237,11 @@ private void TestClient(
private void TestClient(int clientCount, string serverPath, ClientSecurity? clientSecurity = null)
{
TimeSpan timeout = Debugger.IsAttached ? Timeout.InfiniteTimeSpan : ClientSettings.DefaultConnectTimeout;
+ ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = Math.Min(clientCount, 8 * Environment.ProcessorCount) };
+ int[] source = [.. Enumerable.Range(1, clientCount)];
Parallel.ForEach(
- Enumerable.Range(1, clientCount),
- new ParallelOptions { MaxDegreeOfParallelism = Math.Min(clientCount, 8 * Environment.ProcessorCount) },
+ source,
+ parallelOptions,
item =>
{
ClientSettings clientSettings = new(serverPath)
@@ -242,6 +251,7 @@ private void TestClient(int clientCount, string serverPath, ClientSecurity? clie
Security = clientSecurity,
};
+ Debug.WriteLine($"Testing client {item}");
using RmiClient client = new(clientSettings);
ITester proxy = client.CreateProxy();
TestProxy(proxy, item, isSingleClient: clientCount == 1);