using ChatBot.Models; using ChatBot.Services; using ChatBot.Tests.TestUtilities; using FluentAssertions; namespace ChatBot.Tests.Services; public class InMemorySessionStorageTests { private readonly InMemorySessionStorage _sessionStorage; public InMemorySessionStorageTests() { _sessionStorage = new InMemorySessionStorage( TestDataBuilder.Mocks.CreateLoggerMock().Object ); } [Fact] public void GetOrCreate_ShouldReturnExistingSession_WhenSessionExists() { // Arrange _sessionStorage.GetOrCreate(12345, "private", "Test Chat"); // Act var result = _sessionStorage.GetOrCreate(12345, "private", "Test Chat"); // Assert result.Should().NotBeNull(); result.ChatId.Should().Be(12345); result.ChatType.Should().Be("private"); } [Fact] public void GetOrCreate_ShouldCreateNewSession_WhenSessionDoesNotExist() { // Act var result = _sessionStorage.GetOrCreate(12345, "group", "Test Group"); // Assert result.Should().NotBeNull(); result.ChatId.Should().Be(12345); result.ChatType.Should().Be("group"); result.ChatTitle.Should().Be("Test Group"); } [Fact] public void GetOrCreate_ShouldUseDefaultValues_WhenParametersNotProvided() { // Act var result = _sessionStorage.GetOrCreate(12345); // Assert result.Should().NotBeNull(); result.ChatId.Should().Be(12345); result.ChatType.Should().Be("private"); result.ChatTitle.Should().BeEmpty(); } [Fact] public void Get_ShouldReturnSession_WhenSessionExists() { // Arrange var session = _sessionStorage.GetOrCreate(12345, "private", "Test Chat"); // Act var result = _sessionStorage.Get(12345); // Assert result.Should().BeSameAs(session); } [Fact] public void Get_ShouldReturnNull_WhenSessionDoesNotExist() { // Act var result = _sessionStorage.Get(99999); // Assert result.Should().BeNull(); } [Fact] public async Task SaveSessionAsync_ShouldUpdateExistingSession() { // Arrange var session = _sessionStorage.GetOrCreate(12345, "private", "Original Title"); session.ChatTitle = "Updated Title"; session.LastUpdatedAt = DateTime.UtcNow; // Act await _sessionStorage.SaveSessionAsync(session); // Assert var savedSession = _sessionStorage.Get(12345); savedSession.Should().NotBeNull(); savedSession!.ChatTitle.Should().Be("Updated Title"); } [Fact] public async Task SaveSessionAsync_ShouldAddNewSession() { // Arrange var session = _sessionStorage.GetOrCreate(12345, "private", "Original Title"); session.ChatTitle = "New Session"; // Act await _sessionStorage.SaveSessionAsync(session); // Assert var savedSession = _sessionStorage.Get(12345); savedSession.Should().NotBeNull(); savedSession!.ChatTitle.Should().Be("New Session"); } [Fact] public void Remove_ShouldReturnTrue_WhenSessionExists() { // Arrange _sessionStorage.GetOrCreate(12345, "private", "Test Chat"); // Act var result = _sessionStorage.Remove(12345); // Assert result.Should().BeTrue(); _sessionStorage.Get(12345).Should().BeNull(); } [Fact] public void Remove_ShouldReturnFalse_WhenSessionDoesNotExist() { // Act var result = _sessionStorage.Remove(99999); // Assert result.Should().BeFalse(); } [Fact] public void GetActiveSessionsCount_ShouldReturnCorrectCount() { // Arrange _sessionStorage.GetOrCreate(12345, "private", "Chat 1"); _sessionStorage.GetOrCreate(67890, "group", "Chat 2"); _sessionStorage.GetOrCreate(11111, "private", "Chat 3"); // Act var count = _sessionStorage.GetActiveSessionsCount(); // Assert count.Should().Be(3); } [Fact] public void GetActiveSessionsCount_ShouldReturnZero_WhenNoSessions() { // Act var count = _sessionStorage.GetActiveSessionsCount(); // Assert count.Should().Be(0); } [Fact] public void CleanupOldSessions_ShouldDeleteOldSessions() { // Arrange var oldSession = _sessionStorage.GetOrCreate(99999, "private", "Old Chat"); // Manually set CreatedAt to 2 days ago using test method oldSession.SetCreatedAtForTesting(DateTime.UtcNow.AddDays(-2)); var recentSession = _sessionStorage.GetOrCreate(88888, "private", "Recent Chat"); // Manually set CreatedAt to 30 minutes ago using test method recentSession.SetCreatedAtForTesting(DateTime.UtcNow.AddMinutes(-30)); // Act _sessionStorage.CleanupOldSessions(1); // Delete sessions older than 1 day // Assert _sessionStorage.Get(99999).Should().BeNull(); // Old session should be deleted _sessionStorage.Get(88888).Should().NotBeNull(); // Recent session should remain } [Fact] public void CleanupOldSessions_ShouldNotDeleteRecentSessions() { // Arrange var recentSession1 = _sessionStorage.GetOrCreate(12345, "private", "Recent 1"); recentSession1.CreatedAt = DateTime.UtcNow.AddHours(-1); var recentSession2 = _sessionStorage.GetOrCreate(67890, "private", "Recent 2"); recentSession2.CreatedAt = DateTime.UtcNow.AddMinutes(-30); // Act var deletedCount = _sessionStorage.CleanupOldSessions(24); // Delete sessions older than 24 hours // Assert deletedCount.Should().Be(0); _sessionStorage.Get(12345).Should().NotBeNull(); _sessionStorage.Get(67890).Should().NotBeNull(); } [Fact] public void CleanupOldSessions_ShouldReturnZero_WhenNoSessions() { // Act var deletedCount = _sessionStorage.CleanupOldSessions(1); // Assert deletedCount.Should().Be(0); } [Fact] public void GetOrCreate_ShouldCreateSessionWithCorrectTimestamp() { // Act var session = _sessionStorage.GetOrCreate(12345, "private", "Test Chat"); // Assert session.CreatedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromMinutes(1)); session.LastUpdatedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromMinutes(1)); } [Fact] public async Task SaveSessionAsync_ShouldUpdateLastUpdatedAt() { // Arrange var session = _sessionStorage.GetOrCreate(12345, "private", "Test Chat"); var originalTime = session.LastUpdatedAt; // Wait a bit to ensure time difference await Task.Delay(10); session.ChatTitle = "Updated Title"; // Act await _sessionStorage.SaveSessionAsync(session); // Assert var savedSession = _sessionStorage.Get(12345); savedSession!.LastUpdatedAt.Should().BeAfter(originalTime); } [Fact] public async Task GetOrCreate_ShouldHandleConcurrentAccess() { // Arrange var tasks = new List>(); // Act - Create sessions concurrently for (int i = 0; i < 100; i++) { var chatId = 1000 + i; tasks.Add( Task.Run(() => _sessionStorage.GetOrCreate(chatId, "private", $"Chat {chatId}")) ); } await Task.WhenAll(tasks); // Assert _sessionStorage.GetActiveSessionsCount().Should().Be(100); // Verify all sessions were created for (int i = 0; i < 100; i++) { var chatId = 1000 + i; var session = _sessionStorage.Get(chatId); session.Should().NotBeNull(); session!.ChatId.Should().Be(chatId); } } [Fact] public void Remove_ShouldDecreaseActiveSessionsCount() { // Arrange _sessionStorage.GetOrCreate(12345, "private", "Chat 1"); _sessionStorage.GetOrCreate(67890, "private", "Chat 2"); _sessionStorage.GetOrCreate(11111, "private", "Chat 3"); // Act _sessionStorage.Remove(67890); // Assert _sessionStorage.GetActiveSessionsCount().Should().Be(2); _sessionStorage.Get(12345).Should().NotBeNull(); _sessionStorage.Get(67890).Should().BeNull(); _sessionStorage.Get(11111).Should().NotBeNull(); } }