feat: add sort options to /connz (Gap 10.3)
Add ConnzSortOption enum (ConnectionId, Start, BytesTo, BytesFrom, MsgsTo, MsgsFrom, Subscriptions, Pending, Uptime, Idle, LastActivity) and ConnzSorter static class with Parse(string?) and Sort(IEnumerable<ConnInfo>, ConnzSortOption, bool) methods. Add SortBy and SortDescending properties to ConnzFilterOptions and wire them through ConnzFilterOptions.Parse (?sort= and ?desc= query params). Add 10 unit tests in ConnzSortTests covering Parse defaults, known values, unknown string fallback, and sort ordering for key fields. Go reference: server/monitor_sort_opts.go, server/monitor.go Connz().
This commit is contained in:
179
tests/NATS.Server.Tests/Monitoring/ConnzSortTests.cs
Normal file
179
tests/NATS.Server.Tests/Monitoring/ConnzSortTests.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
using NATS.Server.Monitoring;
|
||||
|
||||
namespace NATS.Server.Tests.Monitoring;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for ConnzSortOption enum, ConnzSorter.Parse, and ConnzSorter.Sort.
|
||||
/// All tests exercise the types in isolation — no running server required.
|
||||
/// Go reference: monitor_test.go — TestConnzSortedByCid, TestConnzSortedByBytesTo,
|
||||
/// TestConnzSortedByMsgsFrom, TestConnzSortedByStart, monitor_sort_opts.go.
|
||||
/// </summary>
|
||||
public class ConnzSortTests
|
||||
{
|
||||
// -----------------------------------------------------------------------
|
||||
// Helper — build a ConnInfo with specific field values
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
private static ConnInfo MakeConn(
|
||||
ulong cid = 1,
|
||||
long outBytes = 0,
|
||||
long inBytes = 0,
|
||||
long outMsgs = 0,
|
||||
long inMsgs = 0,
|
||||
uint numSubs = 0,
|
||||
int pending = 0,
|
||||
DateTime connectedAt = default,
|
||||
DateTime lastActivity = default) =>
|
||||
new()
|
||||
{
|
||||
Cid = cid,
|
||||
OutBytes = outBytes,
|
||||
InBytes = inBytes,
|
||||
OutMsgs = outMsgs,
|
||||
InMsgs = inMsgs,
|
||||
NumSubs = numSubs,
|
||||
Pending = pending,
|
||||
Start = connectedAt == default ? DateTime.UtcNow : connectedAt,
|
||||
LastActivity = lastActivity == default ? DateTime.UtcNow : lastActivity,
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// ConnzSorter.Parse tests
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void Parse_ConnectionId_Default()
|
||||
{
|
||||
// Go reference: monitor_sort_opts.go — empty/unknown value defaults to CID sort
|
||||
ConnzSorter.Parse(null).ShouldBe(ConnzSortOption.ConnectionId);
|
||||
ConnzSorter.Parse("").ShouldBe(ConnzSortOption.ConnectionId);
|
||||
ConnzSorter.Parse(" ").ShouldBe(ConnzSortOption.ConnectionId);
|
||||
ConnzSorter.Parse("cid").ShouldBe(ConnzSortOption.ConnectionId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_BytesTo_Parsed()
|
||||
{
|
||||
// Go reference: monitor_sort_opts.go — "bytes_to" => ByBytesTo
|
||||
ConnzSorter.Parse("bytes_to").ShouldBe(ConnzSortOption.BytesTo);
|
||||
ConnzSorter.Parse("BYTES_TO").ShouldBe(ConnzSortOption.BytesTo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_MsgsFrom_Parsed()
|
||||
{
|
||||
// Go reference: monitor_sort_opts.go — "msgs_from" => ByMsgsFrom
|
||||
ConnzSorter.Parse("msgs_from").ShouldBe(ConnzSortOption.MsgsFrom);
|
||||
ConnzSorter.Parse("MSGS_FROM").ShouldBe(ConnzSortOption.MsgsFrom);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_Start_Parsed()
|
||||
{
|
||||
// Go reference: monitor_sort_opts.go — "start" => ByStart
|
||||
ConnzSorter.Parse("start").ShouldBe(ConnzSortOption.Start);
|
||||
ConnzSorter.Parse("START").ShouldBe(ConnzSortOption.Start);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_Unknown_ReturnsDefault()
|
||||
{
|
||||
// Go reference: monitor_sort_opts.go — unrecognised string falls back to CID
|
||||
ConnzSorter.Parse("not_a_sort_key").ShouldBe(ConnzSortOption.ConnectionId);
|
||||
ConnzSorter.Parse("xyz").ShouldBe(ConnzSortOption.ConnectionId);
|
||||
ConnzSorter.Parse("RANDOM").ShouldBe(ConnzSortOption.ConnectionId);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// ConnzSorter.Sort tests
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void Sort_ByConnectionId_Ascending()
|
||||
{
|
||||
// Go reference: monitor_test.go TestConnzSortedByCid — CID ascending is default
|
||||
var conns = new[]
|
||||
{
|
||||
MakeConn(cid: 3),
|
||||
MakeConn(cid: 1),
|
||||
MakeConn(cid: 2),
|
||||
};
|
||||
|
||||
var result = ConnzSorter.Sort(conns, ConnzSortOption.ConnectionId);
|
||||
|
||||
result.Count.ShouldBe(3);
|
||||
result[0].Cid.ShouldBe(1UL);
|
||||
result[1].Cid.ShouldBe(2UL);
|
||||
result[2].Cid.ShouldBe(3UL);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Sort_ByBytesTo_Descending()
|
||||
{
|
||||
// Go reference: monitor_test.go TestConnzSortedByBytesTo — OutBytes descending
|
||||
var conns = new[]
|
||||
{
|
||||
MakeConn(cid: 1, outBytes: 100),
|
||||
MakeConn(cid: 2, outBytes: 300),
|
||||
MakeConn(cid: 3, outBytes: 200),
|
||||
};
|
||||
|
||||
var result = ConnzSorter.Sort(conns, ConnzSortOption.BytesTo);
|
||||
|
||||
result.Count.ShouldBe(3);
|
||||
result[0].OutBytes.ShouldBe(300);
|
||||
result[1].OutBytes.ShouldBe(200);
|
||||
result[2].OutBytes.ShouldBe(100);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Sort_ByStart_Ascending()
|
||||
{
|
||||
// Go reference: monitor_test.go TestConnzSortedByStart — ConnectedAt ascending
|
||||
var t0 = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
var t1 = t0.AddMinutes(1);
|
||||
var t2 = t0.AddMinutes(2);
|
||||
|
||||
var conns = new[]
|
||||
{
|
||||
MakeConn(cid: 1, connectedAt: t2),
|
||||
MakeConn(cid: 2, connectedAt: t0),
|
||||
MakeConn(cid: 3, connectedAt: t1),
|
||||
};
|
||||
|
||||
var result = ConnzSorter.Sort(conns, ConnzSortOption.Start);
|
||||
|
||||
result.Count.ShouldBe(3);
|
||||
result[0].Start.ShouldBe(t0);
|
||||
result[1].Start.ShouldBe(t1);
|
||||
result[2].Start.ShouldBe(t2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Sort_ByMsgsFrom_Descending()
|
||||
{
|
||||
// Go reference: monitor_test.go TestConnzSortedByMsgsFrom — InMsgs descending
|
||||
var conns = new[]
|
||||
{
|
||||
MakeConn(cid: 1, inMsgs: 50),
|
||||
MakeConn(cid: 2, inMsgs: 200),
|
||||
MakeConn(cid: 3, inMsgs: 10),
|
||||
};
|
||||
|
||||
var result = ConnzSorter.Sort(conns, ConnzSortOption.MsgsFrom);
|
||||
|
||||
result.Count.ShouldBe(3);
|
||||
result[0].InMsgs.ShouldBe(200);
|
||||
result[1].InMsgs.ShouldBe(50);
|
||||
result[2].InMsgs.ShouldBe(10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Sort_EmptyList_ReturnsEmpty()
|
||||
{
|
||||
// Sorting an empty input should not throw and should return an empty list.
|
||||
var result = ConnzSorter.Sort([], ConnzSortOption.BytesTo);
|
||||
|
||||
result.ShouldBeEmpty();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user