114 lines
3.9 KiB
C#
114 lines
3.9 KiB
C#
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.");
|
|
}
|
|
}
|