Files
scadalink-design/lmxproxy/tests/ZB.MOM.WW.LmxProxy.Host.Tests/Sessions/SessionManagerTests.cs
2026-03-21 23:58:17 -04:00

149 lines
5.0 KiB
C#

using System;
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using Xunit;
using ZB.MOM.WW.LmxProxy.Host.Sessions;
namespace ZB.MOM.WW.LmxProxy.Host.Tests.Sessions
{
public class SessionManagerTests
{
[Fact]
public void CreateSession_Returns32CharHexId()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
var id = sm.CreateSession("client1", "key1");
id.Should().HaveLength(32);
id.Should().MatchRegex("^[0-9a-f]{32}$");
}
[Fact]
public void CreateSession_IncrementsCount()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
sm.ActiveSessionCount.Should().Be(0);
sm.CreateSession("c1", "k1");
sm.ActiveSessionCount.Should().Be(1);
sm.CreateSession("c2", "k2");
sm.ActiveSessionCount.Should().Be(2);
}
[Fact]
public void ValidateSession_ReturnsTrueForExistingSession()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
var id = sm.CreateSession("c1", "k1");
sm.ValidateSession(id).Should().BeTrue();
}
[Fact]
public void ValidateSession_ReturnsFalseForUnknownSession()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
sm.ValidateSession("nonexistent").Should().BeFalse();
}
[Fact]
public void ValidateSession_UpdatesLastActivity()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
var id = sm.CreateSession("c1", "k1");
var session = sm.GetSession(id);
var initialActivity = session!.LastActivity;
Thread.Sleep(50); // Small delay to ensure time passes
sm.ValidateSession(id);
session.LastActivity.Should().BeAfter(initialActivity);
}
[Fact]
public void TerminateSession_RemovesSession()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
var id = sm.CreateSession("c1", "k1");
sm.TerminateSession(id).Should().BeTrue();
sm.ActiveSessionCount.Should().Be(0);
sm.ValidateSession(id).Should().BeFalse();
}
[Fact]
public void TerminateSession_ReturnsFalseForUnknownSession()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
sm.TerminateSession("nonexistent").Should().BeFalse();
}
[Fact]
public void GetSession_ReturnsNullForUnknown()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
sm.GetSession("nonexistent").Should().BeNull();
}
[Fact]
public void GetSession_ReturnsCorrectInfo()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
var id = sm.CreateSession("client-abc", "key-xyz");
var session = sm.GetSession(id);
session.Should().NotBeNull();
session!.ClientId.Should().Be("client-abc");
session.ApiKey.Should().Be("key-xyz");
session.SessionId.Should().Be(id);
session.ConnectedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(2));
}
[Fact]
public void GetAllSessions_ReturnsSnapshot()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
sm.CreateSession("c1", "k1");
sm.CreateSession("c2", "k2");
var all = sm.GetAllSessions();
all.Should().HaveCount(2);
}
[Fact]
public async Task ConcurrentAccess_IsThreadSafe()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
var tasks = new Task[100];
for (int i = 0; i < 100; i++)
{
int idx = i;
tasks[i] = Task.Run(() =>
{
var id = sm.CreateSession($"client-{idx}", $"key-{idx}");
sm.ValidateSession(id);
if (idx % 3 == 0) sm.TerminateSession(id);
});
}
await Task.WhenAll(tasks);
// Should have ~67 sessions remaining (100 - ~33 terminated)
sm.ActiveSessionCount.Should().BeInRange(60, 70);
}
[Fact]
public void Dispose_ClearsAllSessions()
{
var sm = new SessionManager(inactivityTimeoutMinutes: 0);
sm.CreateSession("c1", "k1");
sm.CreateSession("c2", "k2");
sm.Dispose();
sm.ActiveSessionCount.Should().Be(0);
}
[Fact]
public void ConnectedSinceUtcTicks_ReturnsCorrectValue()
{
using var sm = new SessionManager(inactivityTimeoutMinutes: 0);
var id = sm.CreateSession("c1", "k1");
var session = sm.GetSession(id);
session!.ConnectedSinceUtcTicks.Should().Be(session.ConnectedAt.Ticks);
}
}
}