Make SingleInstanceChecker tests to run in serial mode.
ADD
WalletWasabi.Tests/UnitTests/Clients/SerialSingleInstanceCheckerTests.cs
+using NBitcoin;
+using System;
+using System.Threading.Tasks;
+using WalletWasabi.Services;
+using Xunit;
+
+namespace WalletWasabi.Tests.UnitTests.Clients
+{
+ /// <summary>
+ /// The tests in this collection are time-sensitive, therefore this test collection is run in a special way:
+ /// Parallel-capable test collections will be run first (in parallel), followed by parallel-disabled test collections (run sequentially) like this one.
+ /// </summary>
+ /// <seealso href="https://xunit.net/docs/running-tests-in-parallel.html#parallelism-in-test-frameworks"/>
+ [Collection("Serial unit tests collection")]
+ public class SerialSingleInstanceCheckerTests
+ {
+ [Fact]
+ public async Task SingleInstanceTestsAsync()
+ {
+ // Disposal test.
+ using (SingleInstanceChecker sic = new SingleInstanceChecker(Network.Main))
+ {
+ await sic.CheckAsync();
+ }
+
+ // Check different networks.
+ using (SingleInstanceChecker sic = new SingleInstanceChecker(Network.Main))
+ {
+ await sic.CheckAsync();
+ await Assert.ThrowsAsync<InvalidOperationException>(async () => await sic.CheckAsync());
+
+ using SingleInstanceChecker sicMainNet2 = new SingleInstanceChecker(Network.Main);
+ await Assert.ThrowsAsync<InvalidOperationException>(async () => await sicMainNet2.CheckAsync());
+
+ using SingleInstanceChecker sicTestNet = new SingleInstanceChecker(Network.TestNet);
+ await sicTestNet.CheckAsync();
+ await Assert.ThrowsAsync<InvalidOperationException>(async () => await sicTestNet.CheckAsync());
+
+ using SingleInstanceChecker sicRegTest = new SingleInstanceChecker(Network.RegTest);
+ await sicRegTest.CheckAsync();
+ await Assert.ThrowsAsync<InvalidOperationException>(async () => await sicRegTest.CheckAsync());
+ }
+ }
+ }
+}

MODIFY
WalletWasabi.Tests/UnitTests/Clients/WasabiClientTests.cs
WalletWasabi.Tests/UnitTests/Clients/WasabiClientTests.cs
@@ -105,33 +105,5 @@ namespace WalletWasabi.Tests.UnitTests.Clients
int.Parse(WalletWasabi.Helpers.Constants.BackendMajorVersion);
}
-
- [Fact]
- public async Task SingleInstanceTestsAsync()
- {
- // Disposal test.
- using (SingleInstanceChecker sic = new SingleInstanceChecker(Network.Main))
- {
- await sic.CheckAsync();
- }
-
- // Check different networks.
- using (SingleInstanceChecker sic = new SingleInstanceChecker(Network.Main))
- {
- await sic.CheckAsync();
- await Assert.ThrowsAsync<InvalidOperationException>(async () => await sic.CheckAsync());
-
- using SingleInstanceChecker sic2 = new SingleInstanceChecker(Network.Main);
- await Assert.ThrowsAsync<InvalidOperationException>(async () => await sic2.CheckAsync());
-
- using SingleInstanceChecker sicTest = new SingleInstanceChecker(Network.TestNet);
- await sicTest.CheckAsync();
- await Assert.ThrowsAsync<InvalidOperationException>(async () => await sicTest.CheckAsync());
-
- using SingleInstanceChecker sicReg = new SingleInstanceChecker(Network.RegTest);
- await sicReg.CheckAsync();
- await Assert.ThrowsAsync<InvalidOperationException>(async () => await sicReg.CheckAsync());
- }
- }
}
}

MODIFY
WalletWasabi/Services/SingleInstanceChecker.cs
WalletWasabi/Services/SingleInstanceChecker.cs
using NBitcoin;
using Nito.AsyncEx;
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -11,6 +9,7 @@ namespace WalletWasabi.Services
{
public class SingleInstanceChecker : IDisposable
{
+ /// <summary>Unique prefix for global mutex name.</summary>
private const string MutexString = "WalletWasabiSingleInstance";
private bool _disposedValue;
@@ -19,7 +18,7 @@ namespace WalletWasabi.Services
Network = network;
}
- private IDisposable SingleApplicationLockHolder { get; set; }
+ private IDisposable? SingleApplicationLockHolder { get; set; }
private Network Network { get; }
public async Task CheckAsync()
@@ -42,6 +41,16 @@ namespace WalletWasabi.Services
}
}
+ /// <summary>
+ /// <list type="bullet">
+ /// <item>Unmanaged resources needs to be released regardless of the value of the <paramref name="disposing"/> parameter.</item>
+ /// <item>Managed resources needs to be released if the value of <paramref name="disposing"/> is <c>true</c>.</item>
+ /// </list>
+ /// </summary>
+ /// <param name="disposing">
+ /// Indicates whether the method call comes from a <see cref="Dispose()"/> method
+ /// (its value is <c>true</c>) or from a finalizer (its value is <c>false</c>).
+ /// </param>
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
@@ -54,9 +63,15 @@ namespace WalletWasabi.Services
}
}
+ /// <summary>
+ /// Do not change this code.
+ /// </summary>
public void Dispose()
{
- Dispose(disposing: true);
+ // Dispose of unmanaged resources.
+ Dispose(true);
+ // Suppress finalization.
+ GC.SuppressFinalize(this);
}
}
}

Make SingleInstanceChecker tests to run in serial mode.