WebSocketService tests

This commit is contained in:
Martin Berg Alstad 2023-07-13 13:51:02 +02:00
parent 37b460b515
commit 00d777d985
4 changed files with 174 additions and 7 deletions
BackendTests/Services
pac-man-board-game

@ -1,6 +1,170 @@
using System.Net.WebSockets;
using BackendTests.TestUtils;
using Microsoft.Extensions.Logging;
using NSubstitute;
using pacMan.Game;
using pacMan.Interfaces;
using pacMan.Services;
using pacMan.Utils;
namespace BackendTests.Services; namespace BackendTests.Services;
public class WebSocketServiceTests // TODO: Implement public class WebSocketServiceTests // TODO: Implement
{ {
private IWebSocketService _service = null!;
[SetUp]
public void SetUp()
{
_service = new WebSocketService(Substitute.For<ILogger<WebSocketService>>());
}
#region Send(Websocket, ArraySegment<byte>)
[Test]
public void Send_OpenWebsocket()
{
var segment = "test".ToArraySegment();
using var webSocket = Substitute.For<WebSocket>();
_service.Send(webSocket, segment);
webSocket.ReceivedWithAnyArgs().SendAsync(default, default, default, default);
}
[Test]
public void Send_ClosedWebsocket()
{
var segment = "test".ToArraySegment();
using var webSocket = Substitute.For<WebSocket>();
webSocket.State.Returns(WebSocketState.Closed);
Assert.That(webSocket.State, Is.Not.EqualTo(WebSocketState.Open).Or.EqualTo(WebSocketState.CloseReceived));
webSocket
.WhenForAnyArgs(x => x.SendAsync(default, default, default, default))
.Do(_ => throw new WebSocketException());
Assert.ThrowsAsync<WebSocketException>(async () => await _service.Send(webSocket, segment));
webSocket.Received().SendAsync(segment, WebSocketMessageType.Text, true, CancellationToken.None);
}
#endregion
#region Receive(Websocket, byte[])
[Test]
public void Receive_ExactBuffer()
{
const int bufferSize = 16;
var buffer = new byte[bufferSize];
var segment = "0123456789ABCDEF".ToArraySegment();
var webSocket = Substitute.For<WebSocket>();
webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None)
.Returns(new WebSocketReceiveResult(bufferSize, WebSocketMessageType.Text, true))
.AndDoes(_ => buffer = segment.ToArray());
var result = _service.Receive(webSocket, buffer).Result;
Assert.Multiple(() =>
{
Assert.That(result, Has.Count.EqualTo(bufferSize));
Assert.That(buffer.GetString(buffer.Length), Is.EqualTo(segment.ToArray().GetString(buffer.Length)));
});
}
[Test]
public void Receive_CloseWebsocket()
{
using var webSocket = Substitute.For<WebSocket>();
webSocket.State.Returns(WebSocketState.Closed);
Assert.That(webSocket.State, Is.Not.EqualTo(WebSocketState.Open).Or.EqualTo(WebSocketState.CloseReceived));
webSocket
.WhenForAnyArgs(x => x.ReceiveAsync(default, default))
.Do(_ => throw new WebSocketException());
Assert.ThrowsAsync<WebSocketException>(async () => await _service.Receive(webSocket, new byte[] { }));
webSocket.ReceivedWithAnyArgs().ReceiveAsync(default, CancellationToken.None);
}
#endregion
#region Close(Websocket, WebSocketCloseStatus, string?)
[Test]
public void Close_OpenWebsocket()
{
using var webSocket = Substitute.For<WebSocket>();
webSocket.State.Returns(WebSocketState.Open);
Assert.That(webSocket.State, Is.EqualTo(WebSocketState.Open).Or.EqualTo(WebSocketState.CloseReceived));
_service.Close(webSocket, WebSocketCloseStatus.NormalClosure, null).Wait();
webSocket.ReceivedWithAnyArgs().CloseAsync(default, default, CancellationToken.None);
}
[Test]
public void Close_ClosedWebsocket()
{
using var webSocket = Substitute.For<WebSocket>();
webSocket.State.Returns(WebSocketState.Closed);
Assert.That(webSocket.State, Is.Not.EqualTo(WebSocketState.Open).Or.EqualTo(WebSocketState.CloseReceived));
webSocket
.WhenForAnyArgs(x => x.CloseAsync(default, default, default))
.Do(_ => throw new WebSocketException());
Assert.ThrowsAsync<WebSocketException>(async () =>
await _service.Close(webSocket, WebSocketCloseStatus.NormalClosure, null));
webSocket.ReceivedWithAnyArgs().CloseAsync(default, default, CancellationToken.None);
}
#endregion
#region AddPlayer(IPlayer)
[Test]
public void AddPlayer_ToEmptyGroup()
{
var player = Players.Create("white");
var group = _service.AddPlayer(player);
Assert.Multiple(() =>
{
Assert.That(group.Players, Has.Count.EqualTo(1));
Assert.That(group.RandomPlayer, Is.EqualTo(player));
Assert.That(_service.Games, Has.Count.EqualTo(1));
});
}
[Test]
public void AddPlayer_ToFullGroup()
{
for (int i = 0; i < 4; i++)
{
var player = Players.Create(i.ToString());
_service.AddPlayer(player);
}
var player5 = Players.Create("white");
var group = _service.AddPlayer(player5);
Assert.Multiple(() =>
{
Assert.That(group.Players, Has.Count.EqualTo(1));
Assert.That(group.RandomPlayer, Is.EqualTo(player5));
Assert.That(_service.Games, Has.Count.EqualTo(2));
Assert.That(_service.Games.First(), Has.Count.EqualTo(Rules.MaxPlayers));
});
}
#endregion
} }

@ -6,11 +6,12 @@ namespace pacMan.Interfaces;
public interface IWebSocketService public interface IWebSocketService
{ {
SynchronizedCollection<GameGroup> Games { get; }
int CountConnected { get; }
event Func<ArraySegment<byte>, Task>? Connections; event Func<ArraySegment<byte>, Task>? Connections;
Task Send(WebSocket webSocket, ArraySegment<byte> segment); Task Send(WebSocket webSocket, ArraySegment<byte> segment);
void SendToAll(ArraySegment<byte> segment); void SendToAll(ArraySegment<byte> segment);
Task<WebSocketReceiveResult> Receive(WebSocket webSocket, byte[] buffer); Task<WebSocketReceiveResult> Receive(WebSocket webSocket, byte[] buffer);
Task Close(WebSocket webSocket, WebSocketCloseStatus closeStatus, string? closeStatusDescription); Task Close(WebSocket webSocket, WebSocketCloseStatus closeStatus, string? closeStatusDescription);
int CountConnected();
GameGroup AddPlayer(IPlayer player); GameGroup AddPlayer(IPlayer player);
} }

@ -11,6 +11,7 @@ public class GameGroup : IEnumerable<IPlayer>
public List<IPlayer> Players { get; } = new(); public List<IPlayer> Players { get; } = new();
public IPlayer RandomPlayer => Players[_random.Next(Players.Count)]; public IPlayer RandomPlayer => Players[_random.Next(Players.Count)];
public int Count => Players.Count;
public IEnumerator<IPlayer> GetEnumerator() => Players.GetEnumerator(); public IEnumerator<IPlayer> GetEnumerator() => Players.GetEnumerator();

@ -5,7 +5,7 @@ using pacMan.Utils;
namespace pacMan.Services; namespace pacMan.Services;
public class WebSocketService : IWebSocketService // TODO add tests public class WebSocketService : IWebSocketService
{ {
private readonly ILogger<WebSocketService> _logger; private readonly ILogger<WebSocketService> _logger;
@ -17,7 +17,9 @@ public class WebSocketService : IWebSocketService // TODO add tests
public SynchronizedCollection<GameGroup> Games { get; } = new(); public SynchronizedCollection<GameGroup> Games { get; } = new();
public event Func<ArraySegment<byte>, Task>? Connections; public int CountConnected => Connections?.GetInvocationList().Length ?? 0;
public event Func<ArraySegment<byte>, Task>? Connections; // TODO remove and use GameGroup
public async Task Send(WebSocket webSocket, ArraySegment<byte> segment) public async Task Send(WebSocket webSocket, ArraySegment<byte> segment)
{ {
@ -27,7 +29,7 @@ public class WebSocketService : IWebSocketService // TODO add tests
true, true,
CancellationToken.None); CancellationToken.None);
_logger.Log(LogLevel.Trace, "Message sent to WebSocket"); _logger.Log(LogLevel.Debug, "Message sent to WebSocket");
} }
public void SendToAll(ArraySegment<byte> segment) public void SendToAll(ArraySegment<byte> segment)
@ -50,11 +52,10 @@ public class WebSocketService : IWebSocketService // TODO add tests
closeStatus, closeStatus,
closeStatusDescription, closeStatusDescription,
CancellationToken.None); CancellationToken.None);
_logger.Log(LogLevel.Information, "WebSocket connection closed"); _logger.Log(LogLevel.Information, "WebSocket connection closed");
} }
public int CountConnected() => Connections?.GetInvocationList().Length ?? 0;
public GameGroup AddPlayer(IPlayer player) public GameGroup AddPlayer(IPlayer player)
{ {
var index = 0; var index = 0;