#nullable enable using System.Linq; using System.Reflection; using Content.IntegrationTests.Pair; using Content.Shared.CCVar; using Robust.UnitTesting; namespace Content.IntegrationTests; // The static class exist to avoid breaking changes public static partial class PoolManager { public static readonly ContentPoolManager Instance = new(); public const string TestMap = "Empty"; /// /// Runs a server, or a client until a condition is true /// /// The server or client /// The condition to check /// How many ticks to try before giving up /// How many ticks to wait between checks public static async Task WaitUntil(RobustIntegrationTest.IntegrationInstance instance, Func func, int maxTicks = 600, int tickStep = 1) { await WaitUntil(instance, async () => await Task.FromResult(func()), maxTicks, tickStep); } /// /// Runs a server, or a client until a condition is true /// /// The server or client /// The async condition to check /// How many ticks to try before giving up /// How many ticks to wait between checks public static async Task WaitUntil(RobustIntegrationTest.IntegrationInstance instance, Func> func, int maxTicks = 600, int tickStep = 1) { var ticksAwaited = 0; bool passed; await instance.WaitIdleAsync(); while (!(passed = await func()) && ticksAwaited < maxTicks) { var ticksToRun = tickStep; if (ticksAwaited + tickStep > maxTicks) { ticksToRun = maxTicks - ticksAwaited; } await instance.WaitRunTicks(ticksToRun); ticksAwaited += ticksToRun; } if (!passed) { Assert.Fail($"Condition did not pass after {maxTicks} ticks.\n" + $"Tests ran ({instance.TestsRan.Count}):\n" + $"{string.Join('\n', instance.TestsRan)}"); } Assert.That(passed); } public static async Task GetServerClient( PoolSettings? settings = null, ITestContextLike? testContext = null) { return await Instance.GetPair(settings, testContext); } public static void Startup(params Assembly[] extra) => Instance.Startup(extra); public static void Shutdown() => Instance.Shutdown(); public static string DeathReport() => Instance.DeathReport(); } /// /// Making clients, and servers is slow, this manages a pool of them so tests can reuse them. /// public sealed class ContentPoolManager : PoolManager { public override PairSettings DefaultSettings => new PoolSettings(); protected override string GetDefaultTestName(ITestContextLike testContext) { return testContext.FullName.Replace("Content.IntegrationTests.Tests.", ""); } public override void Startup(params Assembly[] extraAssemblies) { DefaultCvars.AddRange(PoolManager.TestCvars); var shared = extraAssemblies .Append(typeof(Shared.Entry.EntryPoint).Assembly) .Append(typeof(PoolManager).Assembly) .ToArray(); Startup([typeof(Client.Entry.EntryPoint).Assembly], [typeof(Server.Entry.EntryPoint).Assembly], shared); } }