mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-26 07:29:00 -07:00
83 lines
3.6 KiB
C#
83 lines
3.6 KiB
C#
using System.Text.Json;
|
|
using Microsoft.Data.SqlClient;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using RadicadeServer.API.Notifications;
|
|
using RadicadeServer.DB;
|
|
using RadicadeServer.RecNet.Enums.Messages;
|
|
using RadicadeServer.RecNet.Messages;
|
|
using Xunit;
|
|
|
|
namespace RadicadeServer.Tests;
|
|
|
|
public sealed class SqlServerInviteFactAttribute : FactAttribute
|
|
{
|
|
public SqlServerInviteFactAttribute()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("RADICADE_SQL_TEST_CONNECTION")))
|
|
Skip = "Set RADICADE_SQL_TEST_CONNECTION to a SQL Server with permission to create a scratch database.";
|
|
}
|
|
}
|
|
|
|
[Collection(DbFactoryCollection.Name)]
|
|
public class SqlServerInvitePersistenceTests
|
|
{
|
|
private sealed class Factory(string connection) : IDbContextFactory<RecDBContext>
|
|
{
|
|
public RecDBContext CreateDbContext() => new(TestDbOptions.Create()
|
|
.UseSqlServer(connection, sql => sql.EnableRetryOnFailure(3)).Options);
|
|
}
|
|
|
|
[SqlServerInviteFact]
|
|
public async Task InvitePayloadCommitsWithSqlServerRetriesEnabled()
|
|
{
|
|
// Never write test invitations into the user's database or notify real players.
|
|
var database = "RadicadeInviteTest_" + Guid.NewGuid().ToString("N");
|
|
var connection = new SqlConnectionStringBuilder(
|
|
Environment.GetEnvironmentVariable("RADICADE_SQL_TEST_CONNECTION"));
|
|
connection.InitialCatalog = "master";
|
|
await using var admin = new SqlConnection(connection.ConnectionString);
|
|
await admin.OpenAsync();
|
|
await using (var create = new SqlCommand($"CREATE DATABASE [{database}]", admin))
|
|
await create.ExecuteNonQueryAsync();
|
|
var previous = Notify.DbFactory;
|
|
try
|
|
{
|
|
connection.InitialCatalog = database;
|
|
var factory = new Factory(connection.ConnectionString);
|
|
await using var db = factory.CreateDbContext();
|
|
await db.Database.ExecuteSqlRawAsync("""
|
|
CREATE TABLE [Messages] (
|
|
[Id] bigint IDENTITY PRIMARY KEY,
|
|
[FromPlayerId] bigint NOT NULL, [ToPlayerId] bigint NOT NULL,
|
|
[SentTime] datetime2 NOT NULL, [Type] int NOT NULL,
|
|
[Data] nvarchar(max) NOT NULL, [Details] nvarchar(max) NOT NULL,
|
|
[RoomId] bigint NULL, [PlayerEventId] bigint NULL,
|
|
[IsDismissed] bit NOT NULL);
|
|
""");
|
|
Notify.DbFactory = factory;
|
|
var message = new Message
|
|
{
|
|
FromPlayerId = long.MaxValue - 1, RoomId = 45, Type = MessageType.GameInviteV2
|
|
};
|
|
await Notify.SendMessage(long.MaxValue, message, prepareWithId: stored =>
|
|
stored.Data = JsonSerializer.Serialize(new RoomInviteDetails
|
|
{
|
|
InviteId = stored.Id, Name = "SQL invite test", RoomInstanceId = 123
|
|
}));
|
|
var saved = await db.Messages.AsNoTracking().SingleAsync();
|
|
Assert.True(saved.Id > 0);
|
|
Assert.Equal(saved.Id, JsonSerializer.Deserialize<RoomInviteDetails>(saved.Data)!.InviteId);
|
|
Assert.Equal(123L, RoomInviteDetails.GetInstanceId(saved));
|
|
Assert.Equal(long.MaxValue, saved.ToPlayerId);
|
|
}
|
|
finally
|
|
{
|
|
Notify.DbFactory = previous;
|
|
SqlConnection.ClearAllPools();
|
|
await using var drop = new SqlCommand(
|
|
$"ALTER DATABASE [{database}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [{database}]", admin);
|
|
await drop.ExecuteNonQueryAsync();
|
|
}
|
|
}
|
|
}
|