using Vanguard.Server.Tickets; namespace Vanguard.Server.Tests; public class GameTicketServiceTests { [Fact] public async Task Ticket_Is_Redeemed_Only_Once() { var time = new FakeTimeProvider(DateTimeOffset.UnixEpoch); var service = NewService(time); var ticket = await service.IssueAsync("p1", "m1", 0); var first = await service.RedeemAsync(ticket.Token); var second = await service.RedeemAsync(ticket.Token); Assert.NotNull(first); Assert.Equal("p1", first!.PlayerId); Assert.Equal("m1", first.MatchId); Assert.Equal(0, first.Seat); Assert.Null(second); } [Fact] public async Task Ticket_Expires_After_Ttl() { var time = new FakeTimeProvider(DateTimeOffset.UnixEpoch); var options = ServerTestData.SmallOptions(); options.TicketTtlSeconds = 60; var service = NewService(time, options); var ticket = await service.IssueAsync("p1", "m1", 1); time.Advance(TimeSpan.FromSeconds(61)); Assert.Null(await service.RedeemAsync(ticket.Token)); } [Fact] public async Task Unknown_Token_Is_Rejected() { var service = NewService(new FakeTimeProvider(DateTimeOffset.UnixEpoch)); Assert.Null(await service.RedeemAsync(null)); Assert.Null(await service.RedeemAsync("")); Assert.Null(await service.RedeemAsync("no-such-ticket")); } private static GameTicketService NewService( FakeTimeProvider time, Vanguard.Server.Configuration.GameOptions? options = null) => new(new InMemoryTicketStore(time), options ?? ServerTestData.SmallOptions(), time); }