feat: session A — config binding via appsettings.json (67 stubs complete)
Add JSON attributes to ServerOptions, four custom JSON converters (NatsDurationJsonConverter, TlsVersionJsonConverter, NatsUrlJsonConverter, StorageSizeJsonConverter), ServerOptionsConfiguration for JSON file/string binding, and 15 tests covering config parsing, duration parsing, and size parsing. Mark 67 opts.go features complete in porting.db.
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
// Copyright 2012-2025 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
namespace ZB.MOM.NatsNet.Server.Tests.Config;
|
||||
|
||||
using ZB.MOM.NatsNet.Server.Config;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
public class ServerOptionsConfigurationTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessConfigString_MinimalJson_SetsPort()
|
||||
{
|
||||
var opts = ServerOptionsConfiguration.ProcessConfigString("""{"port": 4222}""");
|
||||
opts.Port.ShouldBe(4222);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessConfigString_EmptyJson_AppliesDefaults()
|
||||
{
|
||||
var opts = ServerOptionsConfiguration.ProcessConfigString("{}");
|
||||
opts.Port.ShouldBe(ServerConstants.DefaultPort);
|
||||
opts.Host.ShouldBe(ServerConstants.DefaultHost);
|
||||
opts.MaxPayload.ShouldBe(ServerConstants.MaxPayload);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessConfigString_AllBasicFields_Roundtrip()
|
||||
{
|
||||
var json = """
|
||||
{
|
||||
"port": 5222,
|
||||
"host": "127.0.0.1",
|
||||
"server_name": "test-server",
|
||||
"debug": true,
|
||||
"trace": true,
|
||||
"max_connections": 100,
|
||||
"auth_timeout": 2.0
|
||||
}
|
||||
""";
|
||||
var opts = ServerOptionsConfiguration.ProcessConfigString(json);
|
||||
opts.Port.ShouldBe(5222);
|
||||
opts.Host.ShouldBe("127.0.0.1");
|
||||
opts.ServerName.ShouldBe("test-server");
|
||||
opts.Debug.ShouldBeTrue();
|
||||
opts.Trace.ShouldBeTrue();
|
||||
opts.MaxConn.ShouldBe(100);
|
||||
opts.AuthTimeout.ShouldBe(2.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessConfigFile_FileNotFound_Throws()
|
||||
{
|
||||
Should.Throw<FileNotFoundException>(() =>
|
||||
ServerOptionsConfiguration.ProcessConfigFile("/nonexistent/path.json"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessConfigFile_ValidFile_ReturnsOptions()
|
||||
{
|
||||
var tmpFile = Path.GetTempFileName();
|
||||
File.WriteAllText(tmpFile, """{"port": 9090, "server_name": "from-file"}""");
|
||||
try
|
||||
{
|
||||
var opts = ServerOptionsConfiguration.ProcessConfigFile(tmpFile);
|
||||
opts.Port.ShouldBe(9090);
|
||||
opts.ServerName.ShouldBe("from-file");
|
||||
}
|
||||
finally { File.Delete(tmpFile); }
|
||||
}
|
||||
}
|
||||
|
||||
public class NatsDurationJsonConverterTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("2s", 0, 0, 2, 0)]
|
||||
[InlineData("100ms", 0, 0, 0, 100)]
|
||||
[InlineData("1h30m", 1, 30, 0, 0)]
|
||||
public void Parse_ValidDurationStrings_ReturnsCorrectTimeSpan(
|
||||
string input, int hours, int minutes, int seconds, int ms)
|
||||
{
|
||||
var expected = new TimeSpan(0, hours, minutes, seconds, ms);
|
||||
NatsDurationJsonConverter.Parse(input).ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_FiveMinutesTenSeconds_ReturnsCorrectSpan()
|
||||
{
|
||||
var result = NatsDurationJsonConverter.Parse("5m10s");
|
||||
result.ShouldBe(TimeSpan.FromSeconds(310));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_InvalidString_ThrowsFormatException()
|
||||
{
|
||||
Should.Throw<FormatException>(() => NatsDurationJsonConverter.Parse("notaduration"));
|
||||
}
|
||||
}
|
||||
|
||||
public class StorageSizeJsonConverterTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("1GB", 1L * 1024 * 1024 * 1024)]
|
||||
[InlineData("512MB", 512L * 1024 * 1024)]
|
||||
[InlineData("1KB", 1024L)]
|
||||
[InlineData("1024", 1024L)]
|
||||
public void Parse_ValidSizeStrings_ReturnsBytes(string input, long expectedBytes)
|
||||
{
|
||||
StorageSizeJsonConverter.Parse(input).ShouldBe(expectedBytes);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user