120 lines
3.7 KiB
C#
120 lines
3.7 KiB
C#
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using RpgRoller.Data;
|
|
|
|
namespace RpgRoller.Tests;
|
|
|
|
internal static class ServiceTestSupport
|
|
{
|
|
internal sealed class ServiceHarness : IDisposable
|
|
{
|
|
internal ServiceHarness(GameService service, SqliteDbContextFactory factory, string dbPath)
|
|
{
|
|
Service = service;
|
|
m_Factory = factory;
|
|
DbPath = dbPath;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
m_Factory.Dispose();
|
|
}
|
|
|
|
public RpgRollerDbContext CreateDbContext()
|
|
{
|
|
return m_Factory.CreateDbContext();
|
|
}
|
|
|
|
public GameService Service { get; }
|
|
public string DbPath { get; }
|
|
private readonly SqliteDbContextFactory m_Factory;
|
|
}
|
|
|
|
internal sealed class RehashingPasswordHasher : IPasswordHasher<UserAccount>
|
|
{
|
|
public string HashPassword(UserAccount user, string password)
|
|
{
|
|
HashCalls += 1;
|
|
return $"hash:{HashCalls}:{password}";
|
|
}
|
|
|
|
public PasswordVerificationResult VerifyHashedPassword(UserAccount user, string hashedPassword, string providedPassword)
|
|
{
|
|
return providedPassword == "Password123" ? PasswordVerificationResult.SuccessRehashNeeded : PasswordVerificationResult.Failed;
|
|
}
|
|
|
|
public int HashCalls { get; private set; }
|
|
}
|
|
|
|
private sealed class FixedDiceRoller : IDiceRoller
|
|
{
|
|
public FixedDiceRoller(IEnumerable<int> values)
|
|
{
|
|
m_Values = new(values);
|
|
}
|
|
|
|
public int Roll(int sides)
|
|
{
|
|
var next = m_Values.Count > 0 ? m_Values.Dequeue() : 1;
|
|
return Math.Clamp(next, 1, sides);
|
|
}
|
|
|
|
private readonly Queue<int> m_Values;
|
|
}
|
|
|
|
internal sealed class SqliteDbContextFactory : IDbContextFactory<RpgRollerDbContext>, IDisposable
|
|
{
|
|
public SqliteDbContextFactory(string dbPath)
|
|
{
|
|
m_Options = new DbContextOptionsBuilder<RpgRollerDbContext>().UseSqlite($"Data Source={dbPath}").Options;
|
|
}
|
|
|
|
public RpgRollerDbContext CreateDbContext()
|
|
{
|
|
return new(m_Options);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
private readonly DbContextOptions<RpgRollerDbContext> m_Options;
|
|
}
|
|
|
|
internal static ServiceHarness CreateHarness(params int[] rollValues)
|
|
{
|
|
return CreateHarness(new PasswordHasher<UserAccount>(), rollValues);
|
|
}
|
|
|
|
internal static ServiceHarness CreateHarness(IPasswordHasher<UserAccount> passwordHasher, params int[] rollValues)
|
|
{
|
|
var dbPath = Path.Combine(Path.GetTempPath(), $"rpgroller-servicetests-{Guid.NewGuid():N}.db");
|
|
return CreateHarnessFromPath(dbPath, passwordHasher, rollValues);
|
|
}
|
|
|
|
internal static ServiceHarness CreateHarnessFromPath(string dbPath, params int[] rollValues)
|
|
{
|
|
return CreateHarnessFromPath(dbPath, new PasswordHasher<UserAccount>(), rollValues);
|
|
}
|
|
|
|
internal static ServiceHarness CreateHarnessFromPath(string dbPath, IPasswordHasher<UserAccount> passwordHasher, params int[] rollValues)
|
|
{
|
|
var options = new DbContextOptionsBuilder<RpgRollerDbContext>().UseSqlite($"Data Source={dbPath}").Options;
|
|
|
|
using (var db = new RpgRollerDbContext(options))
|
|
{
|
|
db.Database.EnsureCreated();
|
|
}
|
|
|
|
var factory = new SqliteDbContextFactory(dbPath);
|
|
var service = new GameService(factory, passwordHasher, new FixedDiceRoller(rollValues));
|
|
return new(service, factory, dbPath);
|
|
}
|
|
|
|
internal static T GetValue<T>(ServiceResult<T> result)
|
|
{
|
|
Assert.True(result.Succeeded);
|
|
Assert.NotNull(result.Value);
|
|
return result.Value!;
|
|
}
|
|
} |