Files
natsdotnet/tests/NATS.Server.Core.Tests/SlowConsumerStallGateTests.cs
Joseph Doherty 7fbffffd05 refactor: rename remaining tests to NATS.Server.Core.Tests
- Rename tests/NATS.Server.Tests -> tests/NATS.Server.Core.Tests
- Update solution file, InternalsVisibleTo, and csproj references
- Remove JETSTREAM_INTEGRATION_MATRIX and NATS.NKeys from csproj (moved to JetStream.Tests and Auth.Tests)
- Update all namespaces from NATS.Server.Tests.* to NATS.Server.Core.Tests.*
- Replace private GetFreePort/ReadUntilAsync helpers with TestUtilities calls
- Fix stale namespace in Transport.Tests/NetworkingGoParityTests.cs
2026-03-12 16:14:02 -04:00

154 lines
4.7 KiB
C#

using NATS.Server;
using NATS.Server.Auth;
using Shouldly;
namespace NATS.Server.Core.Tests;
/// <summary>
/// Tests for <see cref="SlowConsumerTracker"/> and <see cref="Account"/> slow-consumer counters.
/// Go reference: server/client.go — handleSlowConsumer, markConnAsSlow.
/// </summary>
public class SlowConsumerStallGateTests
{
// ── SlowConsumerTracker ────────────────────────────────────────────────────
[Fact]
public void RecordSlowConsumer_increments_total_count()
{
var tracker = new SlowConsumerTracker();
tracker.RecordSlowConsumer(ClientKind.Client);
tracker.RecordSlowConsumer(ClientKind.Client);
tracker.RecordSlowConsumer(ClientKind.Router);
tracker.TotalCount.ShouldBe(3L);
}
[Fact]
public void RecordSlowConsumer_increments_per_kind_count()
{
var tracker = new SlowConsumerTracker();
tracker.RecordSlowConsumer(ClientKind.Client);
tracker.RecordSlowConsumer(ClientKind.Client);
tracker.RecordSlowConsumer(ClientKind.Gateway);
tracker.GetCount(ClientKind.Client).ShouldBe(2L);
tracker.GetCount(ClientKind.Gateway).ShouldBe(1L);
}
[Fact]
public void GetCount_returns_zero_for_unrecorded_kind()
{
var tracker = new SlowConsumerTracker();
tracker.GetCount(ClientKind.Leaf).ShouldBe(0L);
}
[Fact]
public void Multiple_kinds_tracked_independently()
{
var tracker = new SlowConsumerTracker();
tracker.RecordSlowConsumer(ClientKind.Client);
tracker.RecordSlowConsumer(ClientKind.Router);
tracker.RecordSlowConsumer(ClientKind.Gateway);
tracker.RecordSlowConsumer(ClientKind.Leaf);
tracker.GetCount(ClientKind.Client).ShouldBe(1L);
tracker.GetCount(ClientKind.Router).ShouldBe(1L);
tracker.GetCount(ClientKind.Gateway).ShouldBe(1L);
tracker.GetCount(ClientKind.Leaf).ShouldBe(1L);
tracker.GetCount(ClientKind.System).ShouldBe(0L);
tracker.TotalCount.ShouldBe(4L);
}
[Fact]
public void OnThresholdExceeded_fires_when_threshold_reached()
{
var tracker = new SlowConsumerTracker(threshold: 3);
ClientKind? firedKind = null;
tracker.OnThresholdExceeded(k => firedKind = k);
tracker.RecordSlowConsumer(ClientKind.Client);
firedKind.ShouldBeNull();
tracker.RecordSlowConsumer(ClientKind.Client);
firedKind.ShouldBeNull();
tracker.RecordSlowConsumer(ClientKind.Router);
firedKind.ShouldBe(ClientKind.Router);
}
[Fact]
public void OnThresholdExceeded_not_fired_below_threshold()
{
var tracker = new SlowConsumerTracker(threshold: 5);
var fired = false;
tracker.OnThresholdExceeded(_ => fired = true);
tracker.RecordSlowConsumer(ClientKind.Client);
tracker.RecordSlowConsumer(ClientKind.Client);
tracker.RecordSlowConsumer(ClientKind.Client);
fired.ShouldBeFalse();
}
[Fact]
public void Reset_clears_all_counters()
{
var tracker = new SlowConsumerTracker();
tracker.RecordSlowConsumer(ClientKind.Client);
tracker.RecordSlowConsumer(ClientKind.Router);
tracker.TotalCount.ShouldBe(2L);
tracker.Reset();
tracker.TotalCount.ShouldBe(0L);
tracker.GetCount(ClientKind.Client).ShouldBe(0L);
tracker.GetCount(ClientKind.Router).ShouldBe(0L);
}
// ── Account slow-consumer counters ────────────────────────────────────────
[Fact]
public void Account_IncrementSlowConsumers_tracks_count()
{
var account = new Account("test-account");
account.SlowConsumerCount.ShouldBe(0L);
account.IncrementSlowConsumers();
account.IncrementSlowConsumers();
account.IncrementSlowConsumers();
account.SlowConsumerCount.ShouldBe(3L);
}
[Fact]
public void Account_ResetSlowConsumerCount_clears()
{
var account = new Account("test-account");
account.IncrementSlowConsumers();
account.IncrementSlowConsumers();
account.SlowConsumerCount.ShouldBe(2L);
account.ResetSlowConsumerCount();
account.SlowConsumerCount.ShouldBe(0L);
}
[Fact]
public void Thread_safety_concurrent_increments()
{
var tracker = new SlowConsumerTracker();
Parallel.For(0, 1000, _ => tracker.RecordSlowConsumer(ClientKind.Client));
tracker.TotalCount.ShouldBe(1000L);
tracker.GetCount(ClientKind.Client).ShouldBe(1000L);
}
}