fix(host): resolve Host-005..011 — async startup, HOCON escaping, port-conflict check, dead-config cleanup, migration retry, log-level wiring; Host-002 flagged
This commit is contained in:
87
tests/ScadaLink.Host.Tests/HoconBuilderTests.cs
Normal file
87
tests/ScadaLink.Host.Tests/HoconBuilderTests.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using Akka.Configuration;
|
||||
using ScadaLink.ClusterInfrastructure;
|
||||
using ScadaLink.Host.Actors;
|
||||
|
||||
namespace ScadaLink.Host.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Host-006: the Akka HOCON document must be assembled with every interpolated value
|
||||
/// quoted/escaped, so a hostname, seed-node URI or split-brain strategy containing a
|
||||
/// quote, backslash or whitespace cannot corrupt the document or be silently
|
||||
/// misparsed.
|
||||
/// </summary>
|
||||
public class HoconBuilderTests
|
||||
{
|
||||
private static ClusterOptions DefaultCluster() => new()
|
||||
{
|
||||
SeedNodes = new List<string>
|
||||
{
|
||||
"akka.tcp://scadalink@localhost:8081",
|
||||
"akka.tcp://scadalink@localhost:8082",
|
||||
},
|
||||
SplitBrainResolverStrategy = "keep-oldest",
|
||||
MinNrOfMembers = 1,
|
||||
StableAfter = TimeSpan.FromSeconds(15),
|
||||
HeartbeatInterval = TimeSpan.FromSeconds(2),
|
||||
FailureDetectionThreshold = TimeSpan.FromSeconds(10),
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void BuildHocon_PlainValues_ParsesAndPreservesValues()
|
||||
{
|
||||
var node = new NodeOptions
|
||||
{
|
||||
Role = "Central",
|
||||
NodeHostname = "central-node1",
|
||||
RemotingPort = 8081,
|
||||
};
|
||||
|
||||
var hocon = AkkaHostedService.BuildHocon(
|
||||
node, DefaultCluster(), new[] { "Central" }, 5, 15);
|
||||
|
||||
var config = ConfigurationFactory.ParseString(hocon);
|
||||
Assert.Equal("central-node1", config.GetString("akka.remote.dot-netty.tcp.hostname"));
|
||||
Assert.Equal("keep-oldest", config.GetString("akka.cluster.split-brain-resolver.active-strategy"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildHocon_HostnameWithQuote_DoesNotCorruptDocument()
|
||||
{
|
||||
// A hostname containing a double quote would, with raw interpolation, close
|
||||
// the HOCON string literal early and corrupt every following key.
|
||||
var node = new NodeOptions
|
||||
{
|
||||
Role = "Central",
|
||||
NodeHostname = "evil\"host",
|
||||
RemotingPort = 8081,
|
||||
};
|
||||
|
||||
var hocon = AkkaHostedService.BuildHocon(
|
||||
node, DefaultCluster(), new[] { "Central" }, 5, 15);
|
||||
|
||||
// Must still parse, and the keys after the hostname must remain intact.
|
||||
var config = ConfigurationFactory.ParseString(hocon);
|
||||
Assert.Equal("evil\"host", config.GetString("akka.remote.dot-netty.tcp.hostname"));
|
||||
Assert.Equal(8081, config.GetInt("akka.remote.dot-netty.tcp.port"));
|
||||
Assert.Equal(1, config.GetInt("akka.cluster.min-nr-of-members"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildHocon_StrategyWithWhitespace_RemainsQuoted()
|
||||
{
|
||||
var cluster = DefaultCluster();
|
||||
cluster.SplitBrainResolverStrategy = "keep oldest";
|
||||
var node = new NodeOptions
|
||||
{
|
||||
Role = "Central",
|
||||
NodeHostname = "node1",
|
||||
RemotingPort = 8081,
|
||||
};
|
||||
|
||||
var hocon = AkkaHostedService.BuildHocon(
|
||||
node, cluster, new[] { "Central" }, 5, 15);
|
||||
|
||||
var config = ConfigurationFactory.ParseString(hocon);
|
||||
Assert.Equal("keep oldest", config.GetString("akka.cluster.split-brain-resolver.active-strategy"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user