Files
PalladiumWallet/tests/PalladiumWallet.Tests/Net/LiveServerTests.cs
T
davide 42e8dfdb63 test: add ServerProbe tool and opt-in live server test
ServerProbe is a read-only conformance/health checker for Electrum
protocol servers (Fulcrum, ElectrumX): handshake/TLS, features and
genesis, header linkage, Merkle proof vs header root, fees, latency.
LiveServerTests runs it from dotnet test when PALLADIUM_TEST_SERVERS is
set. Also ignore .claude/, apk/aab and local.properties.
2026-11-03 09:34:34 +01:00

46 lines
2.0 KiB
C#

using System.Reflection;
namespace PalladiumWallet.Tests.Net;
/// <summary>
/// Opt-in conformance run of the ServerProbe against real Electrum/Fulcrum servers.
/// Does nothing (passes) unless <c>PALLADIUM_TEST_SERVERS</c> is set, so the default
/// <c>dotnet test</c> stays offline and deterministic.
///
/// PALLADIUM_TEST_SERVERS=host1:50002,host2:50002 servers to probe (comma separated)
/// PALLADIUM_TEST_SSL=1 use TLS
/// PALLADIUM_TEST_NET=mainnet|testnet|regtest network (default mainnet)
///
/// Example: PALLADIUM_TEST_SERVERS=1.2.3.4:50002 PALLADIUM_TEST_SSL=1 dotnet test --filter LiveServer
/// </summary>
[Collection("Console")] // the probe writes to Console, which is process-global
public class LiveServerTests
{
[Fact]
public async Task LiveServer_PassesProbe()
{
var servers = Environment.GetEnvironmentVariable("PALLADIUM_TEST_SERVERS");
if (string.IsNullOrWhiteSpace(servers)) return;
var args = new List<string>();
foreach (var s in servers.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
args.AddRange(["--server", s]);
if (Environment.GetEnvironmentVariable("PALLADIUM_TEST_SSL") is "1" or "true") args.Add("--ssl");
if (Environment.GetEnvironmentVariable("PALLADIUM_TEST_NET") is { Length: > 0 } net) args.AddRange(["--net", net]);
// The probe is a top-level-statements exe: call its entry point rather than shelling out.
var entry = Assembly.Load("PalladiumWallet.ServerProbe").EntryPoint
?? throw new InvalidOperationException("ServerProbe has no entry point.");
var original = Console.Out;
var captured = new StringWriter();
Console.SetOut(captured);
int exit;
// The synthesized entry point is a synchronous Main(string[]) → int wrapper.
try { exit = await Task.Run(() => (int)entry.Invoke(null, [args.ToArray()])!); }
finally { Console.SetOut(original); }
Assert.True(exit == 0, captured.ToString());
}
}