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

View File

@ -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;
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
}

View File

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

View File

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

View File

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