121 lines
3.8 KiB
C#
121 lines
3.8 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Vanguard.Server.Configuration;
|
|
using Vanguard.Server.Matches;
|
|
using Vanguard.Server.Meta;
|
|
using Vanguard.Server.Storage;
|
|
|
|
namespace Vanguard.Server.Tests;
|
|
|
|
public class MetaProfileServiceTests
|
|
{
|
|
private static readonly DateTimeOffset Start = new(2026, 10, 21, 12, 0, 0, TimeSpan.Zero);
|
|
|
|
[Fact]
|
|
public async Task Forfeit_Records_History_Without_Gold_Or_Xp()
|
|
{
|
|
var factory = new TestFactory();
|
|
await CreateUsersAsync(factory);
|
|
var service = NewService(factory);
|
|
|
|
await service.RecordAsync(new MatchResult(
|
|
"m-forfeit", GameMode.ClassicRanked, "p1", "p2", 0,
|
|
MatchFinishReason.Concede));
|
|
|
|
await using var db = factory.CreateDbContext();
|
|
var rows = await db.MatchHistory.OrderBy(row => row.UserId).ToListAsync();
|
|
|
|
Assert.Equal(2, rows.Count);
|
|
Assert.All(rows, row =>
|
|
{
|
|
Assert.Equal(0, row.Gold);
|
|
Assert.Equal(0, row.Xp);
|
|
Assert.Equal("concede", row.FinishReason);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Normal_Finish_Gives_Gold_Xp_And_Is_Idempotent()
|
|
{
|
|
var factory = new TestFactory();
|
|
await CreateUsersAsync(factory);
|
|
var service = NewService(factory);
|
|
|
|
var result = new MatchResult(
|
|
"m-normal", GameMode.ClassicRanked, "p1", "p2", 0,
|
|
MatchFinishReason.Normal);
|
|
|
|
await service.RecordAsync(result);
|
|
await service.RecordAsync(result);
|
|
|
|
await using var db = factory.CreateDbContext();
|
|
var rows = await db.MatchHistory.OrderBy(row => row.Result).ToListAsync();
|
|
|
|
Assert.Equal(2, rows.Count);
|
|
|
|
var win = Assert.Single(rows, row => row.Result == "win");
|
|
var loss = Assert.Single(rows, row => row.Result == "loss");
|
|
|
|
Assert.Equal(30, win.Gold);
|
|
Assert.Equal(150, win.Xp);
|
|
Assert.Equal(15, loss.Gold);
|
|
Assert.Equal(75, loss.Xp);
|
|
|
|
var winner = await db.Users.SingleAsync(user => user.NormalizedUserName == "P1");
|
|
var loser = await db.Users.SingleAsync(user => user.NormalizedUserName == "P2");
|
|
|
|
Assert.Equal(150, winner.Xp);
|
|
Assert.Equal(75, loser.Xp);
|
|
Assert.True(winner.RankedMmr > 1000);
|
|
Assert.True(loser.RankedMmr < 1000);
|
|
}
|
|
|
|
private static MetaProfileService NewService(TestFactory factory) => new(
|
|
factory,
|
|
new MetaOptions(),
|
|
new FakeTimeProvider(Start),
|
|
NullLogger<MetaProfileService>.Instance);
|
|
|
|
private static async Task CreateUsersAsync(TestFactory factory)
|
|
{
|
|
await using var db = factory.CreateDbContext();
|
|
db.Users.AddRange(
|
|
new UserEntity
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
UserName = "p1",
|
|
NormalizedUserName = "P1",
|
|
PasswordHash = "x",
|
|
CreatedAt = Start,
|
|
RankedMmr = 1000,
|
|
CasualMmr = 1000,
|
|
},
|
|
new UserEntity
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
UserName = "p2",
|
|
NormalizedUserName = "P2",
|
|
PasswordHash = "x",
|
|
CreatedAt = Start,
|
|
RankedMmr = 1000,
|
|
CasualMmr = 1000,
|
|
});
|
|
|
|
await db.SaveChangesAsync();
|
|
}
|
|
|
|
private sealed class TestFactory : IDbContextFactory<MatchDbContext>
|
|
{
|
|
private readonly DbContextOptions<MatchDbContext> _options;
|
|
|
|
public TestFactory()
|
|
{
|
|
_options = new DbContextOptionsBuilder<MatchDbContext>()
|
|
.UseInMemoryDatabase("meta-profile-" + Guid.NewGuid().ToString("N"))
|
|
.Options;
|
|
}
|
|
|
|
public MatchDbContext CreateDbContext() => new(_options);
|
|
}
|
|
}
|