mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 23:18:56 -07:00
Radicade Public Code
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RadicadeServer.API.Notifications;
|
||||
using RadicadeServer.DB;
|
||||
using RadicadeServer.RecNet.Accounts;
|
||||
using Xunit;
|
||||
|
||||
namespace RadicadeServer.Tests;
|
||||
|
||||
[Collection(DbFactoryCollection.Name)]
|
||||
public class ConnectionRecoveryTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task ReconnectReplaysActiveBanWithoutRoomPresence(bool active)
|
||||
{
|
||||
var options = TestDbOptions.Create()
|
||||
.UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
|
||||
await using var db = new RecDBContext(options);
|
||||
db.Moderation.Add(new RadicadeServer.RecNet.Moderation.ModerationDB
|
||||
{
|
||||
PlayerId = 987654322, IsBan = true, Message = "test ban",
|
||||
ExpireDuration = DateTime.UtcNow.AddHours(active ? 1 : -1)
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
var proxy = new RecordingClient();
|
||||
var clients = System.Reflection.DispatchProxy.Create<IHubCallerClients, CallerClientsProxy>();
|
||||
((CallerClientsProxy)(object)clients).Client = proxy;
|
||||
var previousContext = Notify.Context;
|
||||
var previousFactory = Notify.DbFactory;
|
||||
try
|
||||
{
|
||||
Notify.DbFactory = null!;
|
||||
var hub = new NotifyHub(previousContext, db)
|
||||
{
|
||||
Context = new TestHubContext(987654322), Clients = clients
|
||||
};
|
||||
await hub.OnConnectedAsync();
|
||||
Assert.Equal(active ? 1 : 0, proxy.Messages.Count);
|
||||
if (active)
|
||||
{
|
||||
Assert.Equal("Notification", proxy.Messages[0].Method);
|
||||
// The replayed kick must carry the client enum's NUMBER (22) inside a JSON
|
||||
// string; the name parses and lands on no handler, and a bare number does not
|
||||
// parse at all - both leave a banned player kicked with no ban screen.
|
||||
Assert.Contains("\"Id\":\"22\"", proxy.Messages[0].Json);
|
||||
Assert.DoesNotContain("ModerationKick", proxy.Messages[0].Json);
|
||||
Assert.Contains("test ban", proxy.Messages[0].Json);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock (Notify.ClientsLock) Notify.Clients.RemoveAll(c => c.AccountId == 987654322);
|
||||
Notify.Context = previousContext;
|
||||
Notify.DbFactory = previousFactory;
|
||||
}
|
||||
}
|
||||
|
||||
public class CallerClientsProxy : System.Reflection.DispatchProxy
|
||||
{
|
||||
public IClientProxy Client = null!;
|
||||
protected override object? Invoke(System.Reflection.MethodInfo? method, object?[]? args)
|
||||
=> method?.Name == "get_Caller" ? Client : throw new NotSupportedException();
|
||||
}
|
||||
|
||||
private sealed class RecordingClient : ISingleClientProxy
|
||||
{
|
||||
public Task<T> InvokeCoreAsync<T>(string method, object?[] args, CancellationToken cancellationToken = default)
|
||||
=> throw new NotSupportedException();
|
||||
public List<(string Method, string Json)> Messages { get; } = new();
|
||||
public Task SendCoreAsync(string method, object?[] args, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Messages.Add((method, Assert.IsType<string>(args[0])));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NotificationDisconnectDoesNotChangeGamePresence()
|
||||
{
|
||||
var options = TestDbOptions.Create()
|
||||
.UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
|
||||
await using var db = new RecDBContext(options);
|
||||
var presence = new RealPresence { playerId = 987654321, isOnline = true, roomInstance = 42 };
|
||||
db.Presences.Add(presence);
|
||||
await db.SaveChangesAsync();
|
||||
var hub = new NotifyHub(Notify.Context, db) { Context = new TestHubContext(presence.playerId) };
|
||||
|
||||
await hub.OnDisconnectedAsync(new IOException("Transport interrupted"));
|
||||
|
||||
await db.Entry(presence).ReloadAsync();
|
||||
Assert.Equal(42L, presence.roomInstance);
|
||||
Assert.True(presence.isOnline);
|
||||
}
|
||||
|
||||
private sealed class TestHubContext(long accountId) : HubCallerContext
|
||||
{
|
||||
public override string ConnectionId => "connection-recovery-test";
|
||||
public override string? UserIdentifier => accountId.ToString();
|
||||
public override ClaimsPrincipal User => new(new ClaimsIdentity(
|
||||
[new Claim(ClaimTypes.NameIdentifier, accountId.ToString())], "test"));
|
||||
public override IDictionary<object, object?> Items { get; } = new Dictionary<object, object?>();
|
||||
public override IFeatureCollection Features { get; } = new FeatureCollection();
|
||||
public override CancellationToken ConnectionAborted => CancellationToken.None;
|
||||
public override void Abort() { }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user