// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // namespace MUnique.OpenMU.ChatServer.Tests; using Microsoft.Extensions.Logging.Abstractions; using Moq; using MUnique.OpenMU.ChatServer; using MUnique.OpenMU.Interfaces; /// /// Unit tests for the . /// [TestFixture] public class ChatRoomTests { private const string ChatServerHost = ""; /// /// Tests if a new room returns the specified room id, which was given to the constructor. /// [Test] public void RoomId() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); Assert.That(room.RoomId, Is.EqualTo(roomId)); } /// /// Tries to register a client with a different room id. This should fail with an . /// [Test] public void RegisterClientWithDifferentRoomId() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId = room.GetNextClientIndex(); var authenticationInfo = new ChatServerAuthenticationInfo(clientId, roomId - 1, "Bob", ChatServerHost, "123456789"); Assert.Throws(() => room.RegisterClient(authenticationInfo)); } /// /// Tries to register a client with a correct room id. /// [Test] public void RegisterClientWithCorrectRoomId() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId = room.GetNextClientIndex(); var authenticationInfo = new ChatServerAuthenticationInfo(clientId, roomId, "Bob", ChatServerHost, "123456789"); Assert.DoesNotThrow(() => room.RegisterClient(authenticationInfo)); } /// /// Tries to join a null client. This should fail with an . /// [Test] public async ValueTask TryJoinNullClientAsync() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId = room.GetNextClientIndex(); var authenticationInfo = new ChatServerAuthenticationInfo(clientId, roomId, "Bob", ChatServerHost, "123456789"); room.RegisterClient(authenticationInfo); Assert.That(async () => await room.TryJoinAsync(null!), Throws.TypeOf()); } /// /// Tries to join the room with an unauthenticated client. This should fail. /// [Test] public async ValueTask TryJoinWithUnauthenticatedClientAsync() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId = room.GetNextClientIndex(); var authenticationInfo = new ChatServerAuthenticationInfo(clientId, roomId, "Bob", ChatServerHost, "123456789"); room.RegisterClient(authenticationInfo); var chatClient = new Mock(); Assert.That(await room.TryJoinAsync(chatClient.Object).ConfigureAwait(false), Is.False); } /// /// Tries to join the room with a client with a wrong authentication token. This should fail. /// [Test] public async ValueTask TryJoinWithAuthenticatedClientButWrongTokenAsync() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId = room.GetNextClientIndex(); var authenticationInfo = new ChatServerAuthenticationInfo(clientId, roomId, "Bob", ChatServerHost, "123456789"); room.RegisterClient(authenticationInfo); var chatClient = new Mock(); chatClient.Setup(c => c.AuthenticationToken).Returns("987654321"); Assert.That(await room.TryJoinAsync(chatClient.Object).ConfigureAwait(false), Is.False); } /// /// Tries to join the room with an authenticated client. This should be successful. /// [Test] public async ValueTask TryJoinWithAuthenticatedClientAsync() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId = room.GetNextClientIndex(); var authenticationInfo = new ChatServerAuthenticationInfo(clientId, roomId, "Bob", ChatServerHost, "123456789"); room.RegisterClient(authenticationInfo); var chatClient = new Mock(); chatClient.Setup(c => c.AuthenticationToken).Returns(authenticationInfo.AuthenticationToken); Assert.That(await room.TryJoinAsync(chatClient.Object).ConfigureAwait(false), Is.True); } /// /// Tests if is called after a client successfully joined a room. /// [Test] public async ValueTask ChatRoomClientListSentAsync() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId = room.GetNextClientIndex(); var authenticationInfo = new ChatServerAuthenticationInfo(clientId, roomId, "Bob", ChatServerHost, "123456789"); room.RegisterClient(authenticationInfo); var chatClient = new Mock(); chatClient.Setup(c => c.AuthenticationToken).Returns(authenticationInfo.AuthenticationToken); await room.TryJoinAsync(chatClient.Object).ConfigureAwait(false); chatClient.Verify(c => c.SendChatRoomClientListAsync(room.ConnectedClients), Times.Once); } /// /// Tests if returns the successfully authenticated and joined client. /// [Test] public async ValueTask ConnectedClientsAsync() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId = room.GetNextClientIndex(); var authenticationInfo = new ChatServerAuthenticationInfo(clientId, roomId, "Bob", ChatServerHost, "123456789"); room.RegisterClient(authenticationInfo); var chatClient = new Mock(); chatClient.Setup(c => c.AuthenticationToken).Returns(authenticationInfo.AuthenticationToken); await room.TryJoinAsync(chatClient.Object).ConfigureAwait(false); Assert.That(room.ConnectedClients, Has.Count.EqualTo(1)); Assert.That(room.ConnectedClients, Contains.Item(chatClient.Object)); } /// /// Tests if is called as soon as another client joined the room. /// [Test] public async ValueTask SendJoinedMessageAsync() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId0 = room.GetNextClientIndex(); var clientId1 = room.GetNextClientIndex(); var authenticationInfo0 = new ChatServerAuthenticationInfo(clientId0, roomId, "Alice", ChatServerHost, "99999"); var authenticationInfo1 = new ChatServerAuthenticationInfo(clientId1, roomId, "Bob", ChatServerHost, "123456789"); room.RegisterClient(authenticationInfo0); room.RegisterClient(authenticationInfo1); var chatClient0 = new Mock(); chatClient0.SetupAllProperties(); chatClient0.Setup(c => c.AuthenticationToken).Returns(authenticationInfo0.AuthenticationToken); var chatClient1 = new Mock(); chatClient1.SetupAllProperties(); chatClient1.Setup(c => c.AuthenticationToken).Returns(authenticationInfo1.AuthenticationToken); await room.TryJoinAsync(chatClient0.Object).ConfigureAwait(false); await room.TryJoinAsync(chatClient1.Object).ConfigureAwait(false); chatClient0.Verify(c => c.SendChatRoomClientUpdateAsync(clientId1, authenticationInfo1.ClientName, ChatRoomClientUpdateType.Joined), Times.Once); } /// /// Tests if is called as soon as another client left the room. /// [Test] public async ValueTask SendLeftMessageAsync() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId0 = room.GetNextClientIndex(); var clientId1 = room.GetNextClientIndex(); var authenticationInfo0 = new ChatServerAuthenticationInfo(clientId0, roomId, "Alice", ChatServerHost, "99999"); var authenticationInfo1 = new ChatServerAuthenticationInfo(clientId1, roomId, "Bob", ChatServerHost, "123456789"); room.RegisterClient(authenticationInfo0); room.RegisterClient(authenticationInfo1); var chatClient0 = new Mock(); chatClient0.SetupAllProperties(); chatClient0.Setup(c => c.AuthenticationToken).Returns(authenticationInfo0.AuthenticationToken); var chatClient1 = new Mock(); chatClient1.SetupAllProperties(); chatClient1.Setup(c => c.AuthenticationToken).Returns(authenticationInfo1.AuthenticationToken); await room.TryJoinAsync(chatClient0.Object).ConfigureAwait(false); await room.TryJoinAsync(chatClient1.Object).ConfigureAwait(false); await room.LeaveAsync(chatClient0.Object).ConfigureAwait(false); chatClient1.Verify(c => c.SendChatRoomClientUpdateAsync(clientId0, authenticationInfo0.ClientName, ChatRoomClientUpdateType.Left), Times.Once); } /// /// Tests if is called as soon as a message is sent through the room. /// [Test] public async ValueTask SendMessageAsync() { const ushort roomId = 4711; const string chatMessage = "foobar1234567890"; var room = new ChatRoom(roomId, new NullLogger()); var clientId0 = room.GetNextClientIndex(); var clientId1 = room.GetNextClientIndex(); var authenticationInfo0 = new ChatServerAuthenticationInfo(clientId0, roomId, "Alice", ChatServerHost, "99999"); var authenticationInfo1 = new ChatServerAuthenticationInfo(clientId1, roomId, "Bob", ChatServerHost, "123456789"); room.RegisterClient(authenticationInfo0); room.RegisterClient(authenticationInfo1); var chatClient0 = new Mock(); chatClient0.Setup(c => c.AuthenticationToken).Returns(authenticationInfo0.AuthenticationToken); var chatClient1 = new Mock(); chatClient1.Setup(c => c.AuthenticationToken).Returns(authenticationInfo1.AuthenticationToken); await room.TryJoinAsync(chatClient0.Object).ConfigureAwait(false); await room.TryJoinAsync(chatClient1.Object).ConfigureAwait(false); await room.SendMessageAsync(clientId1, chatMessage).ConfigureAwait(false); chatClient0.Verify(c => c.SendMessageAsync(clientId1, chatMessage), Times.Once); chatClient1.Verify(c => c.SendMessageAsync(clientId1, chatMessage), Times.Once); } /// /// Tests if is fired as soon as all connected clients left the room. /// [Test] public async ValueTask RoomClosedEventAsync() { const ushort roomId = 4711; var room = new ChatRoom(roomId, new NullLogger()); var clientId0 = room.GetNextClientIndex(); var clientId1 = room.GetNextClientIndex(); var authenticationInfo0 = new ChatServerAuthenticationInfo(clientId0, roomId, "Alice", ChatServerHost, "99999"); var authenticationInfo1 = new ChatServerAuthenticationInfo(clientId1, roomId, "Bob", ChatServerHost, "123456789"); room.RegisterClient(authenticationInfo0); room.RegisterClient(authenticationInfo1); var chatClient0 = new Mock(); chatClient0.Setup(c => c.AuthenticationToken).Returns(authenticationInfo0.AuthenticationToken); var chatClient1 = new Mock(); chatClient1.Setup(c => c.AuthenticationToken).Returns(authenticationInfo1.AuthenticationToken); var eventCalled = false; room.RoomClosed += (sender, e) => eventCalled = true; await room.TryJoinAsync(chatClient0.Object).ConfigureAwait(false); await room.TryJoinAsync(chatClient1.Object).ConfigureAwait(false); await room.LeaveAsync(chatClient0.Object).ConfigureAwait(false); await room.LeaveAsync(chatClient1.Object).ConfigureAwait(false); Assert.That(eventCalled, Is.True); } }