feature: Self-Service Clinical Testing Sessions
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using StackExchange.Redis;
|
||||
|
||||
[Collection("Integration")]
|
||||
public class SimulationSessionTests : IAsyncLifetime
|
||||
{
|
||||
private readonly ApiFixture _fixture;
|
||||
private ISimulationRunner _runner = null!;
|
||||
private TestSimulationClientFactory _clientFactory = null!;
|
||||
|
||||
public SimulationSessionTests(ApiFixture fixture) => _fixture = fixture;
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
using var scope = _fixture.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
var redis = scope.ServiceProvider.GetRequiredService<IConnectionMultiplexer>();
|
||||
await DbResetHelper.ResetAsync(db);
|
||||
await DataSeeder.SeedThresholdsOnlyAsync(db, redis);
|
||||
|
||||
_runner = _fixture.Services.GetRequiredService<ISimulationRunner>();
|
||||
_clientFactory = _fixture.SimulationClientFactory;
|
||||
_clientFactory.HangOnCreate = false;
|
||||
_clientFactory.FailOnCreate = false;
|
||||
|
||||
foreach (var run in _runner.ListRuns())
|
||||
_runner.Cancel(run.RunId);
|
||||
|
||||
await WaitForAsync(() => !_runner.HasActiveRuns());
|
||||
_runner.ClearRegistry();
|
||||
}
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
_clientFactory.HangOnCreate = false;
|
||||
_clientFactory.FailOnCreate = false;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartSession_StartsAllScenarios()
|
||||
{
|
||||
_clientFactory.HangOnCreate = true;
|
||||
|
||||
var session = await _runner.StartSessionAsync(
|
||||
"session-test-two", 60, "tester", CancellationToken.None);
|
||||
|
||||
session.RunIds.Should().HaveCount(2);
|
||||
_runner.ListRuns().Count(r =>
|
||||
r.Status is SimulationRunStatus.Pending or SimulationRunStatus.Running)
|
||||
.Should().Be(2);
|
||||
|
||||
foreach (var runId in session.RunIds)
|
||||
_runner.Cancel(runId);
|
||||
|
||||
await WaitForAsync(() => !_runner.HasActiveRuns());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartSession_ExceedingConcurrency_StartsNothing()
|
||||
{
|
||||
_clientFactory.HangOnCreate = true;
|
||||
|
||||
var act = () => _runner.StartSessionAsync(
|
||||
"session-test-three", 60, "tester", CancellationToken.None);
|
||||
|
||||
var ex = await act.Should().ThrowAsync<ConflictException>();
|
||||
ex.Which.ErrorCode.Should().Be("SIMULATION_CONCURRENCY_LIMIT");
|
||||
|
||||
_runner.ListRuns().Should().BeEmpty();
|
||||
|
||||
using var scope = _fixture.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
(await db.SimulationRuns.CountAsync()).Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartSession_TagsRunsWithSessionId()
|
||||
{
|
||||
_clientFactory.HangOnCreate = true;
|
||||
|
||||
var session = await _runner.StartSessionAsync(
|
||||
"session-test-one", null, "tester", CancellationToken.None);
|
||||
|
||||
session.SessionId.Should().Be("session-test-one");
|
||||
var run = _runner.GetRun(session.RunIds[0])!;
|
||||
run.SessionId.Should().Be("session-test-one");
|
||||
run.Speed.Should().Be(120); // defaultSpeed from fixture manifest
|
||||
|
||||
using var scope = _fixture.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
var row = await db.SimulationRuns.SingleAsync(r => r.Id == run.RunId);
|
||||
row.SessionId.Should().Be("session-test-one");
|
||||
|
||||
_runner.Cancel(run.RunId);
|
||||
await WaitForAsync(() => !_runner.HasActiveRuns());
|
||||
}
|
||||
|
||||
private static async Task WaitForAsync(Func<bool> condition, TimeSpan? timeout = null)
|
||||
{
|
||||
var deadline = DateTimeOffset.UtcNow + (timeout ?? TimeSpan.FromSeconds(15));
|
||||
while (DateTimeOffset.UtcNow < deadline)
|
||||
{
|
||||
if (condition())
|
||||
return;
|
||||
await Task.Delay(25);
|
||||
}
|
||||
|
||||
throw new TimeoutException("Condition was not met within the timeout.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user