feat(batch6-task2): implement F1 opts parsing and verify features

This commit is contained in:
Joseph Doherty
2026-02-28 09:29:50 -05:00
parent edc2afbb2f
commit 4c8fb4e344
5 changed files with 1140 additions and 800 deletions

View File

@@ -1,731 +1,79 @@
using Shouldly;
using ZB.MOM.NatsNet.Server;
using ZB.MOM.NatsNet.Server.Internal;
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
public sealed class ConfigReloaderTests
{
[Fact] // T:2748
public void ConfigReloadClusterNoAdvertise_ShouldSucceed()
[Fact] // T:2766
public void ConfigReloadBoolFlags_ShouldSucceed()
{
var goFile = "server/reload_test.go";
var options = new ServerOptions();
var errors = new List<Exception>();
var warnings = new List<Exception>();
goFile.ShouldStartWith("server/");
ServerOptions.ParseCluster(
new Dictionary<string, object?>
{
["no_advertise"] = true,
["connect_backoff"] = true,
},
options,
errors,
warnings);
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadClusterNoAdvertise_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadClusterNoAdvertise".ShouldNotBeNullOrWhiteSpace();
errors.ShouldBeEmpty();
options.Cluster.NoAdvertise.ShouldBeTrue();
options.Cluster.ConnectBackoff.ShouldBeTrue();
options.InConfig.TryGetValue("Cluster.NoAdvertise", out var explicitValue).ShouldBeTrue();
explicitValue.ShouldBeTrue();
}
[Fact] // T:2749
public void ConfigReloadClusterName_ShouldSucceed()
[Fact]
public void ParseCluster_WithUnknownFieldAndStrictMode_ReturnsError()
{
var goFile = "server/reload_test.go";
ServerOptions.NoErrOnUnknownFields(false);
goFile.ShouldStartWith("server/");
var options = new ServerOptions();
var errors = new List<Exception>();
ServerConstants.DefaultPort.ShouldBe(4222);
ServerOptions.ParseCluster(
new Dictionary<string, object?>
{
["unknown_cluster_field"] = true,
},
options,
errors,
warnings: null);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadClusterName_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadClusterName".ShouldNotBeNullOrWhiteSpace();
errors.Count.ShouldBe(1);
errors[0].Message.ShouldContain("unknown field");
}
[Fact] // T:2751
public void ConfigReloadClientAdvertise_ShouldSucceed()
[Fact]
public void ParseCluster_WithUnknownFieldAndRelaxedMode_IgnoresUnknownField()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
ServerOptions.NoErrOnUnknownFields(true);
try
{
var options = new ServerOptions();
var errors = new List<Exception>();
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
ServerOptions.ParseCluster(
new Dictionary<string, object?>
{
["unknown_cluster_field"] = true,
},
options,
errors,
warnings: null);
errors.ShouldBeEmpty();
}
else
finally
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
ServerOptions.NoErrOnUnknownFields(false);
}
"ConfigReloadClientAdvertise_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadClientAdvertise".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2755
public void ConfigReloadClusterWorks_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadClusterWorks_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadClusterWorks".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2757
public void ConfigReloadClusterPermsImport_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadClusterPermsImport_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadClusterPermsImport".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2758
public void ConfigReloadClusterPermsExport_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadClusterPermsExport_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadClusterPermsExport".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2759
public void ConfigReloadClusterPermsOldServer_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadClusterPermsOldServer_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadClusterPermsOldServer".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2760
public void ConfigReloadAccountUsers_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadAccountUsers_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadAccountUsers".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2764
public void ConfigReloadAccountServicesImportExport_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadAccountServicesImportExport_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadAccountServicesImportExport".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2780
public void ConfigReloadAccountMappings_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadAccountMappings_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadAccountMappings".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2782
public void ConfigReloadRouteImportPermissionsWithAccounts_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadRouteImportPermissionsWithAccounts_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadRouteImportPermissionsWithAccounts".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2783
public void ConfigReloadRoutePoolAndPerAccount_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadRoutePoolAndPerAccount_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadRoutePoolAndPerAccount".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2784
public void ConfigReloadRoutePoolAndPerAccountNoPanicIfFirstAdded_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadRoutePoolAndPerAccountNoPanicIfFirstAdded_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadRoutePoolAndPerAccountNoPanicIfFirstAdded".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2786
public void ConfigReloadRoutePoolAndPerAccountWithOlderServer_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadRoutePoolAndPerAccountWithOlderServer_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadRoutePoolAndPerAccountWithOlderServer".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2787
public void ConfigReloadRoutePoolAndPerAccountNoDuplicateSub_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadRoutePoolAndPerAccountNoDuplicateSub_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadRoutePoolAndPerAccountNoDuplicateSub".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2789
public void ConfigReloadRouteCompression_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadRouteCompression_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadRouteCompression".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2790
public void ConfigReloadRouteCompressionS2Auto_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadRouteCompressionS2Auto_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadRouteCompressionS2Auto".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2791
public void ConfigReloadLeafNodeCompression_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadLeafNodeCompression_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadLeafNodeCompression".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2792
public void ConfigReloadLeafNodeCompressionS2Auto_ShouldSucceed()
{
var goFile = "server/reload_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
{
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"ConfigReloadLeafNodeCompressionS2Auto_ShouldSucceed".ShouldContain("Should");
"TestConfigReloadLeafNodeCompressionS2Auto".ShouldNotBeNullOrWhiteSpace();
}
}

View File

@@ -1,123 +1,313 @@
using Shouldly;
using ZB.MOM.NatsNet.Server;
using ZB.MOM.NatsNet.Server.Internal;
using ZB.MOM.NatsNet.Server.Auth;
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
public sealed class ServerOptionsTests
{
[Fact] // T:2552
public void AccountUsersLoadedProperly_ShouldSucceed()
[Fact]
public void DeepCopyURLs_WithEntries_ReturnsIndependentCopy()
{
var goFile = "server/opts_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
var source = new List<Uri>
{
new("nats://127.0.0.1:4222"),
new("nats://127.0.0.1:4223"),
};
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
var copy = ServerOptions.DeepCopyURLs(source);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"AccountUsersLoadedProperly_ShouldSucceed".ShouldContain("Should");
"TestAccountUsersLoadedProperly".ShouldNotBeNullOrWhiteSpace();
copy.ShouldNotBeNull();
copy.Count.ShouldBe(2);
ReferenceEquals(copy, source).ShouldBeFalse();
copy[0].ToString().ShouldBe(source[0].ToString());
copy[1].ToString().ShouldBe(source[1].ToString());
}
[Fact] // T:2561
public void SublistNoCacheConfigOnAccounts_ShouldSucceed()
[Fact]
public void ProcessConfigFile_WithValidFile_ReturnsParsedOptions()
{
var goFile = "server/opts_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
var tempFile = Path.GetTempFileName();
try
{
File.WriteAllText(tempFile, """
{
"host": "127.0.0.1",
"port": 4444,
"system_account": "$SYS"
}
""");
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
var options = ServerOptions.ProcessConfigFile(tempFile);
options.Host.ShouldBe("127.0.0.1");
options.Port.ShouldBe(4444);
options.SystemAccount.ShouldBe("$SYS");
}
else
finally
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
File.Delete(tempFile);
}
"SublistNoCacheConfigOnAccounts_ShouldSucceed".ShouldContain("Should");
"TestSublistNoCacheConfigOnAccounts".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:2585
public void NewServerFromConfigVsLoadConfig_ShouldSucceed()
[Fact]
public void ConfigureSystemAccount_WithSystemAccountString_SetsValue()
{
var goFile = "server/opts_test.go";
goFile.ShouldStartWith("server/");
ServerConstants.DefaultPort.ShouldBe(4222);
ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();
if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||
goFile.Contains("store", StringComparison.OrdinalIgnoreCase))
var options = new ServerOptions();
var config = new Dictionary<string, object?>
{
["system_account"] = "$SYSX",
};
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
var error = ServerOptions.ConfigureSystemAccount(options, config);
JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);
}
else
{
ServerUtilities.ParseSize("123"u8).ShouldBe(123);
ServerUtilities.ParseInt64("456"u8).ShouldBe(456);
}
"NewServerFromConfigVsLoadConfig_ShouldSucceed".ShouldContain("Should");
"TestNewServerFromConfigVsLoadConfig".ShouldNotBeNullOrWhiteSpace();
error.ShouldBeNull();
options.SystemAccount.ShouldBe("$SYSX");
}
[Fact]
public void ConfigureSystemAccount_WithNonString_ReturnsError()
{
var options = new ServerOptions();
var config = new Dictionary<string, object?>
{
["system"] = 123L,
};
var error = ServerOptions.ConfigureSystemAccount(options, config);
error.ShouldNotBeNull();
error.Message.ShouldContain("must be a string");
}
[Fact]
public void SetupUsersAndNKeysDuplicateCheckMap_WithUsersAndNkeys_IncludesAllIdentities()
{
var options = new ServerOptions
{
Users =
[
new User { Username = "alice" },
new User { Username = "bob" },
],
Nkeys =
[
new NkeyUser { Nkey = "UAA" },
new NkeyUser { Nkey = "UBB" },
],
};
var map = ServerOptions.SetupUsersAndNKeysDuplicateCheckMap(options);
map.Count.ShouldBe(4);
map.ShouldContain("alice");
map.ShouldContain("bob");
map.ShouldContain("UAA");
map.ShouldContain("UBB");
}
[Fact]
public void ParseDuration_WithDurationString_ReturnsExpectedDuration()
{
var errors = new List<Exception>();
var warnings = new List<Exception>();
var parsed = ServerOptions.ParseDuration("write_deadline", "5s", errors, warnings);
parsed.ShouldBe(TimeSpan.FromSeconds(5));
errors.ShouldBeEmpty();
warnings.ShouldBeEmpty();
}
[Fact]
public void ParseDuration_WithLegacySeconds_AddsWarning()
{
var errors = new List<Exception>();
var warnings = new List<Exception>();
var parsed = ServerOptions.ParseDuration("auth_timeout", 3L, errors, warnings);
parsed.ShouldBe(TimeSpan.FromSeconds(3));
errors.ShouldBeEmpty();
warnings.Count.ShouldBe(1);
}
[Fact]
public void ParseWriteDeadlinePolicy_WithInvalidValue_ReturnsDefaultAndError()
{
var errors = new List<Exception>();
var policy = ServerOptions.ParseWriteDeadlinePolicy("invalid", errors);
policy.ShouldBe(WriteTimeoutPolicy.Default);
errors.Count.ShouldBe(1);
errors[0].Message.ShouldContain("write_timeout");
}
[Theory]
[InlineData(8222L, "", 8222)]
[InlineData("127.0.0.1:6222", "127.0.0.1", 6222)]
public void ParseListen_WithValidInput_ReturnsHostPort(object input, string expectedHost, int expectedPort)
{
var (host, port) = ServerOptions.ParseListen(input);
host.ShouldBe(expectedHost);
port.ShouldBe(expectedPort);
}
[Fact]
public void ParseCompression_WithMapValue_ParsesModeAndThresholds()
{
var compression = new CompressionOpts();
var error = ServerOptions.ParseCompression(
compression,
CompressionModes.S2Fast,
"compression",
new Dictionary<string, object?>
{
["mode"] = CompressionModes.S2Best,
["rtt_thresholds"] = new List<object?> { "10ms", "25ms" },
});
error.ShouldBeNull();
compression.Mode.ShouldBe(CompressionModes.S2Best);
compression.RttThresholds.Count.ShouldBe(2);
compression.RttThresholds[0].ShouldBe(TimeSpan.FromMilliseconds(10));
compression.RttThresholds[1].ShouldBe(TimeSpan.FromMilliseconds(25));
}
[Fact]
public void ParseURLs_WithDuplicateEntries_DeduplicatesAndWarns()
{
var warnings = new List<Exception>();
var errors = new List<Exception>();
var urls = ServerOptions.ParseURLs(
["nats://127.0.0.1:4222", "nats://127.0.0.1:4222", "nats://127.0.0.1:4223"],
"route",
warnings,
errors);
errors.ShouldBeEmpty();
warnings.Count.ShouldBe(1);
urls.Count.ShouldBe(2);
}
[Fact]
public void ParseCluster_WithBasicConfig_PopulatesClusterAndRoutes()
{
var options = new ServerOptions();
var errors = new List<Exception>();
var warnings = new List<Exception>();
var parseError = ServerOptions.ParseCluster(
new Dictionary<string, object?>
{
["name"] = "core",
["listen"] = "127.0.0.1:6222",
["connect_retries"] = 8L,
["connect_backoff"] = true,
["no_advertise"] = true,
["compression"] = "s2_fast",
["routes"] = new List<object?> { "nats://127.0.0.1:6223" },
},
options,
errors,
warnings);
parseError.ShouldBeNull();
errors.ShouldBeEmpty();
options.Cluster.Name.ShouldBe("core");
options.Cluster.Host.ShouldBe("127.0.0.1");
options.Cluster.Port.ShouldBe(6222);
options.Cluster.ConnectRetries.ShouldBe(8);
options.Cluster.ConnectBackoff.ShouldBeTrue();
options.Cluster.NoAdvertise.ShouldBeTrue();
options.Cluster.Compression.Mode.ShouldBe("s2_fast");
options.Routes.Count.ShouldBe(1);
options.Routes[0].ToString().ShouldBe("nats://127.0.0.1:6223/");
}
[Fact]
public void ParseGateway_WithBasicConfig_PopulatesGateway()
{
var options = new ServerOptions();
var errors = new List<Exception>();
var warnings = new List<Exception>();
var parseError = ServerOptions.ParseGateway(
new Dictionary<string, object?>
{
["name"] = "edge",
["listen"] = "127.0.0.1:7222",
["connect_retries"] = 4L,
["connect_backoff"] = true,
["advertise"] = "gw.local:7222",
["reject_unknown"] = true,
["authorization"] = new Dictionary<string, object?>
{
["user"] = "gwu",
["password"] = "gwp",
["auth_timeout"] = 3L,
},
},
options,
errors,
warnings);
parseError.ShouldBeNull();
errors.ShouldBeEmpty();
options.Gateway.Name.ShouldBe("edge");
options.Gateway.Host.ShouldBe("127.0.0.1");
options.Gateway.Port.ShouldBe(7222);
options.Gateway.ConnectRetries.ShouldBe(4);
options.Gateway.ConnectBackoff.ShouldBeTrue();
options.Gateway.Advertise.ShouldBe("gw.local:7222");
options.Gateway.RejectUnknown.ShouldBeTrue();
options.Gateway.Username.ShouldBe("gwu");
options.Gateway.Password.ShouldBe("gwp");
options.Gateway.AuthTimeout.ShouldBe(3);
}
[Fact] // T:2586
public void WriteDeadlineConfigParsing_ShouldSucceed()
{
var options = new ServerOptions();
var errors = new List<Exception>();
var warnings = new List<Exception>();
ServerOptions.ParseCluster(
new Dictionary<string, object?>
{
["write_deadline"] = "12s",
},
options,
errors,
warnings);
errors.ShouldBeEmpty();
options.Cluster.WriteDeadline.ShouldBe(TimeSpan.FromSeconds(12));
}
[Fact] // T:2587
public void WriteTimeoutConfigParsing_ShouldSucceed()
{
var options = new ServerOptions();
var errors = new List<Exception>();
var warnings = new List<Exception>();
ServerOptions.ParseGateway(
new Dictionary<string, object?>
{
["write_timeout"] = "retry",
},
options,
errors,
warnings);
errors.ShouldBeEmpty();
options.Gateway.WriteTimeout.ShouldBe(WriteTimeoutPolicy.Retry);
}
}