From 81e3b2da884c379eee87be66c7d22f903af49db1 Mon Sep 17 00:00:00 2001 From: wrexbe <81056464+wrexbe@users.noreply.github.com> Date: Sun, 19 Jun 2022 20:22:28 -0700 Subject: [PATCH] Make tests faster (#8737) * Test changes * Make finding the test tile a little smarter --- .github/workflows/build-test-debug.yml | 5 + Content.Client/Clothing/ClothingSystem.cs | 2 +- .../ContentIntegrationTest.cs | 440 ----------- .../ContentIntegrationTestSetup.cs | 15 - Content.IntegrationTests/PoolManager.cs | 707 ++++++++++++++++++ .../PoolManagerTestEventHandler.cs | 15 + .../Tests/AI/BehaviorSetsTest.cs | 7 +- .../Tests/Access/AccessReaderTest.cs | 7 +- .../Tests/Administration/Logs/AddTests.cs | 119 ++- .../Tests/Administration/Logs/FilterTests.cs | 21 +- .../Tests/Administration/Logs/QueryTests.cs | 18 +- .../Tests/Atmos/AlarmThresholdTest.cs | 11 +- .../Tests/Atmos/ConstantsTest.cs | 8 +- .../Tests/Atmos/GasMixtureTest.cs | 18 +- .../Tests/Body/LegTest.cs | 7 +- .../Tests/Body/LungTest.cs | 16 +- .../Tests/Buckle/BuckleTest.cs | 34 +- .../Tests/Chemistry/SolutionSystemTests.cs | 51 +- .../Tests/Chemistry/TryAllReactionsTest.cs | 18 +- .../Tests/ClickableTest.cs | 42 +- .../Tests/Commands/PardonCommand.cs | 8 +- .../Tests/Commands/RejuvenateTest.cs | 7 +- .../Tests/Commands/RestartRoundTest.cs | 26 +- .../Construction/ConstructionActionValid.cs | 20 +- .../Construction/ConstructionPrototypeTest.cs | 20 +- .../Tests/ContainerOcclusionTest.cs | 94 +-- .../Tests/Damageable/DamageSpecifierTest.cs | 2 +- .../Tests/Damageable/DamageableTest.cs | 37 +- .../Tests/DeleteInventoryTest.cs | 6 +- .../DestructibleDamageGroupTest.cs | 14 +- .../DestructibleDamageTypeTest.cs | 14 +- .../DestructibleDestructionTest.cs | 14 +- .../DestructibleThresholdActivationTest.cs | 14 +- .../Tests/DeviceNetwork/DeviceNetworkTest.cs | 62 +- .../Tests/Disposal/DisposalUnitTest.cs | 10 +- .../Tests/DoAfter/DoAfterServerTest.cs | 19 +- .../Tests/Doors/AirlockTest.cs | 34 +- .../Tests/DummyIconTest.cs | 9 +- Content.IntegrationTests/Tests/EntityTest.cs | 57 +- .../Tests/Fluids/FluidSpillTest.cs | 22 +- .../Tests/Fluids/PuddleTest.cs | 46 +- .../Tests/FollowerSystemTest.cs | 8 +- .../Components/ActionBlocking/HandCuffTest.cs | 10 +- .../EntityPrototypeComponentsTest.cs | 14 +- .../Components/Mobs/AlertsComponentTests.cs | 15 +- .../Components/Movement/ClimbUnitTest.cs | 12 +- .../Tests/GameRules/RuleMaxTimeRestartTest.cs | 40 +- .../Tests/Gravity/WeightlessStatusTests.cs | 37 +- .../Tests/GravityGridTest.cs | 25 +- .../Tests/HumanInventoryUniformSlotsTest.cs | 14 +- .../Click/InteractionSystemTests.cs | 103 +-- .../Tests/Interaction/InRangeUnobstructed.cs | 13 +- .../Tests/InventoryHelpersTest.cs | 9 +- .../Tests/Lobby/CharacterCreationTest.cs | 46 +- .../Tests/MindEntityDeletionTest.cs | 71 +- .../Tests/Networking/ConnectTest.cs | 34 +- .../Tests/Networking/NetworkIdsMatchTest.cs | 33 +- .../Tests/Networking/ReconnectTest.cs | 24 +- .../Networking/SimplePredictReconcileTest.cs | 47 +- .../Tests/PostMapInitTest.cs | 107 ++- .../Tests/Power/PowerTest.cs | 506 +++++++------ .../Tests/ResettingEntitySystemTests.cs | 16 +- .../Tests/RestartRoundTest.cs | 10 +- .../Tests/RoundEndTest.cs | 11 +- .../Tests/SaveLoadMapTest.cs | 15 +- .../Tests/SaveLoadSaveTest.cs | 20 +- Content.IntegrationTests/Tests/ShuttleTest.cs | 8 +- Content.IntegrationTests/Tests/StartTest.cs | 52 +- .../Tests/Station/StationJobsTest.cs | 24 +- .../StationEvents/StationEventsSystemTest.cs | 9 +- .../Tests/StorageFillTest.cs | 8 +- Content.IntegrationTests/Tests/Tag/TagTest.cs | 12 +- .../Utility/EntitySystemExtensionsTest.cs | 15 +- .../Tests/Utility/EntityWhitelistTest.cs | 10 +- .../Tests/VendingMachineTest.cs | 9 +- Content.MapRenderer/Painters/MapPainter.cs | 37 +- .../Systems/StationJobsSystem.Roundstart.cs | 2 + .../Station/Systems/StationJobsSystem.cs | 2 - .../StationEvents/Events/BureaucraticError.cs | 1 + Content.YAMLLinter/Program.cs | 32 +- 80 files changed, 1769 insertions(+), 1788 deletions(-) delete mode 100644 Content.IntegrationTests/ContentIntegrationTest.cs delete mode 100644 Content.IntegrationTests/ContentIntegrationTestSetup.cs create mode 100644 Content.IntegrationTests/PoolManager.cs create mode 100644 Content.IntegrationTests/PoolManagerTestEventHandler.cs diff --git a/.github/workflows/build-test-debug.yml b/.github/workflows/build-test-debug.yml index c929fce6b9..d8128c0369 100644 --- a/.github/workflows/build-test-debug.yml +++ b/.github/workflows/build-test-debug.yml @@ -62,3 +62,8 @@ jobs: - name: Run Content.Tests run: dotnet test --no-build Content.Tests/Content.Tests.csproj -- NUnit.ConsoleOut=0 + - name: Run Content.IntegrationTests + shell: pwsh + run: | + $env:DOTNET_gcServer=1 + dotnet test --no-build Content.IntegrationTests/Content.IntegrationTests.csproj -- NUnit.ConsoleOut=0 diff --git a/Content.Client/Clothing/ClothingSystem.cs b/Content.Client/Clothing/ClothingSystem.cs index 95171f094c..702fd4e6b4 100644 --- a/Content.Client/Clothing/ClothingSystem.cs +++ b/Content.Client/Clothing/ClothingSystem.cs @@ -258,7 +258,7 @@ public sealed class ClothingSystem : EntitySystem // temporary, until layer draw depths get added. Basically: a layer with the key "slot" is being used as a // bookmark to determine where in the list of layers we should insert the clothing layers. bool slotLayerExists = sprite.LayerMapTryGet(slot, out var index); - + // add the new layers foreach (var (key, layerData) in ev.Layers) { diff --git a/Content.IntegrationTests/ContentIntegrationTest.cs b/Content.IntegrationTests/ContentIntegrationTest.cs deleted file mode 100644 index 6eba7723f6..0000000000 --- a/Content.IntegrationTests/ContentIntegrationTest.cs +++ /dev/null @@ -1,440 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Content.Client.Entry; -using Content.Client.IoC; -using Content.Client.Parallax.Managers; -using Content.Server.GameTicking; -using Content.Server.IoC; -using Content.Shared.CCVar; -using NUnit.Framework; -using Robust.Client; -using Robust.Server; -using Robust.Server.Player; -using Robust.Shared.ContentPack; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Log; -using Robust.Shared.Map; -using Robust.Shared.Network; -using Robust.Shared.Prototypes; -using Robust.UnitTesting; - -namespace Content.IntegrationTests -{ - [Parallelizable(ParallelScope.All)] - public abstract class ContentIntegrationTest : RobustIntegrationTest - { - private static readonly (string cvar, string value, bool)[] ServerTestCvars = { - // Avoid funny race conditions with the database. - (CCVars.DatabaseSynchronous.Name, "true", false), - - // No artificial database delay, as it can make tests fail. - (CCVars.DatabaseSqliteDelay.Name, "0", false), - - // Disable holidays as some of them might mess with the map at round start. - (CCVars.HolidaysEnabled.Name, "false", false), - - // Avoid loading a large map by default for integration tests if none has been specified. - (CCVars.GameMap.Name, "empty", true), - - // Makes sure IGameMapManager actually listens. - (CCVars.GameMapForced.Name, "true", true), - }; - - private static void SetServerTestCvars(IntegrationOptions options) - { - foreach (var (cvar, value, tryAdd) in ServerTestCvars) - { - if (tryAdd) - { - options.CVarOverrides.TryAdd(cvar, value); - } - else - { - options.CVarOverrides[cvar] = value; - } - } - } - - protected sealed override ClientIntegrationInstance StartClient(ClientIntegrationOptions options = null) - { - options ??= new ClientContentIntegrationOption() - { - FailureLogLevel = LogLevel.Warning - }; - - options.Pool = ShouldPool(options, false); - - // Load content resources, but not config and user data. - options.Options = new GameControllerOptions() - { - LoadContentResources = true, - LoadConfigAndUserData = false, - }; - - options.ContentStart = true; - - options.ContentAssemblies = new[] - { - typeof(Shared.Entry.EntryPoint).Assembly, - typeof(EntryPoint).Assembly, - typeof(ContentIntegrationTest).Assembly - }; - - options.BeforeStart += () => - { - IoCManager.Resolve().SetModuleBaseCallbacks(new ClientModuleTestingCallbacks - { - ClientBeforeIoC = () => - { - if (options is ClientContentIntegrationOption contentOptions) - { - contentOptions.ContentBeforeIoC?.Invoke(); - } - - IoCManager.Register(true); - IoCManager.Resolve().GetSawmill("loc").Level = LogLevel.Error; - } - }); - }; - - return base.StartClient(options); - } - - protected override ServerIntegrationInstance StartServer(ServerIntegrationOptions options = null) - { - options ??= new ServerContentIntegrationOption - { - FailureLogLevel = LogLevel.Warning, - }; - - SetServerTestCvars(options); - options.Pool = ShouldPool(options, true); - - // Load content resources, but not config and user data. - options.Options = new ServerOptions() - { - LoadConfigAndUserData = false, - LoadContentResources = true, - }; - - options.ContentStart = true; - - options.ContentAssemblies = new[] - { - typeof(Shared.Entry.EntryPoint).Assembly, - typeof(Server.Entry.EntryPoint).Assembly, - typeof(ContentIntegrationTest).Assembly - }; - - options.BeforeStart += () => - { - IoCManager.Resolve().SetModuleBaseCallbacks(new ServerModuleTestingCallbacks - { - ServerBeforeIoC = () => - { - if (options is ServerContentIntegrationOption contentOptions) - { - contentOptions.ContentBeforeIoC?.Invoke(); - } - } - }); - - IoCManager.Resolve().GetSawmill("loc").Level = LogLevel.Error; - }; - - return base.StartServer(options); - } - - protected ServerIntegrationInstance StartServerDummyTicker(ServerIntegrationOptions options = null) - { - options ??= new ServerContentIntegrationOption(); - - // Load content resources, but not config and user data. - options.Options = new ServerOptions() - { - LoadConfigAndUserData = false, - LoadContentResources = true, - }; - - // Dummy game ticker. - options.CVarOverrides[CCVars.GameDummyTicker.Name] = "true"; - - return StartServer(options); - } - - protected async Task<(ClientIntegrationInstance client, ServerIntegrationInstance server)> - StartConnectedServerClientPair(ClientIntegrationOptions clientOptions = null, - ServerIntegrationOptions serverOptions = null) - { - var client = StartClient(clientOptions); - var server = StartServer(serverOptions); - - await StartConnectedPairShared(client, server); - - return (client, server); - } - - protected async Task<(ClientIntegrationInstance client, ServerIntegrationInstance server)> - StartConnectedServerDummyTickerClientPair(ClientIntegrationOptions clientOptions = null, - ServerIntegrationOptions serverOptions = null) - { - var client = StartClient(clientOptions); - var server = StartServerDummyTicker(serverOptions); - - await StartConnectedPairShared(client, server); - - return (client, server); - } - - private bool ShouldPool(IntegrationOptions options, bool server) - { - // TODO TEST POOLING client pooling - if (!server) - { - return false; - } - - if (options.Pool.HasValue) - { - return options.Pool.Value; - } - - if (server) - { - if (options.CVarOverrides.Count != 3) - { - return false; - } - - foreach (var (cvar, value, _) in ServerTestCvars) - { - if (!options.CVarOverrides.TryGetValue(cvar, out var actualValue) || - actualValue != value) - { - return false; - } - } - } - - if (options.CVarOverrides.TryGetValue(CCVars.GameDummyTicker.Name, out var dummy) && - dummy == "true") - { - return false; - } - - if (options.CVarOverrides.TryGetValue(CCVars.GameLobbyEnabled.Name, out var lobby) && - lobby == "true") - { - return false; - } - - if (options is ClientContentIntegrationOption {ContentBeforeIoC: { }} - or ServerContentIntegrationOption {ContentBeforeIoC: { }}) - { - return false; - } - - return options.InitIoC == null && - options.BeforeStart == null && - options.ContentAssemblies == null; - } - - protected override async Task OnClientReturn(ClientIntegrationInstance client) - { - await base.OnClientReturn(client); - - await client.WaitIdleAsync(); - - var net = client.ResolveDependency(); - var prototypes = client.ResolveDependency(); - - await client.WaitPost(() => - { - net.ClientDisconnect("Test pooling disconnect"); - - if (client.PreviousOptions?.ExtraPrototypes is { } oldExtra) - { - prototypes.RemoveString(oldExtra); - } - - if (client.Options?.ExtraPrototypes is { } extra) - { - prototypes.LoadString(extra, true); - prototypes.ResolveResults(); - } - }); - - await WaitUntil(client, () => !net.IsConnected); - } - - protected override async Task OnServerReturn(ServerIntegrationInstance server) - { - await base.OnServerReturn(server); - - await server.WaitIdleAsync(); - - if (server.Options != null) - { - SetServerTestCvars(server.Options); - } - - var systems = server.ResolveDependency(); - var prototypes = server.ResolveDependency(); - var net = server.ResolveDependency(); - var players = server.ResolveDependency(); - - var gameTicker = systems.GetEntitySystem(); - - await server.WaitPost(() => - { - foreach (var channel in net.Channels) - { - net.DisconnectChannel(channel, "Test pooling disconnect"); - } - }); - - await WaitUntil(server, () => players.PlayerCount == 0); - - await server.WaitPost(() => - { - gameTicker.RestartRound(); - - if (server.PreviousOptions?.ExtraPrototypes is { } oldExtra) - { - prototypes.RemoveString(oldExtra); - } - - if (server.Options?.ExtraPrototypes is { } extra) - { - prototypes.LoadString(extra, true); - prototypes.ResolveResults(); - } - }); - - if (!gameTicker.DummyTicker) - { - await WaitUntil(server, () => gameTicker.RunLevel == GameRunLevel.InRound); - } - } - - protected async Task WaitUntil(IntegrationInstance instance, Func func, int maxTicks = 600, - int tickStep = 1) - { - await WaitUntil(instance, async () => await Task.FromResult(func()), maxTicks, tickStep); - } - - protected async Task WaitUntil(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); - } - - private static async Task StartConnectedPairShared(ClientIntegrationInstance client, - ServerIntegrationInstance server) - { - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); - - client.SetConnectTarget(server); - - client.Post(() => IoCManager.Resolve().ClientConnect(null!, 0, null!)); - - await RunTicksSync(client, server, 10); - } - - /// - /// Runs ticks on both server and client while keeping their main loop in sync. - /// - protected static async Task RunTicksSync(ClientIntegrationInstance client, ServerIntegrationInstance server, - int ticks) - { - for (var i = 0; i < ticks; i++) - { - await server.WaitRunTicks(1); - await client.WaitRunTicks(1); - } - } - - protected MapId GetMainMapId(IMapManager manager) - { - // TODO a heuristic that is not this bad - return manager.GetAllMapIds().Last(); - } - - protected IMapGrid GetMainGrid(IMapManager manager) - { - // TODO a heuristic that is not this bad - return manager.GetAllGrids().First(); - } - - protected TileRef GetMainTile(IMapGrid grid) - { - // TODO a heuristic that is not this bad - return grid.GetAllTiles().First(); - } - - protected EntityCoordinates GetMainEntityCoordinates(IMapManager manager) - { - var gridId = GetMainGrid(manager).GridEntityId; - return new EntityCoordinates(gridId, -0.5f, -0.5f); - } - - protected sealed class ClientContentIntegrationOption : ClientIntegrationOptions - { - public ClientContentIntegrationOption() - { - FailureLogLevel = LogLevel.Warning; - } - - public override GameControllerOptions Options { get; set; } = new() - { - LoadContentResources = true, - LoadConfigAndUserData = false, - }; - - public Action ContentBeforeIoC { get; set; } - } - - protected sealed class ServerContentIntegrationOption : ServerIntegrationOptions - { - public ServerContentIntegrationOption() - { - FailureLogLevel = LogLevel.Warning; - } - - public override ServerOptions Options { get; set; } = new() - { - LoadContentResources = true, - LoadConfigAndUserData = false, - }; - - public Action ContentBeforeIoC { get; set; } - } - } -} diff --git a/Content.IntegrationTests/ContentIntegrationTestSetup.cs b/Content.IntegrationTests/ContentIntegrationTestSetup.cs deleted file mode 100644 index b459fd480a..0000000000 --- a/Content.IntegrationTests/ContentIntegrationTestSetup.cs +++ /dev/null @@ -1,15 +0,0 @@ -using NUnit.Framework; - -[SetUpFixture] -// ReSharper disable once CheckNamespace -public sealed class ContentIntegrationTestSetup -{ - [OneTimeTearDown] - public void TearDown() - { - var robustSetup = new RobustIntegrationTestSetup(); - - robustSetup.Shutdown(); - robustSetup.PrintTestPoolingInfo(); - } -} diff --git a/Content.IntegrationTests/PoolManager.cs b/Content.IntegrationTests/PoolManager.cs new file mode 100644 index 0000000000..192dd52096 --- /dev/null +++ b/Content.IntegrationTests/PoolManager.cs @@ -0,0 +1,707 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Content.Client.IoC; +using Content.Client.Parallax.Managers; +using Content.IntegrationTests.Tests; +using Content.IntegrationTests.Tests.DeviceNetwork; +using Content.IntegrationTests.Tests.Interaction.Click; +using Content.IntegrationTests.Tests.Networking; +using Content.Server.GameTicking; +using Content.Shared.CCVar; +using Content.Shared.Maps; +using NUnit.Framework; +using Robust.Client; +using Robust.Server; +using Robust.Shared.Configuration; +using Robust.Shared.ContentPack; +using Robust.Shared.Exceptions; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Map; +using Robust.Shared.Network; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; +using Robust.UnitTesting; + + +[assembly: LevelOfParallelism(3)] + +namespace Content.IntegrationTests; + +public static class PoolManager +{ + private static readonly (string cvar, string value, bool tryAdd)[] ServerTestCvars = + { + (CCVars.DatabaseSynchronous.Name, "true", false), + (CCVars.DatabaseSqliteDelay.Name, "0", false), + (CCVars.HolidaysEnabled.Name, "false", false), + (CCVars.GameMap.Name, "empty", true), + (CCVars.GameMapForced.Name, "true", true), + (CCVars.AdminLogsQueueSendDelay.Name, "0", true), + (CCVars.NetPVS.Name, "false", true), + (CCVars.NetInterp.Name, "false", true), + (CCVars.NPCMaxUpdates.Name, "999999", true), + (CCVars.GameMapForced.Name, "true", true), + (CCVars.SysWinTickPeriod.Name, "0", true), + (CCVars.ContactMinimumThreads.Name, "1", true), + (CCVars.ContactMultithreadThreshold.Name, "999", true), + (CCVars.PositionConstraintsMinimumThread.Name, "1", true), + (CCVars.PositionConstraintsPerThread.Name, "999", true), + (CCVars.VelocityConstraintMinimumThreads.Name, "1", true), + (CCVars.VelocityConstraintsPerThread.Name, "999", true), + (CCVars.ThreadParallelCount.Name, "1", true), + }; + + private static int PairId = 0; + private static object PairLock = new object(); + private static List Pairs = new(); + + private static async Task ConfigurePrototypes(RobustIntegrationTest.IntegrationInstance instance, + PoolSettings settings) + { + await instance.WaitPost(() => + { + var prototypeManager = IoCManager.Resolve(); + var changes = new Dictionary>(); + prototypeManager.LoadString(settings.ExtraPrototypes.Trim(), true, changes); + prototypeManager.ReloadPrototypes(changes); + }); + } + + private static async Task GenerateServer(PoolSettings poolSettings) + { + var options = new RobustIntegrationTest.ServerIntegrationOptions + { + ExtraPrototypes = poolSettings.ExtraPrototypes, + ContentStart = true, + Options = new ServerOptions() + { + LoadConfigAndUserData = false, + LoadContentResources = !poolSettings.NoLoadContent, + }, + ContentAssemblies = new[] + { + typeof(Shared.Entry.EntryPoint).Assembly, + typeof(Server.Entry.EntryPoint).Assembly, + typeof(PoolManager).Assembly + } + }; + + options.BeforeStart += () => + { + IoCManager.Resolve() + .LoadExtraSystemType(); + IoCManager.Resolve().RegisterClass(); + IoCManager.Register(); + IoCManager.Register(); + IoCManager.Register(); + IoCManager.Resolve() + .LoadExtraSystemType(); + IoCManager.Resolve() + .LoadExtraSystemType(); + IoCManager.Resolve().LoadExtraSystemType(); + IoCManager.Resolve().GetSawmill("loc").Level = LogLevel.Error; + }; + + SetupCVars(poolSettings, options); + + var server = new RobustIntegrationTest.ServerIntegrationInstance(options); + await server.WaitIdleAsync(); + return server; + } + + public static void Shutdown() + { + lock (PairLock) + { + var pairs = Pairs; + // We are trying to make things blow up if they are still happening after this method. + Pairs = null; + foreach (var pair in pairs) + { + pair.Client.Dispose(); + pair.Server.Dispose(); + } + } + } + + private static async Task GenerateClient(PoolSettings poolSettings) + { + var options = new RobustIntegrationTest.ClientIntegrationOptions + { + FailureLogLevel = LogLevel.Warning, + ContentStart = true, + ExtraPrototypes = poolSettings.ExtraPrototypes, + ContentAssemblies = new[] + { + typeof(Shared.Entry.EntryPoint).Assembly, + typeof(Client.Entry.EntryPoint).Assembly, + typeof(PoolManager).Assembly + } + }; + + if (poolSettings.NoLoadContent) + { + Assert.Warn("NoLoadContent does not work on the client, ignoring"); + } + + options.Options = new GameControllerOptions() + { + LoadConfigAndUserData = false, + // LoadContentResources = !poolSettings.NoLoadContent + }; + + options.BeforeStart += () => + { + IoCManager.Resolve().SetModuleBaseCallbacks(new ClientModuleTestingCallbacks + { + ClientBeforeIoC = () => + { + IoCManager.Resolve() + .LoadExtraSystemType(); + IoCManager.Resolve() + .RegisterClass(); + IoCManager.Register(true); + IoCManager.Resolve().GetSawmill("loc").Level = LogLevel.Error; + } + }); + }; + + SetupCVars(poolSettings, options); + + var client = new RobustIntegrationTest.ClientIntegrationInstance(options); + await client.WaitIdleAsync(); + return client; + } + + private static void SetupCVars(PoolSettings poolSettings, RobustIntegrationTest.IntegrationOptions options) + { + foreach (var serverTestCvar in ServerTestCvars) + { + options.CVarOverrides[serverTestCvar.cvar] = serverTestCvar.value; + } + + if (poolSettings.DummyTicker) + { + options.CVarOverrides[CCVars.GameDummyTicker.Name] = "true"; + } + + if (poolSettings.InLobby) + { + options.CVarOverrides[CCVars.GameLobbyEnabled.Name] = "true"; + } + + if (poolSettings.DisableInterpolate) + { + options.CVarOverrides[CCVars.NetInterp.Name] = "false"; + } + + if (poolSettings.Map != null) + { + options.CVarOverrides[CCVars.GameMap.Name] = poolSettings.Map; + } + } + + public static async Task GetServerClient(PoolSettings poolSettings = null, + [System.Runtime.CompilerServices.CallerFilePath] string testMethodFilePath = "", + [System.Runtime.CompilerServices.CallerMemberName] string testMethodName = "") => + await GetServerClientPair(poolSettings ?? new PoolSettings(), $"{testMethodFilePath}, {testMethodName}"); + + private static async Task GetServerClientPair(PoolSettings poolSettings, string testMethodName) + { + var poolRetrieveTimeWatch = new Stopwatch(); + poolRetrieveTimeWatch.Start(); + await TestContext.Out.WriteLineAsync("Getting server/client"); + Pair pair; + if (poolSettings.MustBeNew) + { + await TestContext.Out.WriteLineAsync($"Creating, because must be new pair"); + pair = await CreateServerClientPair(poolSettings); + } + else + { + pair = GrabOptimalPair(poolSettings); + if (pair != null) + { + var mapManager = pair.Server.ResolveDependency(); + var mainGrid = GetMainGrid(mapManager); + var canSkip = pair.Settings.CanFastRecycle(poolSettings); + await TestContext.Out.WriteLineAsync($"canSkip: {canSkip}, maingrid:{mainGrid != null}"); + + if (!canSkip || mainGrid == null) + { + await TestContext.Out.WriteLineAsync($"Cleaning existing pair"); + await CleanPooledPair(poolSettings, pair); + } + else + { + await TestContext.Out.WriteLineAsync($"Skip cleanup pair"); + } + } + else + { + await TestContext.Out.WriteLineAsync($"Creating, because pool empty"); + pair = await CreateServerClientPair(poolSettings); + } + } + + var poolRetrieveTime = poolRetrieveTimeWatch.Elapsed; + await TestContext.Out.WriteLineAsync($"Got server/client (id:{pair.PairId},uses:{pair.TestHistory.Count}) in {poolRetrieveTime.TotalMilliseconds} ms"); + pair.Settings = poolSettings; + + TestContext.Out.WriteLine($"Test History|\n{string.Join('\n', pair.TestHistory)}\n|Test History End"); + pair.TestHistory.Add(testMethodName); + var usageWatch = new Stopwatch(); + usageWatch.Start(); + return new PairTracker() + { + Pair = pair, + UsageWatch = usageWatch + }; + } + + private static Pair GrabOptimalPair(PoolSettings poolSettings) + { + lock (PairLock) + { + if (Pairs.Count == 0) return null; + for (var i = 0; i < Pairs.Count; i++) + { + var pair = Pairs[i]; + if (!pair.Settings.CanFastRecycle(poolSettings)) continue; + Pairs.RemoveAt(i); + return pair; + } + var defaultPair = Pairs[^1]; + Pairs.RemoveAt(Pairs.Count - 1); + return defaultPair; + } + } + + /// + /// Used after checking pairs, Don't use this directly + /// + /// + public static void NoCheckReturn(Pair pair) + { + lock (PairLock) + { + Pairs.Add(pair); + } + } + + private static async Task CleanPooledPair(PoolSettings poolSettings, Pair pair) + { + var methodWatch = new Stopwatch(); + methodWatch.Start(); + await TestContext.Out.WriteLineAsync($"Recycling: {methodWatch.Elapsed.TotalMilliseconds} ms: Setting CVar "); + var configManager = pair.Server.ResolveDependency(); + await pair.Server.WaitPost(() => + { + configManager.SetCVar(CCVars.GameLobbyEnabled, poolSettings.InLobby); + }); + var cNetMgr = pair.Client.ResolveDependency(); + if (!cNetMgr.IsConnected) + { + await TestContext.Out.WriteLineAsync($"Recycling: {methodWatch.Elapsed.TotalMilliseconds} ms: Connecting client, and restarting server"); + pair.Client.SetConnectTarget(pair.Server); + await pair.Server.WaitPost(() => + { + EntitySystem.Get().RestartRound(); + }); + await pair.Client.WaitPost(() => + { + cNetMgr.ClientConnect(null!, 0, null!); + }); + await ReallyBeIdle(pair,11); + } + await TestContext.Out.WriteLineAsync($"Recycling: {methodWatch.Elapsed.TotalMilliseconds} ms: Disconnecting client, and restarting server"); + + await pair.Client.WaitPost(() => + { + cNetMgr.ClientDisconnect("Test pooling cleanup disconnect"); + }); + await ReallyBeIdle(pair, 5); + + if (!string.IsNullOrWhiteSpace(pair.Settings.ExtraPrototypes)) + { + await TestContext.Out.WriteLineAsync($"Recycling: {methodWatch.Elapsed.TotalMilliseconds} ms: Removing prototypes"); + if (!pair.Settings.NoServer) + { + var serverProtoManager = pair.Server.ResolveDependency(); + await pair.Server.WaitPost(() => + { + serverProtoManager.RemoveString(pair.Settings.ExtraPrototypes.Trim()); + }); + } + if(!pair.Settings.NoClient) + { + var clientProtoManager = pair.Client.ResolveDependency(); + await pair.Client.WaitPost(() => + { + clientProtoManager.RemoveString(pair.Settings.ExtraPrototypes.Trim()); + }); + } + + await ReallyBeIdle(pair, 1); + } + + if (poolSettings.ExtraPrototypes != null) + { + await TestContext.Out.WriteLineAsync($"Recycling: {methodWatch.Elapsed.TotalMilliseconds} ms: Adding prototypes"); + if (!poolSettings.NoServer) + { + await ConfigurePrototypes(pair.Server, poolSettings); + } + if (!poolSettings.NoClient) + { + await ConfigurePrototypes(pair.Client, poolSettings); + } + } + + await TestContext.Out.WriteLineAsync($"Recycling: {methodWatch.Elapsed.TotalMilliseconds} ms: Restarting server again"); + await pair.Server.WaitPost(() => + { + EntitySystem.Get().RestartRound(); + }); + + + if (!poolSettings.NotConnected) + { + await TestContext.Out.WriteLineAsync($"Recycling: {methodWatch.Elapsed.TotalMilliseconds} ms: Connecting client"); + await ReallyBeIdle(pair); + pair.Client.SetConnectTarget(pair.Server); + await pair.Client.WaitPost(() => + { + var netMgr = IoCManager.Resolve(); + if (!netMgr.IsConnected) + { + netMgr.ClientConnect(null!, 0, null!); + } + }); + } + await ReallyBeIdle(pair); + await TestContext.Out.WriteLineAsync($"Recycling: {methodWatch.Elapsed.TotalMilliseconds} ms: Done recycling"); + } + + private static async Task CreateServerClientPair(PoolSettings poolSettings) + { + var client = await GenerateClient(poolSettings); + var server = await GenerateServer(poolSettings); + + var pair = new Pair { Server = server, Client = client, PairId = Interlocked.Increment(ref PairId)}; + if (!poolSettings.NotConnected) + { + pair.Client.SetConnectTarget(pair.Server); + await pair.Client.WaitPost(() => + { + var netMgr = IoCManager.Resolve(); + if (!netMgr.IsConnected) + { + netMgr.ClientConnect(null!, 0, null!); + } + }); + await ReallyBeIdle(pair, 10); + await client.WaitRunTicks(1); + } + return pair; + } + + public static TileRef GetMainTile(IMapManager manager) + { + foreach (var grid in manager.GetAllGrids()) + { + if (manager.GridExists(grid.GridEntityId)) + { + foreach (var tile in grid.GetAllTiles()) + { + if(tile.IsSpace())continue; + if(tile.IsBlockedTurf(false))continue; + return tile; + } + } + } + + throw new Exception("Failed to find empty tile"); + } + + public static EntityCoordinates GetMainEntityCoordinates(IMapManager manager) + { + var gridId = GetMainGrid(manager).GridEntityId; + return new EntityCoordinates(gridId, -0.5f, -0.5f); + } + + public static IMapGrid GetMainGrid(IMapManager manager) + { + foreach (var grid in manager.GetAllGrids()) + { + if (manager.GridExists(grid.GridEntityId)) + return grid; + } + + return null; + } + + public static async Task RunTicksSync(Pair pair, int ticks) + { + for (var i = 0; i < ticks; i++) + { + await pair.Server.WaitRunTicks(1); + await pair.Client.WaitRunTicks(1); + } + } + + 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); + } + + public static async Task ReallyBeIdle(Pair pair, int runTicks = 25) + { + for (int i = 0; i < runTicks; i++) + { + await pair.Client.WaitRunTicks(1); + await pair.Server.WaitRunTicks(1); + for (int idleCycles = 0; idleCycles < 4; idleCycles++) + { + await pair.Client.WaitIdleAsync(); + await pair.Server.WaitIdleAsync(); + } + } + } + + 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 sealed class PoolSettings +{ + // Todo: We can make more of these pool-able, if we need enough of them for it to matter + public bool MustNotBeReused => Destructive || NoLoadContent || DisableInterpolate || DummyTicker; + public bool MustBeNew => Fresh || NoLoadContent || DisableInterpolate || DummyTicker; + + public bool NotConnected => NoClient || NoServer || Disconnected; + /// + /// We are going to ruin this pair + /// + public bool Destructive { get; init; } + + /// + /// We need a brand new pair + /// + public bool Fresh { get; init; } + + /// + /// We need a pair that uses a dummy ticker + /// + public bool DummyTicker { get; init; } + + /// + /// We need the client, and server to be disconnected + /// + public bool Disconnected { get; init; } + + /// + /// We need the server to be in the lobby + /// + public bool InLobby { get; init; } + + /// + /// We don't want content loaded + /// + public bool NoLoadContent { get; init; } + + /// + /// We want to add some prototypes + /// + public string ExtraPrototypes { get; init; } + + /// + /// Disables NetInterp + /// + public bool DisableInterpolate { get; init; } + + /// + /// Tells the pool it has to clean up before the server/client can be used. + /// + public bool Dirty { get; init; } + + /// + /// Sets the map Cvar, and loads the map + /// + public string Map { get; init; } // TODO for map painter + + /// + /// The test won't use the client (so we can skip cleaning it) + /// + public bool NoClient { get; init; } + + /// + /// The test won't use the client (so we can skip cleaning it) + /// + public bool NoServer { get; init; } + + /// + /// Guess if skipping recycling is ok + /// + /// The next set of settings the old pair will be set to + /// + public bool CanFastRecycle(PoolSettings nextSettings) + { + if (Dirty) return false; + if (Destructive || nextSettings.Destructive) return false; + if (NotConnected != nextSettings.NotConnected) return false; + if (InLobby != nextSettings.InLobby) return false; + if (DisableInterpolate != nextSettings.DisableInterpolate) return false; + if (nextSettings.DummyTicker) return false; + if (Map != nextSettings.Map) return false; + if (NoLoadContent != nextSettings.NoLoadContent) return false; + if (nextSettings.Fresh) return false; + if (ExtraPrototypes != nextSettings.ExtraPrototypes) return false; + return true; + } +} + +public sealed class Pair +{ + public int PairId { get; init; } + public List TestHistory { get; set; } = new(); + public PoolSettings Settings { get; set; } + public RobustIntegrationTest.ServerIntegrationInstance Server { get; init; } + public RobustIntegrationTest.ClientIntegrationInstance Client { get; init; } +} + +public sealed class PairTracker : IAsyncDisposable +{ + private int _disposed; + + public async Task OnDirtyDispose() + { + var usageTime = UsageWatch.Elapsed; + await TestContext.Out.WriteLineAsync($"Dirty: Test returned in {usageTime.TotalMilliseconds} ms"); + var dirtyWatch = new Stopwatch(); + dirtyWatch.Start(); + Pair.Client.Dispose(); + Pair.Server.Dispose(); + var disposeTime = dirtyWatch.Elapsed; + await TestContext.Out.WriteLineAsync($"Dirty: Disposed in {disposeTime.TotalMilliseconds} ms"); + } + + public async Task OnCleanDispose() + { + var usageTime = UsageWatch.Elapsed; + await TestContext.Out.WriteLineAsync($"Clean: Test returned in {usageTime.TotalMilliseconds} ms"); + var cleanWatch = new Stopwatch(); + cleanWatch.Start(); + // Let any last minute failures the test cause happen. + await PoolManager.ReallyBeIdle(Pair); + if (!Pair.Settings.Destructive) + { + if (Pair.Client.IsAlive == false) + { + throw new Exception("Test killed the client", Pair.Client.UnhandledException); + } + + if (Pair.Server.IsAlive == false) + { + throw new Exception("Test killed the server", Pair.Server.UnhandledException); + } + } + + if (Pair.Settings.MustNotBeReused) + { + Pair.Client.Dispose(); + Pair.Server.Dispose(); + var returnTime2 = cleanWatch.Elapsed; + await TestContext.Out.WriteLineAsync($"Clean: Clean disposed in {returnTime2.TotalMilliseconds} ms"); + return; + } + + var sRuntimeLog = Pair.Server.ResolveDependency(); + if (sRuntimeLog.ExceptionCount > 0) throw new Exception("Server logged exceptions"); + var cRuntimeLog = Pair.Client.ResolveDependency(); + if (cRuntimeLog.ExceptionCount > 0) throw new Exception("Client logged exceptions"); + PoolManager.NoCheckReturn(Pair); + var returnTime = cleanWatch.Elapsed; + await TestContext.Out.WriteLineAsync($"Clean: Clean returned to pool in {returnTime.TotalMilliseconds} ms"); + } + public Stopwatch UsageWatch { get; set; } + public Pair Pair { get; init; } + + public async ValueTask CleanReturnAsync() + { + var disposed = Interlocked.Exchange(ref _disposed, 1); + switch (disposed) + { + case 0: + await TestContext.Out.WriteLineAsync("Clean Return Start"); + break; + case 1: + throw new Exception("Already called clean return before"); + case 2: + throw new Exception("Already dirty disposed"); + default: + throw new Exception("Unexpected disposed value"); + } + + await OnCleanDispose(); + await TestContext.Out.WriteLineAsync($"Clean Return Exiting"); + } + + public async ValueTask DisposeAsync() + { + var disposed = Interlocked.Exchange(ref _disposed, 2); + switch (disposed) + { + case 0: + await TestContext.Out.WriteLineAsync("Dirty Return Start"); + break; + case 1: + await TestContext.Out.WriteLineAsync("Dirty Return - Already Clean Disposed"); + return; + case 2: + throw new Exception("Already called dirty return before"); + default: + throw new Exception("Unexpected disposed value"); + } + + await OnDirtyDispose(); + await TestContext.Out.WriteLineAsync($"Dirty Return Exiting"); + } +} diff --git a/Content.IntegrationTests/PoolManagerTestEventHandler.cs b/Content.IntegrationTests/PoolManagerTestEventHandler.cs new file mode 100644 index 0000000000..6d3598bb87 --- /dev/null +++ b/Content.IntegrationTests/PoolManagerTestEventHandler.cs @@ -0,0 +1,15 @@ +using NUnit.Framework; + +[assembly: Parallelizable(ParallelScope.Children)] + +namespace Content.IntegrationTests; + +[SetUpFixture] +public sealed class PoolManagerTestEventHandler +{ + [OneTimeTearDown] + public void TearDown() + { + PoolManager.Shutdown(); + } +} diff --git a/Content.IntegrationTests/Tests/AI/BehaviorSetsTest.cs b/Content.IntegrationTests/Tests/AI/BehaviorSetsTest.cs index a98b7f26a3..4f89e79791 100644 --- a/Content.IntegrationTests/Tests/AI/BehaviorSetsTest.cs +++ b/Content.IntegrationTests/Tests/AI/BehaviorSetsTest.cs @@ -12,13 +12,13 @@ namespace Content.IntegrationTests.Tests.AI { [TestFixture] [TestOf(typeof(BehaviorSetPrototype))] - public sealed class BehaviorSetsTest : ContentIntegrationTest + public sealed class BehaviorSetsTest { [Test] public async Task TestBehaviorSets() { - var server = StartServer(); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var protoManager = server.ResolveDependency(); var reflectionManager = server.ResolveDependency(); @@ -56,6 +56,7 @@ namespace Content.IntegrationTests.Tests.AI } } }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Access/AccessReaderTest.cs b/Content.IntegrationTests/Tests/Access/AccessReaderTest.cs index e14a034fb7..ae8da040ec 100644 --- a/Content.IntegrationTests/Tests/Access/AccessReaderTest.cs +++ b/Content.IntegrationTests/Tests/Access/AccessReaderTest.cs @@ -9,12 +9,14 @@ namespace Content.IntegrationTests.Tests.Access { [TestFixture] [TestOf(typeof(AccessReaderComponent))] - public sealed class AccessReaderTest : ContentIntegrationTest + public sealed class AccessReaderTest { [Test] public async Task TestTags() { - var server = StartServer(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; + await server.WaitAssertion(() => { var system = EntitySystem.Get(); @@ -69,6 +71,7 @@ namespace Content.IntegrationTests.Tests.Access Assert.That(system.IsAllowed(new[] { "A", "B" }, reader), Is.False); Assert.That(system.IsAllowed(new string[] { }, reader), Is.False); }); + await pairTracker.CleanReturnAsync(); } } diff --git a/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs b/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs index c2666465b8..e9575985c9 100644 --- a/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs +++ b/Content.IntegrationTests/Tests/Administration/Logs/AddTests.cs @@ -5,11 +5,13 @@ using System.Threading.Tasks; using Content.Server.Administration.Logs; using Content.Server.Database; using Content.Server.GameTicking; +using Content.Server.GameTicking.Commands; using Content.Shared.Administration.Logs; using Content.Shared.CCVar; using Content.Shared.Database; using NUnit.Framework; using Robust.Server.Player; +using Robust.Shared.Configuration; using Robust.Shared.GameObjects; using Robust.Shared.Map; @@ -17,24 +19,16 @@ namespace Content.IntegrationTests.Tests.Administration.Logs; [TestFixture] [TestOf(typeof(AdminLogSystem))] -public sealed class AddTests : ContentIntegrationTest +public sealed class AddTests { [Test] public async Task AddAndGetSingleLog() { - var server = StartServer(new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.AdminLogsQueueSendDelay.Name] = "0" - }, - Pool = true - }); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var sMaps = server.ResolveDependency(); - var sSystems = server.ResolveDependency(); var sAdminLogSystem = server.ResolveDependency(); @@ -42,13 +36,13 @@ public sealed class AddTests : ContentIntegrationTest await server.WaitPost(() => { - var coordinates = GetMainEntityCoordinates(sMaps); + var coordinates = PoolManager.GetMainEntityCoordinates(sMaps); var entity = sEntities.SpawnEntity(null, coordinates); sAdminLogSystem.Add(LogType.Unknown, $"{entity:Entity} test log: {guid}"); }); - await WaitUntil(server, async () => + await PoolManager.WaitUntil(server, async () => { var logs = sAdminLogSystem.CurrentRoundJson(new LogFilter { @@ -69,20 +63,15 @@ public sealed class AddTests : ContentIntegrationTest return false; }); + + await pairTracker.CleanReturnAsync(); } [Test] public async Task AddAndGetUnformattedLog() { - var server = StartServer(new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.AdminLogsQueueSendDelay.Name] = "0" - }, - Pool = true - }); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var sDatabase = server.ResolveDependency(); var sEntities = server.ResolveDependency(); @@ -96,7 +85,7 @@ public sealed class AddTests : ContentIntegrationTest await server.WaitPost(() => { - var coordinates = GetMainEntityCoordinates(sMaps); + var coordinates = PoolManager.GetMainEntityCoordinates(sMaps); var entity = sEntities.SpawnEntity(null, coordinates); sAdminLogSystem.Add(LogType.Unknown, $"{entity} test log: {guid}"); @@ -104,7 +93,7 @@ public sealed class AddTests : ContentIntegrationTest SharedAdminLog log = default; - await WaitUntil(server, async () => + await PoolManager.WaitUntil(server, async () => { var logs = await sAdminLogSystem.CurrentRoundLogs(new LogFilter { @@ -136,31 +125,25 @@ public sealed class AddTests : ContentIntegrationTest json.Dispose(); } + + await pairTracker.CleanReturnAsync(); } [Test] [TestCase(500)] public async Task BulkAddLogs(int amount) { - var server = StartServer(new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.AdminLogsQueueSendDelay.Name] = "0" - }, - Pool = true - }); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var sMaps = server.ResolveDependency(); - var sSystems = server.ResolveDependency(); var sAdminLogSystem = server.ResolveDependency(); await server.WaitPost(() => { - var coordinates = GetMainEntityCoordinates(sMaps); + var coordinates = PoolManager.GetMainEntityCoordinates(sMaps); var entity = sEntities.SpawnEntity(null, coordinates); for (var i = 0; i < amount; i++) @@ -169,26 +152,20 @@ public sealed class AddTests : ContentIntegrationTest } }); - await WaitUntil(server, async () => + await PoolManager.WaitUntil(server, async () => { var messages = await sAdminLogSystem.CurrentRoundLogs(); return messages.Count >= amount; }); + + await pairTracker.CleanReturnAsync(); } [Test] public async Task AddPlayerSessionLog() { - var (client, server) = await StartConnectedServerClientPair(serverOptions: new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.AdminLogsQueueSendDelay.Name] = "0" - }, - Pool = true - }); - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; var sPlayers = server.ResolveDependency(); var sSystems = server.ResolveDependency(); @@ -207,7 +184,7 @@ public sealed class AddTests : ContentIntegrationTest }); }); - await WaitUntil(server, async () => + await PoolManager.WaitUntil(server, async () => { var logs = await sAdminLogSystem.CurrentRoundLogs(); if (logs.Count == 0) @@ -218,20 +195,22 @@ public sealed class AddTests : ContentIntegrationTest Assert.That(logs.First().Players, Does.Contain(playerGuid)); return true; }); + await pairTracker.CleanReturnAsync(); } [Test] public async Task PreRoundAddAndGetSingle() { - var server = StartServer(new ServerContentIntegrationOption + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{Dirty = true}); + var server = pairTracker.Pair.Server; + + var configManager = server.ResolveDependency(); + await server.WaitPost(() => { - CVarOverrides = - { - [CCVars.AdminLogsQueueSendDelay.Name] = "0", - [CCVars.GameLobbyEnabled.Name] = "true" - }, + configManager.SetCVar(CCVars.GameLobbyEnabled, true); + var command = new RestartRoundNowCommand(); + command.Execute(null, string.Empty, Array.Empty()); }); - await server.WaitIdleAsync(); var sDatabase = server.ResolveDependency(); var sSystems = server.ResolveDependency(); @@ -253,7 +232,7 @@ public sealed class AddTests : ContentIntegrationTest SharedAdminLog log = default; - await WaitUntil(server, async () => + await PoolManager.WaitUntil(server, async () => { var logs = await sAdminLogSystem.CurrentRoundLogs(new LogFilter { @@ -284,20 +263,14 @@ public sealed class AddTests : ContentIntegrationTest json.Dispose(); } + await pairTracker.CleanReturnAsync(); } [Test] public async Task DuplicatePlayerDoesNotThrowTest() { - var (client, server) = await StartConnectedServerClientPair(serverOptions: new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.AdminLogsQueueSendDelay.Name] = "0" - }, - }); - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; var sPlayers = server.ResolveDependency(); var sSystems = server.ResolveDependency(); @@ -313,7 +286,7 @@ public sealed class AddTests : ContentIntegrationTest sAdminLogSystem.Add(LogType.Unknown, $"{player} {player} test log: {guid}"); }); - await WaitUntil(server, async () => + await PoolManager.WaitUntil(server, async () => { var logs = await sAdminLogSystem.CurrentRoundLogs(new LogFilter { @@ -328,24 +301,17 @@ public sealed class AddTests : ContentIntegrationTest return true; }); + await pairTracker.CleanReturnAsync(); Assert.Pass(); } [Test] public async Task DuplicatePlayerIdDoesNotThrowTest() { - var (client, server) = await StartConnectedServerClientPair(serverOptions: new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.AdminLogsQueueSendDelay.Name] = "0" - }, - }); - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; var sPlayers = server.ResolveDependency(); - var sSystems = server.ResolveDependency(); var sAdminLogSystem = server.ResolveDependency(); @@ -358,7 +324,7 @@ public sealed class AddTests : ContentIntegrationTest sAdminLogSystem.Add(LogType.Unknown, $"{player:first} {player:second} test log: {guid}"); }); - await WaitUntil(server, async () => + await PoolManager.WaitUntil(server, async () => { var logs = await sAdminLogSystem.CurrentRoundLogs(new LogFilter { @@ -373,6 +339,7 @@ public sealed class AddTests : ContentIntegrationTest return true; }); + await pairTracker.CleanReturnAsync(); Assert.Pass(); } } diff --git a/Content.IntegrationTests/Tests/Administration/Logs/FilterTests.cs b/Content.IntegrationTests/Tests/Administration/Logs/FilterTests.cs index 9ba8b57eea..310a35b72c 100644 --- a/Content.IntegrationTests/Tests/Administration/Logs/FilterTests.cs +++ b/Content.IntegrationTests/Tests/Administration/Logs/FilterTests.cs @@ -12,26 +12,18 @@ namespace Content.IntegrationTests.Tests.Administration.Logs; [TestFixture] [TestOf(typeof(AdminLogSystem))] -public sealed class FilterTests : ContentIntegrationTest +public sealed class FilterTests { [Test] [TestCase(DateOrder.Ascending)] [TestCase(DateOrder.Descending)] public async Task Date(DateOrder order) { - var server = StartServer(new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.AdminLogsQueueSendDelay.Name] = "0" - }, - Pool = true - }); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var sMaps = server.ResolveDependency(); - var sSystems = server.ResolveDependency(); var sAdminLogSystem = server.ResolveDependency(); @@ -41,7 +33,7 @@ public sealed class FilterTests : ContentIntegrationTest await server.WaitPost(() => { - var coordinates = GetMainEntityCoordinates(sMaps); + var coordinates = PoolManager.GetMainEntityCoordinates(sMaps); var entity = sEntities.SpawnEntity(null, coordinates); sAdminLogSystem.Add(LogType.Unknown, $"{entity:Entity} test log: {commonGuid} {firstGuid}"); @@ -51,13 +43,13 @@ public sealed class FilterTests : ContentIntegrationTest await server.WaitPost(() => { - var coordinates = GetMainEntityCoordinates(sMaps); + var coordinates = PoolManager.GetMainEntityCoordinates(sMaps); var entity = sEntities.SpawnEntity(null, coordinates); sAdminLogSystem.Add(LogType.Unknown, $"{entity:Entity} test log: {commonGuid} {secondGuid}"); }); - await WaitUntil(server, async () => + await PoolManager.WaitUntil(server, async () => { var commonGuidStr = commonGuid.ToString(); @@ -110,5 +102,6 @@ public sealed class FilterTests : ContentIntegrationTest return firstFound && secondFound; }); + await pairTracker.CleanReturnAsync(); } } diff --git a/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs b/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs index 6a686d4420..4805ce20ce 100644 --- a/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs +++ b/Content.IntegrationTests/Tests/Administration/Logs/QueryTests.cs @@ -14,21 +14,13 @@ namespace Content.IntegrationTests.Tests.Administration.Logs; [TestFixture] [TestOf(typeof(AdminLogSystem))] -public sealed class QueryTests : ContentIntegrationTest +public sealed class QueryTests { [Test] public async Task QuerySingleLog() { - var serverOptions = new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.AdminLogsQueueSendDelay.Name] = "0" - } - }; - var (client, server) = await StartConnectedServerClientPair(serverOptions: serverOptions); - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; var sSystems = server.ResolveDependency(); var sPlayers = server.ResolveDependency(); @@ -57,7 +49,7 @@ public sealed class QueryTests : ContentIntegrationTest AnyPlayers = new[] {player.UserId.UserId} }; - await WaitUntil(server, async () => + await PoolManager.WaitUntil(server, async () => { foreach (var _ in await sAdminLogSystem.All(filter)) { @@ -66,5 +58,7 @@ public sealed class QueryTests : ContentIntegrationTest return false; }); + + await pairTracker.CleanReturnAsync(); } } diff --git a/Content.IntegrationTests/Tests/Atmos/AlarmThresholdTest.cs b/Content.IntegrationTests/Tests/Atmos/AlarmThresholdTest.cs index dcdb5e5f42..98d5ac9222 100644 --- a/Content.IntegrationTests/Tests/Atmos/AlarmThresholdTest.cs +++ b/Content.IntegrationTests/Tests/Atmos/AlarmThresholdTest.cs @@ -7,7 +7,7 @@ namespace Content.IntegrationTests.Tests.Atmos { [TestFixture] [TestOf(typeof(AtmosAlarmThreshold))] - public sealed class AlarmThresholdTest : ContentIntegrationTest + public sealed class AlarmThresholdTest { private const string Prototypes = @" - type: alarmThreshold @@ -21,12 +21,8 @@ namespace Content.IntegrationTests.Tests.Atmos [Test] public async Task TestAlarmThreshold() { - var server = StartServerDummyTicker(new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var prototypeManager = server.ResolveDependency(); AtmosAlarmThreshold threshold = default!; @@ -91,6 +87,7 @@ namespace Content.IntegrationTests.Tests.Atmos Assert.That(threshold.UpperBound, Is.EqualTo(null)); Assert.That(threshold.LowerBound, Is.EqualTo(null)); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Atmos/ConstantsTest.cs b/Content.IntegrationTests/Tests/Atmos/ConstantsTest.cs index 2b984ead03..6eba112b2f 100644 --- a/Content.IntegrationTests/Tests/Atmos/ConstantsTest.cs +++ b/Content.IntegrationTests/Tests/Atmos/ConstantsTest.cs @@ -10,14 +10,13 @@ namespace Content.IntegrationTests.Tests.Atmos { [TestFixture] [TestOf(typeof(Atmospherics))] - public sealed class ConstantsTest : ContentIntegrationTest + public sealed class ConstantsTest { [Test] public async Task TotalGasesTest() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; await server.WaitPost(() => { @@ -27,6 +26,7 @@ namespace Content.IntegrationTests.Tests.Atmos Assert.That(Enum.GetValues(typeof(Gas)).Length, Is.EqualTo(Atmospherics.TotalNumberOfGases)); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs b/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs index 666d306b45..1302dc9f4b 100644 --- a/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs +++ b/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs @@ -9,18 +9,17 @@ namespace Content.IntegrationTests.Tests.Atmos { [TestFixture] [TestOf(typeof(GasMixture))] - public sealed class GasMixtureTest : ContentIntegrationTest + public sealed class GasMixtureTest { [Test] public async Task TestMerge() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var atmosphereSystem = server.ResolveDependency().GetEntitySystem(); - server.Assert(() => + await server.WaitAssertion(() => { var a = new GasMixture(10f); var b = new GasMixture(10f); @@ -48,7 +47,7 @@ namespace Content.IntegrationTests.Tests.Atmos Assert.That(a.GetMoles(Gas.Oxygen), Is.EqualTo(50)); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] @@ -60,9 +59,10 @@ namespace Content.IntegrationTests.Tests.Atmos [TestCase(Atmospherics.BreathPercentage)] public async Task RemoveRatio(float ratio) { - var server = StartServer(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; - server.Assert(() => + await server.WaitAssertion(() => { var a = new GasMixture(10f); @@ -85,7 +85,7 @@ namespace Content.IntegrationTests.Tests.Atmos Assert.That(a.GetMoles(Gas.Nitrogen), Is.EqualTo(100 - b.GetMoles(Gas.Nitrogen))); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Body/LegTest.cs b/Content.IntegrationTests/Tests/Body/LegTest.cs index 4edb6e8aa1..01469422cb 100644 --- a/Content.IntegrationTests/Tests/Body/LegTest.cs +++ b/Content.IntegrationTests/Tests/Body/LegTest.cs @@ -14,7 +14,7 @@ namespace Content.IntegrationTests.Tests.Body [TestFixture] [TestOf(typeof(SharedBodyComponent))] [TestOf(typeof(BodyComponent))] - public sealed class LegTest : ContentIntegrationTest + public sealed class LegTest { private const string Prototypes = @" - type: entity @@ -32,8 +32,8 @@ namespace Content.IntegrationTests.Tests.Body [Test] public async Task RemoveLegsFallTest() { - var options = new ServerContentIntegrationOption{ExtraPrototypes = Prototypes}; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; AppearanceComponent appearance = null; @@ -64,6 +64,7 @@ namespace Content.IntegrationTests.Tests.Body Assert.That(appearance.TryGetData(RotationVisuals.RotationState, out RotationState state)); Assert.That(state, Is.EqualTo(RotationState.Horizontal)); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Body/LungTest.cs b/Content.IntegrationTests/Tests/Body/LungTest.cs index 60cf1c88a8..24f1094b38 100644 --- a/Content.IntegrationTests/Tests/Body/LungTest.cs +++ b/Content.IntegrationTests/Tests/Body/LungTest.cs @@ -13,7 +13,7 @@ namespace Content.IntegrationTests.Tests.Body { [TestFixture] [TestOf(typeof(LungSystem))] - public sealed class LungTest : ContentIntegrationTest + public sealed class LungTest { private const string Prototypes = @" - type: entity @@ -49,8 +49,8 @@ namespace Content.IntegrationTests.Tests.Body public async Task AirConsistencyTest() { // --- Setup - var options = new ServerContentIntegrationOption{ExtraPrototypes = Prototypes}; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; await server.WaitIdleAsync(); @@ -121,16 +121,14 @@ namespace Content.IntegrationTests.Tests.Body }); } - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task NoSuffocationTest() { - var options = new ServerContentIntegrationOption{ExtraPrototypes = Prototypes}; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var mapLoader = server.ResolveDependency(); var mapManager = server.ResolveDependency(); @@ -173,7 +171,7 @@ namespace Content.IntegrationTests.Tests.Body }); } - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs index 9cf8a39421..6f1e877368 100644 --- a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs +++ b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs @@ -17,7 +17,7 @@ namespace Content.IntegrationTests.Tests.Buckle [TestFixture] [TestOf(typeof(BuckleComponent))] [TestOf(typeof(StrapComponent))] - public sealed class BuckleTest : ContentIntegrationTest + public sealed class BuckleTest { private const string BuckleDummyId = "BuckleDummy"; private const string StrapDummyId = "StrapDummy"; @@ -51,9 +51,8 @@ namespace Content.IntegrationTests.Tests.Buckle [Test] public async Task BuckleUnbuckleCooldownRangeTest() { - var cOptions = new ClientIntegrationOptions {ExtraPrototypes = Prototypes}; - var sOptions = new ServerIntegrationOptions {ExtraPrototypes = Prototypes}; - var (_, server) = await StartConnectedServerClientPair(cOptions, sOptions); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; EntityUid human = default; EntityUid chair = default; @@ -68,8 +67,7 @@ namespace Content.IntegrationTests.Tests.Buckle var actionBlocker = EntitySystem.Get(); var standingState = EntitySystem.Get(); - var grid = GetMainGrid(mapManager); - var coordinates = new EntityCoordinates(grid.GridEntityId, 0, 0); + var coordinates = PoolManager.GetMainEntityCoordinates(mapManager); human = entityManager.SpawnEntity(BuckleDummyId, coordinates); chair = entityManager.SpawnEntity(StrapDummyId, coordinates); @@ -209,13 +207,15 @@ namespace Content.IntegrationTests.Tests.Buckle Assert.Null(buckle.BuckledTo); Assert.IsEmpty(strap.BuckledEntities); }); + + await pairTracker.CleanReturnAsync(); } [Test] public async Task BuckledDyingDropItemsTest() { - var options = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes}; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; EntityUid human = default; BuckleComponent buckle = null; @@ -229,8 +229,7 @@ namespace Content.IntegrationTests.Tests.Buckle var mapManager = IoCManager.Resolve(); var entityManager = IoCManager.Resolve(); - var grid = GetMainGrid(mapManager); - var coordinates = new EntityCoordinates(grid.GridEntityId, 0, 0); + var coordinates = PoolManager.GetMainEntityCoordinates(mapManager); human = entityManager.SpawnEntity(BuckleDummyId, coordinates); var chair = entityManager.SpawnEntity(StrapDummyId, coordinates); @@ -292,16 +291,15 @@ namespace Content.IntegrationTests.Tests.Buckle buckle.TryUnbuckle(human, true); }); + + await pairTracker.CleanReturnAsync(); } [Test] public async Task ForceUnbuckleBuckleTest() { - var options = new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes - }; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; EntityUid human = default; EntityUid chair = default; @@ -312,8 +310,7 @@ namespace Content.IntegrationTests.Tests.Buckle var mapManager = IoCManager.Resolve(); var entityManager = IoCManager.Resolve(); - var grid = GetMainGrid(mapManager); - var coordinates = new EntityCoordinates(grid.GridEntityId, 0, 0); + var coordinates = PoolManager.GetMainEntityCoordinates(mapManager); human = entityManager.SpawnEntity(BuckleDummyId, coordinates); chair = entityManager.SpawnEntity(StrapDummyId, coordinates); @@ -331,7 +328,7 @@ namespace Content.IntegrationTests.Tests.Buckle entityManager.GetComponent(human).WorldPosition += (100, 0); }); - await WaitUntil(server, () => !buckle.Buckled, 10); + await PoolManager.WaitUntil(server, () => !buckle.Buckled, 10); Assert.False(buckle.Buckled); @@ -356,6 +353,7 @@ namespace Content.IntegrationTests.Tests.Buckle Assert.NotNull(buckle.BuckledTo); Assert.True(buckle.Buckled); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs b/Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs index 7229d49c7f..7e93741999 100644 --- a/Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs +++ b/Content.IntegrationTests/Tests/Chemistry/SolutionSystemTests.cs @@ -14,7 +14,7 @@ namespace Content.IntegrationTests.Tests.Chemistry; // reactions can change this assumption [TestFixture] [TestOf(typeof(SolutionContainerSystem))] -public sealed class SolutionSystemTests : ContentIntegrationTest +public sealed class SolutionSystemTests { private const string Prototypes = @" - type: entity @@ -25,22 +25,19 @@ public sealed class SolutionSystemTests : ContentIntegrationTest beaker: maxVol: 50 "; - [Test] public async Task TryAddTwoNonReactiveReagent() { - var options = new ServerContentIntegrationOption { ExtraPrototypes = Prototypes }; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var entityManager = server.ResolveDependency(); var mapManager = server.ResolveDependency(); - var coordinates = GetMainEntityCoordinates(mapManager); + var coordinates = PoolManager.GetMainEntityCoordinates(mapManager); EntityUid beaker; - server.Assert(() => + await server.WaitAssertion(() => { var oilQuantity = FixedPoint2.New(15); var waterQuantity = FixedPoint2.New(10); @@ -62,7 +59,7 @@ public sealed class SolutionSystemTests : ContentIntegrationTest Assert.That(oil, Is.EqualTo(oilQuantity)); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } // This test mimics current behavior @@ -70,18 +67,16 @@ public sealed class SolutionSystemTests : ContentIntegrationTest [Test] public async Task TryAddTooMuchNonReactiveReagent() { - var options = new ServerContentIntegrationOption { ExtraPrototypes = Prototypes }; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var entityManager = server.ResolveDependency(); var mapManager = server.ResolveDependency(); - var coordinates = GetMainEntityCoordinates(mapManager); + var coordinates = PoolManager.GetMainEntityCoordinates(mapManager); EntityUid beaker; - server.Assert(() => + await server.WaitAssertion(() => { var oilQuantity = FixedPoint2.New(1500); var waterQuantity = FixedPoint2.New(10); @@ -103,25 +98,23 @@ public sealed class SolutionSystemTests : ContentIntegrationTest Assert.That(oil, Is.EqualTo(FixedPoint2.Zero)); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } // Unlike TryAddSolution this adds and two solution without then splits leaving only threshold in original [Test] public async Task TryMixAndOverflowTooMuchReagent() { - var options = new ServerContentIntegrationOption { ExtraPrototypes = Prototypes }; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var entityManager = server.ResolveDependency(); var mapManager = server.ResolveDependency(); - var coordinates = GetMainEntityCoordinates(mapManager); + var coordinates = PoolManager.GetMainEntityCoordinates(mapManager); EntityUid beaker; - server.Assert(() => + await server.WaitAssertion(() => { int ratio = 9; int threshold = 20; @@ -152,25 +145,23 @@ public sealed class SolutionSystemTests : ContentIntegrationTest Assert.That(oilOverFlow, Is.EqualTo(oilQuantity - oilMix)); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } // TryMixAndOverflow will fail if Threshold larger than MaxVolume [Test] public async Task TryMixAndOverflowTooBigOverflow() { - var options = new ServerContentIntegrationOption { ExtraPrototypes = Prototypes }; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var entityManager = server.ResolveDependency(); var mapManager = server.ResolveDependency(); - var coordinates = GetMainEntityCoordinates(mapManager); + var coordinates = PoolManager.GetMainEntityCoordinates(mapManager); EntityUid beaker; - server.Assert(() => + await server.WaitAssertion(() => { int ratio = 9; int threshold = 60; @@ -190,6 +181,6 @@ public sealed class SolutionSystemTests : ContentIntegrationTest Is.False); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } diff --git a/Content.IntegrationTests/Tests/Chemistry/TryAllReactionsTest.cs b/Content.IntegrationTests/Tests/Chemistry/TryAllReactionsTest.cs index 510687ff31..ccd3013837 100644 --- a/Content.IntegrationTests/Tests/Chemistry/TryAllReactionsTest.cs +++ b/Content.IntegrationTests/Tests/Chemistry/TryAllReactionsTest.cs @@ -14,7 +14,7 @@ namespace Content.IntegrationTests.Tests.Chemistry { [TestFixture] [TestOf(typeof(ReactionPrototype))] - public sealed class TryAllReactionsTest : ContentIntegrationTest + public sealed class TryAllReactionsTest { private const string Prototypes = @" - type: entity @@ -24,19 +24,16 @@ namespace Content.IntegrationTests.Tests.Chemistry solutions: beaker: maxVol: 50"; - [Test] public async Task TryAllTest() { - var options = new ServerContentIntegrationOption{ExtraPrototypes = Prototypes}; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var entityManager = server.ResolveDependency(); var prototypeManager = server.ResolveDependency(); var mapManager = server.ResolveDependency(); - var coordinates = GetMainEntityCoordinates(mapManager); + var coordinates = PoolManager.GetMainEntityCoordinates(mapManager); foreach (var reactionPrototype in prototypeManager.EnumeratePrototypes()) { @@ -46,7 +43,7 @@ namespace Content.IntegrationTests.Tests.Chemistry EntityUid beaker; Solution component = null; - server.Assert(() => + await server.WaitAssertion(() => { beaker = entityManager.SpawnEntity("TestSolutionContainer", coordinates); Assert.That(EntitySystem.Get() @@ -63,7 +60,7 @@ namespace Content.IntegrationTests.Tests.Chemistry await server.WaitIdleAsync(); - server.Assert(() => + await server.WaitAssertion(() => { //you just got linq'd fool //(i'm sorry) @@ -78,8 +75,9 @@ namespace Content.IntegrationTests.Tests.Chemistry Assert.That(foundProductsMap.All(x => x.Value)); }); - } + } + await pairTracker.CleanReturnAsync(); } } diff --git a/Content.IntegrationTests/Tests/ClickableTest.cs b/Content.IntegrationTests/Tests/ClickableTest.cs index 250e347d3e..1b5bd2949e 100644 --- a/Content.IntegrationTests/Tests/ClickableTest.cs +++ b/Content.IntegrationTests/Tests/ClickableTest.cs @@ -4,37 +4,20 @@ using Content.Client.Clickable; using NUnit.Framework; using Robust.Client.Graphics; using Robust.Server.GameObjects; -using Robust.Shared; using Robust.Shared.GameObjects; using Robust.Shared.Map; namespace Content.IntegrationTests.Tests { [TestFixture] - public sealed class ClickableTest : ContentIntegrationTest + public sealed class ClickableTest { - private ClientIntegrationInstance _client; - private ServerIntegrationInstance _server; - private const double DirSouth = 0; private const double DirNorth = Math.PI; private const double DirEast = Math.PI / 2; private const double DirSouthEast = Math.PI / 4; private const double DirSouthEastJustShy = Math.PI / 4 - 0.1; - [OneTimeSetUp] - public async Task Setup() - { - (_client, _server) = await StartConnectedServerClientPair(serverOptions: new ServerContentIntegrationOption() - { - CVarOverrides = - { - [CVars.NetPVS.Name] = "false" - } - }); - } - - [Parallelizable(ParallelScope.None)] [Test] [TestCase("ClickTestRotatingCornerVisible", 0.25f, 0.25f, DirSouth, 1, ExpectedResult = true)] [TestCase("ClickTestRotatingCornerVisible", 0.35f, 0.5f, DirSouth, 2, ExpectedResult = true)] @@ -64,26 +47,29 @@ namespace Content.IntegrationTests.Tests [TestCase("ClickTestRotatingCornerInvisibleNoRot", 0.25f, 0.25f, DirSouthEastJustShy, 1, ExpectedResult = true)] public async Task Test(string prototype, float clickPosX, float clickPosY, double angle, float scale) { + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; + var client = pairTracker.Pair.Client; EntityUid entity = default; - var clientEntManager = _client.ResolveDependency(); - var serverEntManager = _server.ResolveDependency(); - var eyeManager = _client.ResolveDependency(); - var mapManager = _server.ResolveDependency(); + var clientEntManager = client.ResolveDependency(); + var serverEntManager = server.ResolveDependency(); + var eyeManager = client.ResolveDependency(); + var mapManager = server.ResolveDependency(); - await _server.WaitPost(() => + await server.WaitPost(() => { - var ent = serverEntManager.SpawnEntity(prototype, GetMainEntityCoordinates(mapManager)); + var ent = serverEntManager.SpawnEntity(prototype, PoolManager.GetMainEntityCoordinates(mapManager)); serverEntManager.GetComponent(ent).WorldRotation = angle; serverEntManager.GetComponent(ent).Scale = (scale, scale); entity = ent; }); // Let client sync up. - await RunTicksSync(_client, _server, 5); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); var hit = false; - await _client.WaitPost(() => + await client.WaitPost(() => { // these tests currently all assume player eye is 0 eyeManager.CurrentEye.Rotation = 0; @@ -94,11 +80,13 @@ namespace Content.IntegrationTests.Tests hit = clickable.CheckClick((clickPosX, clickPosY) + pos, out _, out _); }); - await _server.WaitPost(() => + await server.WaitPost(() => { serverEntManager.DeleteEntity(entity); }); + await pairTracker.CleanReturnAsync(); + return hit; } } diff --git a/Content.IntegrationTests/Tests/Commands/PardonCommand.cs b/Content.IntegrationTests/Tests/Commands/PardonCommand.cs index 66ea9d8b76..d7de02371d 100644 --- a/Content.IntegrationTests/Tests/Commands/PardonCommand.cs +++ b/Content.IntegrationTests/Tests/Commands/PardonCommand.cs @@ -10,16 +10,15 @@ namespace Content.IntegrationTests.Tests.Commands { [TestFixture] [TestOf(typeof(PardonCommand))] - public sealed class PardonCommand : ContentIntegrationTest + public sealed class PardonCommand { private static readonly TimeSpan MarginOfError = TimeSpan.FromMinutes(1); [Test] public async Task PardonTest() { - var (client, server) = await StartConnectedServerClientPair(); - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); + await using var pairTracker = await PoolManager.GetServerClient(new (){Destructive = true}); + var server = pairTracker.Pair.Server; var sPlayerManager = server.ResolveDependency(); var sConsole = server.ResolveDependency(); @@ -122,6 +121,7 @@ namespace Content.IntegrationTests.Tests.Commands // The list is still returned since that ignores pardons Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Commands/RejuvenateTest.cs b/Content.IntegrationTests/Tests/Commands/RejuvenateTest.cs index c915226608..0ba5827c59 100644 --- a/Content.IntegrationTests/Tests/Commands/RejuvenateTest.cs +++ b/Content.IntegrationTests/Tests/Commands/RejuvenateTest.cs @@ -14,7 +14,7 @@ namespace Content.IntegrationTests.Tests.Commands { [TestFixture] [TestOf(typeof(RejuvenateCommand))] - public sealed class RejuvenateTest : ContentIntegrationTest + public sealed class RejuvenateTest { private const string Prototypes = @" - type: entity @@ -33,8 +33,8 @@ namespace Content.IntegrationTests.Tests.Commands [Test] public async Task RejuvenateDeadTest() { - var options = new ServerIntegrationOptions{ExtraPrototypes = Prototypes}; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; await server.WaitAssertion(() => { @@ -78,6 +78,7 @@ namespace Content.IntegrationTests.Tests.Commands Assert.That(damageable.TotalDamage, Is.EqualTo(FixedPoint2.Zero)); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs b/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs index 7c72cd6361..852a589bca 100644 --- a/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs +++ b/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs @@ -12,33 +12,27 @@ namespace Content.IntegrationTests.Tests.Commands { [TestFixture] [TestOf(typeof(RestartRoundNowCommand))] - public sealed class RestartRoundNowTest : ContentIntegrationTest + public sealed class RestartRoundNowTest { [Test] [TestCase(true)] [TestCase(false)] public async Task RestartRoundAfterStart(bool lobbyEnabled) { - var (_, server) = await StartConnectedServerClientPair(serverOptions: new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.GameMap.Name] = "saltern" - } - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings(){Dirty = true}); + var server = pairTracker.Pair.Server; var configManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); var gameTicker = entityManager.EntitySysManager.GetEntitySystem(); - await server.WaitRunTicks(30); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); GameTick tickBeforeRestart = default; - server.Assert(() => + await server.WaitAssertion(() => { + Assert.That(configManager.GetCVar(CCVars.GameLobbyEnabled), Is.EqualTo(false)); configManager.SetCVar(CCVars.GameLobbyEnabled, lobbyEnabled); Assert.That(gameTicker.RunLevel, Is.EqualTo(GameRunLevel.InRound)); @@ -54,17 +48,17 @@ namespace Content.IntegrationTests.Tests.Commands } }); - await server.WaitIdleAsync(); - await server.WaitRunTicks(5); + await PoolManager.RunTicksSync(pairTracker.Pair, 15); - server.Assert(() => + await server.WaitAssertion(() => { var tickAfterRestart = entityManager.CurrentTick; Assert.That(tickBeforeRestart < tickAfterRestart); }); - await server.WaitRunTicks(60); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Construction/ConstructionActionValid.cs b/Content.IntegrationTests/Tests/Construction/ConstructionActionValid.cs index af961f15be..774b01fd80 100644 --- a/Content.IntegrationTests/Tests/Construction/ConstructionActionValid.cs +++ b/Content.IntegrationTests/Tests/Construction/ConstructionActionValid.cs @@ -9,7 +9,7 @@ using Robust.Shared.Prototypes; namespace Content.IntegrationTests.Tests.Construction { [TestFixture] - public sealed class ConstructionActionValid : ContentIntegrationTest + public sealed class ConstructionActionValid { private bool IsValid(IGraphAction action, IPrototypeManager protoMan, out string prototype) { @@ -49,9 +49,8 @@ namespace Content.IntegrationTests.Tests.Construction [Test] public async Task ConstructionGraphSpawnPrototypeValid() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var protoMan = server.ResolveDependency(); @@ -82,6 +81,7 @@ namespace Content.IntegrationTests.Tests.Construction } } } + await pairTracker.CleanReturnAsync(); Assert.That(valid, Is.True, $"One or more SpawnPrototype actions specified invalid entity prototypes!\n{message}"); } @@ -89,9 +89,8 @@ namespace Content.IntegrationTests.Tests.Construction [Test] public async Task ConstructionGraphNodeEntityPrototypeValid() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var protoMan = server.ResolveDependency(); @@ -108,6 +107,7 @@ namespace Content.IntegrationTests.Tests.Construction message.Append($"Invalid entity prototype \"{node.Entity}\" on node \"{node.Name}\" of graph \"{graph.ID}\"\n"); } } + await pairTracker.CleanReturnAsync(); Assert.That(valid, Is.True, $"One or more nodes specified invalid entity prototypes!\n{message}"); } @@ -115,9 +115,8 @@ namespace Content.IntegrationTests.Tests.Construction [Test] public async Task ConstructionGraphEdgeValid() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var protoMan = server.ResolveDependency(); @@ -139,6 +138,7 @@ namespace Content.IntegrationTests.Tests.Construction } Assert.That(valid, Is.True, $"One or more edges specified invalid node targets!\n{message}"); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Construction/ConstructionPrototypeTest.cs b/Content.IntegrationTests/Tests/Construction/ConstructionPrototypeTest.cs index 6599d2d5c8..2377b6abca 100644 --- a/Content.IntegrationTests/Tests/Construction/ConstructionPrototypeTest.cs +++ b/Content.IntegrationTests/Tests/Construction/ConstructionPrototypeTest.cs @@ -6,7 +6,7 @@ using Robust.Shared.Prototypes; namespace Content.IntegrationTests.Tests.Construction { [TestFixture] - public sealed class ConstructionPrototypeTest : ContentIntegrationTest + public sealed class ConstructionPrototypeTest { // discount linter for construction graphs // TODO: Create serialization validators for these? @@ -14,9 +14,8 @@ namespace Content.IntegrationTests.Tests.Construction [Test] public async Task TestStartIsValid() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var protoMan = server.ResolveDependency(); @@ -27,14 +26,14 @@ namespace Content.IntegrationTests.Tests.Construction Assert.That(graph.Nodes.ContainsKey(start), $"Found no startNode \"{start}\" on graph \"{graph.ID}\" for construction prototype \"{proto.ID}\"!"); } + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestTargetIsValid() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var protoMan = server.ResolveDependency(); @@ -45,14 +44,14 @@ namespace Content.IntegrationTests.Tests.Construction Assert.That(graph.Nodes.ContainsKey(target), $"Found no targetNode \"{target}\" on graph \"{graph.ID}\" for construction prototype \"{proto.ID}\"!"); } + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestStartReachesValidTarget() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var protoMan = server.ResolveDependency(); @@ -68,6 +67,7 @@ namespace Content.IntegrationTests.Tests.Construction Assert.That(protoMan.TryIndex(next.Entity, out EntityPrototype entity), $"The next node ({next.Name}) in the path from the start node ({start}) to the target node ({target}) specified an invalid entity prototype ({next.Entity})"); Assert.That(entity.Components.ContainsKey("Construction"), $"The next node ({next.Name}) in the path from the start node ({start}) to the target node ({target}) specified an entity prototype ({next.Entity}) without a ConstructionComponent."); } + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/ContainerOcclusionTest.cs b/Content.IntegrationTests/Tests/ContainerOcclusionTest.cs index c8d342f9e2..421cfae30a 100644 --- a/Content.IntegrationTests/Tests/ContainerOcclusionTest.cs +++ b/Content.IntegrationTests/Tests/ContainerOcclusionTest.cs @@ -3,8 +3,6 @@ using System.Threading.Tasks; using Content.Server.Storage.Components; using NUnit.Framework; using Robust.Client.GameObjects; -using Robust.Server.Player; -using Robust.Shared; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; @@ -12,9 +10,9 @@ using Robust.Shared.Maths; namespace Content.IntegrationTests.Tests { - public sealed class ContainerOcclusionTest : ContentIntegrationTest + public sealed class ContainerOcclusionTest { - private const string ExtraPrototypes = @" + private const string Prototypes = @" - type: entity id: ContainerOcclusionA components: @@ -35,53 +33,21 @@ namespace Content.IntegrationTests.Tests - type: PointLight "; - private async Task<(ClientIntegrationInstance c, ServerIntegrationInstance s)> Start() - { - var optsServer = new ServerIntegrationOptions - { - CVarOverrides = - { - {CVars.NetPVS.Name, "false"} - }, - ExtraPrototypes = ExtraPrototypes - }; - var optsClient = new ClientIntegrationOptions - { - - CVarOverrides = - { - {CVars.NetPVS.Name, "false"} - }, - ExtraPrototypes = ExtraPrototypes - }; - - var (c, s) = await StartConnectedServerDummyTickerClientPair(optsClient, optsServer); - - s.Post(() => - { - IoCManager.Resolve().ServerSessions.Single().JoinGame(); - - var mapMan = IoCManager.Resolve(); - - mapMan.CreateMap(new MapId(1)); - }); - - return (c, s); - } - [Test] public async Task TestA() { - var (c, s) = await Start(); - - await c.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ExtraPrototypes = Prototypes}); + var s = pairTracker.Pair.Server; + var c = pairTracker.Pair.Client; var cEntities = c.ResolveDependency(); EntityUid dummy = default; - s.Post(() => + var ent2 = s.ResolveDependency(); + await s.WaitPost(() => { - var pos = new MapCoordinates(Vector2.Zero, new MapId(1)); + var mapId = ent2.GetAllMapIds().Last(); + var pos = new MapCoordinates(Vector2.Zero, mapId); var ent = IoCManager.Resolve(); var container = ent.SpawnEntity("ContainerOcclusionA", pos); dummy = ent.SpawnEntity("ContainerOcclusionDummy", pos); @@ -89,9 +55,9 @@ namespace Content.IntegrationTests.Tests ent.GetComponent(container).Insert(dummy); }); - await RunTicksSync(c, s, 5); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - c.Assert(() => + await c.WaitAssertion(() => { var sprite = cEntities.GetComponent(dummy); var light = cEntities.GetComponent(dummy); @@ -99,22 +65,24 @@ namespace Content.IntegrationTests.Tests Assert.True(light.ContainerOccluded); }); - await Task.WhenAll(c.WaitIdleAsync(), s.WaitIdleAsync()); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestB() { - var (c, s) = await Start(); - - await c.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ExtraPrototypes = Prototypes}); + var s = pairTracker.Pair.Server; + var c = pairTracker.Pair.Client; var cEntities = c.ResolveDependency(); + var ent2 = s.ResolveDependency(); EntityUid dummy = default; - s.Post(() => + await s.WaitPost(() => { - var pos = new MapCoordinates(Vector2.Zero, new MapId(1)); + var mapId = ent2.GetAllMapIds().Last(); + var pos = new MapCoordinates(Vector2.Zero, mapId); var ent = IoCManager.Resolve(); var container = ent.SpawnEntity("ContainerOcclusionB", pos); dummy = ent.SpawnEntity("ContainerOcclusionDummy", pos); @@ -122,9 +90,9 @@ namespace Content.IntegrationTests.Tests ent.GetComponent(container).Insert(dummy); }); - await RunTicksSync(c, s, 5); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - c.Assert(() => + await c.WaitAssertion(() => { var sprite = cEntities.GetComponent(dummy); var light = cEntities.GetComponent(dummy); @@ -132,22 +100,24 @@ namespace Content.IntegrationTests.Tests Assert.False(light.ContainerOccluded); }); - await Task.WhenAll(c.WaitIdleAsync(), s.WaitIdleAsync()); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestAb() { - var (c, s) = await Start(); - - await c.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{ExtraPrototypes = Prototypes}); + var s = pairTracker.Pair.Server; + var c = pairTracker.Pair.Client; + var ent2 = s.ResolveDependency(); var cEntities = c.ResolveDependency(); EntityUid dummy = default; - s.Post(() => + await s.WaitPost(() => { - var pos = new MapCoordinates(Vector2.Zero, new MapId(1)); + var mapId = ent2.GetAllMapIds().Last(); + var pos = new MapCoordinates(Vector2.Zero, mapId); var ent = IoCManager.Resolve(); var containerA = ent.SpawnEntity("ContainerOcclusionA", pos); var containerB = ent.SpawnEntity("ContainerOcclusionB", pos); @@ -157,9 +127,9 @@ namespace Content.IntegrationTests.Tests ent.GetComponent(containerB).Insert(dummy); }); - await RunTicksSync(c, s, 5); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - c.Assert(() => + await c.WaitAssertion(() => { var sprite = cEntities.GetComponent(dummy); var light = cEntities.GetComponent(dummy); @@ -167,7 +137,7 @@ namespace Content.IntegrationTests.Tests Assert.True(light.ContainerOccluded); }); - await Task.WhenAll(c.WaitIdleAsync(), s.WaitIdleAsync()); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Damageable/DamageSpecifierTest.cs b/Content.IntegrationTests/Tests/Damageable/DamageSpecifierTest.cs index 55ee290875..67658d18ce 100644 --- a/Content.IntegrationTests/Tests/Damageable/DamageSpecifierTest.cs +++ b/Content.IntegrationTests/Tests/Damageable/DamageSpecifierTest.cs @@ -7,7 +7,7 @@ namespace Content.IntegrationTests.Tests.Damageable; [TestFixture] [TestOf(typeof(DamageSpecifier))] -public sealed class DamageSpecifierTest : ContentIntegrationTest +public sealed class DamageSpecifierTest { [Test] public void TestDamageSpecifierOperations() diff --git a/Content.IntegrationTests/Tests/Damageable/DamageableTest.cs b/Content.IntegrationTests/Tests/Damageable/DamageableTest.cs index 6cff665002..bbc759e61c 100644 --- a/Content.IntegrationTests/Tests/Damageable/DamageableTest.cs +++ b/Content.IntegrationTests/Tests/Damageable/DamageableTest.cs @@ -14,9 +14,9 @@ namespace Content.IntegrationTests.Tests.Damageable [TestFixture] [TestOf(typeof(DamageableComponent))] [TestOf(typeof(DamageableSystem))] - public sealed class DamageableTest : ContentIntegrationTest + public sealed class DamageableTest { - private const string Prototypes = @" + public const string Prototypes = @" # Define some damage groups - type: damageType id: TestDamage1 @@ -71,30 +71,17 @@ namespace Content.IntegrationTests.Tests.Damageable damageContainer: testDamageContainer "; - // public bool & function to determine whether dealing damage resulted in actual damage change - public bool DamageChanged = false; - public void DamageChangedListener(EntityUid _, DamageableComponent comp, DamageChangedEvent args) - { - DamageChanged = true; - } - [Test] public async Task TestDamageableComponents() { - var server = StartServerDummyTicker(new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var sEntityManager = server.ResolveDependency(); var sMapManager = server.ResolveDependency(); var sPrototypeManager = server.ResolveDependency(); var sEntitySystemManager = server.ResolveDependency(); - sEntityManager.EventBus.SubscribeLocalEvent(DamageChangedListener); - EntityUid sDamageableEntity = default; DamageableComponent sDamageableComponent = null; DamageableSystem sDamageableSystem = null; @@ -153,8 +140,7 @@ namespace Content.IntegrationTests.Tests.Damageable DamageSpecifier damage = new(group3, damageToDeal); sDamageableSystem.TryChangeDamage(uid, damage, true); - Assert.That(DamageChanged); - DamageChanged = false; + Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damageToDeal)); Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(damageToDeal)); foreach (var type in types) @@ -165,8 +151,7 @@ namespace Content.IntegrationTests.Tests.Damageable // Heal sDamageableSystem.TryChangeDamage(uid, -damage); - Assert.That(DamageChanged); - DamageChanged = false; + Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero)); Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(FixedPoint2.Zero)); foreach (var type in types) @@ -180,8 +165,7 @@ namespace Content.IntegrationTests.Tests.Damageable damageToDeal = FixedPoint2.New(types.Count() * 5 - 1); damage = new DamageSpecifier(group3, damageToDeal); sDamageableSystem.TryChangeDamage(uid, damage, true); - Assert.That(DamageChanged); - DamageChanged = false; + Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(damageToDeal)); Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(damageToDeal)); Assert.That(sDamageableComponent.Damage.DamageDict[type3a.ID], Is.EqualTo(damageToDeal / types.Count())); @@ -192,8 +176,6 @@ namespace Content.IntegrationTests.Tests.Damageable // Heal sDamageableSystem.TryChangeDamage(uid, -damage); - Assert.That(DamageChanged); - DamageChanged = false; Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero)); Assert.That(sDamageableComponent.DamagePerGroup[group3.ID], Is.EqualTo(FixedPoint2.Zero)); foreach (var type in types) @@ -206,7 +188,6 @@ namespace Content.IntegrationTests.Tests.Damageable Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero)); damage = new DamageSpecifier(group1, FixedPoint2.New(10)) + new DamageSpecifier(type2b, FixedPoint2.New(10)); sDamageableSystem.TryChangeDamage(uid, damage, true); - Assert.That(DamageChanged, Is.False); Assert.That(sDamageableComponent.DamagePerGroup.TryGetValue(group1.ID, out groupDamage), Is.False); Assert.That(sDamageableComponent.Damage.DamageDict.TryGetValue(type1.ID, out typeDamage), Is.False); Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero)); @@ -227,15 +208,13 @@ namespace Content.IntegrationTests.Tests.Damageable // Test Over-Healing sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, FixedPoint2.New(-100))); - Assert.That(DamageChanged); - DamageChanged = false; Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero)); // Test that if no health change occurred, returns false sDamageableSystem.TryChangeDamage(uid, new DamageSpecifier(group3, -100)); - Assert.That(DamageChanged, Is.False); Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(FixedPoint2.Zero)); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/DeleteInventoryTest.cs b/Content.IntegrationTests/Tests/DeleteInventoryTest.cs index 865c5544ae..37eaedfb65 100644 --- a/Content.IntegrationTests/Tests/DeleteInventoryTest.cs +++ b/Content.IntegrationTests/Tests/DeleteInventoryTest.cs @@ -11,14 +11,15 @@ using Robust.Shared.Map; namespace Content.IntegrationTests.Tests { [TestFixture] - public sealed class DeleteInventoryTest : ContentIntegrationTest + public sealed class DeleteInventoryTest { // Test that when deleting an entity with an InventoryComponent, // any equipped items also get deleted. [Test] public async Task Test() { - var server = StartServer(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; await server.WaitAssertion(() => { @@ -46,6 +47,7 @@ namespace Content.IntegrationTests.Tests // Assert that child item was also deleted. Assert.That(item.Deleted, Is.True); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Destructible/DestructibleDamageGroupTest.cs b/Content.IntegrationTests/Tests/Destructible/DestructibleDamageGroupTest.cs index 3189726b81..225dbec0c8 100644 --- a/Content.IntegrationTests/Tests/Destructible/DestructibleDamageGroupTest.cs +++ b/Content.IntegrationTests/Tests/Destructible/DestructibleDamageGroupTest.cs @@ -15,17 +15,13 @@ namespace Content.IntegrationTests.Tests.Destructible [TestFixture] [TestOf(typeof(DamageGroupTrigger))] [TestOf(typeof(AndTrigger))] - public sealed class DestructibleDamageGroupTest : ContentIntegrationTest + public sealed class DestructibleDamageGroupTest { [Test] public async Task AndTest() { - var server = StartServer(new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var sEntityManager = server.ResolveDependency(); var sMapManager = server.ResolveDependency(); @@ -39,8 +35,7 @@ namespace Content.IntegrationTests.Tests.Destructible await server.WaitPost(() => { - var gridId = GetMainGrid(sMapManager).GridEntityId; - var coordinates = new EntityCoordinates(gridId, 0, 0); + var coordinates = PoolManager.GetMainEntityCoordinates(sMapManager); sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleDamageGroupEntityId, coordinates); sDamageableComponent = IoCManager.Resolve().GetComponent(sDestructibleEntity); @@ -184,6 +179,7 @@ namespace Content.IntegrationTests.Tests.Destructible // No new thresholds reached as triggers once is set to true and it already triggered before Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Destructible/DestructibleDamageTypeTest.cs b/Content.IntegrationTests/Tests/Destructible/DestructibleDamageTypeTest.cs index 612021860f..d6db6980bc 100644 --- a/Content.IntegrationTests/Tests/Destructible/DestructibleDamageTypeTest.cs +++ b/Content.IntegrationTests/Tests/Destructible/DestructibleDamageTypeTest.cs @@ -14,17 +14,13 @@ namespace Content.IntegrationTests.Tests.Destructible [TestFixture] [TestOf(typeof(DamageTypeTrigger))] [TestOf(typeof(AndTrigger))] - public sealed class DestructibleDamageTypeTest : ContentIntegrationTest + public sealed class DestructibleDamageTypeTest { [Test] public async Task Test() { - var server = StartServer(new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var sEntityManager = server.ResolveDependency(); var sMapManager = server.ResolveDependency(); @@ -37,8 +33,7 @@ namespace Content.IntegrationTests.Tests.Destructible await server.WaitPost(() => { - var gridId = GetMainGrid(sMapManager).GridEntityId; - var coordinates = new EntityCoordinates(gridId, 0, 0); + var coordinates = PoolManager.GetMainEntityCoordinates(sMapManager); sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleDamageTypeEntityId, coordinates); sDamageableComponent = IoCManager.Resolve().GetComponent(sDestructibleEntity); @@ -180,6 +175,7 @@ namespace Content.IntegrationTests.Tests.Destructible // No new thresholds reached as triggers once is set to true and it already triggered before Assert.IsEmpty(sTestThresholdListenerSystem.ThresholdsReached); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Destructible/DestructibleDestructionTest.cs b/Content.IntegrationTests/Tests/Destructible/DestructibleDestructionTest.cs index 7a6eb33953..246d829e92 100644 --- a/Content.IntegrationTests/Tests/Destructible/DestructibleDestructionTest.cs +++ b/Content.IntegrationTests/Tests/Destructible/DestructibleDestructionTest.cs @@ -13,17 +13,13 @@ using static Content.IntegrationTests.Tests.Destructible.DestructibleTestPrototy namespace Content.IntegrationTests.Tests.Destructible { - public sealed class DestructibleDestructionTest : ContentIntegrationTest + public sealed class DestructibleDestructionTest { [Test] public async Task Test() { - var server = StartServer(new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var sEntityManager = server.ResolveDependency(); var sMapManager = server.ResolveDependency(); @@ -35,8 +31,7 @@ namespace Content.IntegrationTests.Tests.Destructible await server.WaitPost(() => { - var gridId = GetMainGrid(sMapManager).GridEntityId; - var coordinates = new EntityCoordinates(gridId, 0, 0); + var coordinates = PoolManager.GetMainEntityCoordinates(sMapManager); sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleDestructionEntityId, coordinates); sTestThresholdListenerSystem = sEntitySystemManager.GetEntitySystem(); @@ -87,6 +82,7 @@ namespace Content.IntegrationTests.Tests.Destructible Assert.That(found, Is.True); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Destructible/DestructibleThresholdActivationTest.cs b/Content.IntegrationTests/Tests/Destructible/DestructibleThresholdActivationTest.cs index 376464b625..cf1bffca48 100644 --- a/Content.IntegrationTests/Tests/Destructible/DestructibleThresholdActivationTest.cs +++ b/Content.IntegrationTests/Tests/Destructible/DestructibleThresholdActivationTest.cs @@ -19,17 +19,13 @@ namespace Content.IntegrationTests.Tests.Destructible [TestFixture] [TestOf(typeof(DestructibleComponent))] [TestOf(typeof(DamageThreshold))] - public sealed class DestructibleThresholdActivationTest : ContentIntegrationTest + public sealed class DestructibleThresholdActivationTest { [Test] public async Task Test() { - var server = StartServer(new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var sEntityManager = server.ResolveDependency(); var sMapManager = server.ResolveDependency(); @@ -44,8 +40,7 @@ namespace Content.IntegrationTests.Tests.Destructible await server.WaitPost(() => { - var gridId = GetMainGrid(sMapManager).GridEntityId; - var coordinates = new EntityCoordinates(gridId, 0, 0); + var coordinates = PoolManager.GetMainEntityCoordinates(sMapManager); sDestructibleEntity = sEntityManager.SpawnEntity(DestructibleEntityId, coordinates); sDamageableComponent = IoCManager.Resolve().GetComponent(sDestructibleEntity); @@ -268,6 +263,7 @@ namespace Content.IntegrationTests.Tests.Destructible // They shouldn't have been triggered by changing TriggersOnce Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/DeviceNetwork/DeviceNetworkTest.cs b/Content.IntegrationTests/Tests/DeviceNetwork/DeviceNetworkTest.cs index 4c5f6466d9..3627327292 100644 --- a/Content.IntegrationTests/Tests/DeviceNetwork/DeviceNetworkTest.cs +++ b/Content.IntegrationTests/Tests/DeviceNetwork/DeviceNetworkTest.cs @@ -13,7 +13,7 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork [TestOf(typeof(DeviceNetworkComponent))] [TestOf(typeof(WiredNetworkComponent))] [TestOf(typeof(WirelessNetworkComponent))] - public sealed class DeviceNetworkTest : ContentIntegrationTest + public sealed class DeviceNetworkTest { private const string Prototypes = @" - type: entity @@ -50,17 +50,8 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork [Test] public async Task NetworkDeviceSendAndReceive() { - var options = new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes, - ContentBeforeIoC = () => { - IoCManager.Resolve().LoadExtraSystemType(); - } - }; - - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); @@ -81,7 +72,7 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork ["testbool"] = true }; - server.Assert(() => { + await server.WaitAssertion(() => { mapManager.CreateNewMapEntity(MapId.Nullspace); device1 = entityManager.SpawnEntity("DummyNetworkDevice", MapCoordinates.Nullspace); @@ -104,25 +95,17 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork await server.WaitRunTicks(1); await server.WaitIdleAsync(); - server.Assert(() => { + await server.WaitAssertion(() => { CollectionAssert.AreEquivalent(deviceNetTestSystem.LastPayload, payload); }); + await pairTracker.CleanReturnAsync(); } [Test] public async Task WirelessNetworkDeviceSendAndReceive() { - var options = new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes, - ContentBeforeIoC = () => { - IoCManager.Resolve().LoadExtraSystemType(); - } - }; - - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); @@ -144,7 +127,7 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork ["testbool"] = true }; - server.Assert(() => { + await server.WaitAssertion(() => { mapManager.CreateNewMapEntity(MapId.Nullspace); device1 = entityManager.SpawnEntity("DummyWirelessNetworkDevice", MapCoordinates.Nullspace); @@ -168,7 +151,7 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork await server.WaitRunTicks(1); await server.WaitIdleAsync(); - server.Assert(() => { + await server.WaitAssertion(() => { CollectionAssert.AreEqual(deviceNetTestSystem.LastPayload, payload); payload = new NetworkPayload @@ -184,27 +167,18 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork await server.WaitRunTicks(1); await server.WaitIdleAsync(); - server.Assert(() => { + await server.WaitAssertion(() => { CollectionAssert.AreNotEqual(deviceNetTestSystem.LastPayload, payload); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task WiredNetworkDeviceSendAndReceive() { - var options = new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes, - ContentBeforeIoC = () => { - IoCManager.Resolve().LoadExtraSystemType(); - } - }; - - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); @@ -230,7 +204,7 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork await server.WaitRunTicks(1); await server.WaitIdleAsync(); - server.Assert(() => { + await server.WaitAssertion(() => { var map = mapManager.CreateNewMapEntity(MapId.Nullspace); grid = mapManager.CreateGrid(MapId.Nullspace); @@ -255,7 +229,7 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork await server.WaitRunTicks(1); await server.WaitIdleAsync(); - server.Assert(() => { + await server.WaitAssertion(() => { //CollectionAssert.AreNotEqual(deviceNetTestSystem.LastPayload, payload); entityManager.SpawnEntity("CableApcExtension", grid.MapToGrid(new MapCoordinates(new Robust.Shared.Maths.Vector2(0, 1), MapId.Nullspace))); @@ -266,11 +240,11 @@ namespace Content.IntegrationTests.Tests.DeviceNetwork await server.WaitRunTicks(1); await server.WaitIdleAsync(); - server.Assert(() => { + await server.WaitAssertion(() => { CollectionAssert.AreEqual(deviceNetTestSystem.LastPayload, payload); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs b/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs index a970dd23ae..114b90cfe0 100644 --- a/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs +++ b/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs @@ -18,7 +18,7 @@ namespace Content.IntegrationTests.Tests.Disposal [TestOf(typeof(DisposalHolderComponent))] [TestOf(typeof(DisposalEntryComponent))] [TestOf(typeof(DisposalUnitComponent))] - public sealed class DisposalUnitTest : ContentIntegrationTest + public sealed class DisposalUnitTest { [Reflect(false)] private sealed class DisposalUnitTestSystem : EntitySystem @@ -127,9 +127,8 @@ namespace Content.IntegrationTests.Tests.Disposal [Test] public async Task Test() { - var options = new ServerIntegrationOptions { ExtraPrototypes = Prototypes }; - var server = StartServer(options); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; EntityUid human = default!; EntityUid wrench = default!; @@ -143,7 +142,7 @@ namespace Content.IntegrationTests.Tests.Disposal await server.WaitAssertion(() => { // Spawn the entities - var coordinates = GetMainEntityCoordinates(mapManager); + var coordinates = PoolManager.GetMainEntityCoordinates(mapManager); human = entityManager.SpawnEntity("HumanDummy", coordinates); wrench = entityManager.SpawnEntity("WrenchDummy", coordinates); disposalUnit = entityManager.SpawnEntity("DisposalUnitDummy", coordinates); @@ -208,6 +207,7 @@ namespace Content.IntegrationTests.Tests.Disposal // Re-pressurizing Flush(unit, false); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/DoAfter/DoAfterServerTest.cs b/Content.IntegrationTests/Tests/DoAfter/DoAfterServerTest.cs index c1a4c76955..a4d3cf1f31 100644 --- a/Content.IntegrationTests/Tests/DoAfter/DoAfterServerTest.cs +++ b/Content.IntegrationTests/Tests/DoAfter/DoAfterServerTest.cs @@ -11,7 +11,7 @@ namespace Content.IntegrationTests.Tests.DoAfter { [TestFixture] [TestOf(typeof(DoAfterComponent))] - public sealed class DoAfterServerTest : ContentIntegrationTest + public sealed class DoAfterServerTest { private const string Prototypes = @" - type: entity @@ -25,11 +25,11 @@ namespace Content.IntegrationTests.Tests.DoAfter public async Task TestFinished() { Task task = null; - var options = new ServerIntegrationOptions{ExtraPrototypes = Prototypes}; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; // That it finishes successfully - server.Post(() => + await server.WaitPost(() => { var tickTime = 1.0f / IoCManager.Resolve().TickRate; var mapManager = IoCManager.Resolve(); @@ -43,16 +43,19 @@ namespace Content.IntegrationTests.Tests.DoAfter await server.WaitRunTicks(1); Assert.That(task.Result == DoAfterStatus.Finished); + + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestCancelled() { Task task = null; - var options = new ServerIntegrationOptions{ExtraPrototypes = Prototypes}; - var server = StartServer(options); - server.Post(() => + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + + await server.WaitPost(() => { var tickTime = 1.0f / IoCManager.Resolve().TickRate; var mapManager = IoCManager.Resolve(); @@ -67,6 +70,8 @@ namespace Content.IntegrationTests.Tests.DoAfter await server.WaitRunTicks(3); Assert.That(task.Result == DoAfterStatus.Cancelled, $"Result was {task.Result}"); + + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Doors/AirlockTest.cs b/Content.IntegrationTests/Tests/Doors/AirlockTest.cs index 0edfa925d5..e7c81b7333 100644 --- a/Content.IntegrationTests/Tests/Doors/AirlockTest.cs +++ b/Content.IntegrationTests/Tests/Doors/AirlockTest.cs @@ -12,7 +12,7 @@ namespace Content.IntegrationTests.Tests.Doors { [TestFixture] [TestOf(typeof(AirlockComponent))] - public sealed class AirlockTest : ContentIntegrationTest + public sealed class AirlockTest { private const string Prototypes = @" - type: entity @@ -48,10 +48,8 @@ namespace Content.IntegrationTests.Tests.Doors [Test] public async Task OpenCloseDestroyTest() { - var options = new ServerIntegrationOptions {ExtraPrototypes = Prototypes}; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); @@ -59,7 +57,7 @@ namespace Content.IntegrationTests.Tests.Doors EntityUid airlock = default; DoorComponent doorComponent = null; - server.Assert(() => + await server.WaitAssertion(() => { mapManager.CreateNewMapEntity(MapId.Nullspace); @@ -71,7 +69,7 @@ namespace Content.IntegrationTests.Tests.Doors await server.WaitIdleAsync(); - server.Assert(() => + await server.WaitAssertion(() => { EntitySystem.Get().StartOpening(airlock); Assert.That(doorComponent.State, Is.EqualTo(DoorState.Opening)); @@ -79,21 +77,21 @@ namespace Content.IntegrationTests.Tests.Doors await server.WaitIdleAsync(); - await WaitUntil(server, () => doorComponent.State == DoorState.Open); + await PoolManager.WaitUntil(server, () => doorComponent.State == DoorState.Open); Assert.That(doorComponent.State, Is.EqualTo(DoorState.Open)); - server.Assert(() => + await server.WaitAssertion(() => { EntitySystem.Get().TryClose((EntityUid) airlock); Assert.That(doorComponent.State, Is.EqualTo(DoorState.Closing)); }); - await WaitUntil(server, () => doorComponent.State == DoorState.Closed); + await PoolManager.WaitUntil(server, () => doorComponent.State == DoorState.Closed); Assert.That(doorComponent.State, Is.EqualTo(DoorState.Closed)); - server.Assert(() => + await server.WaitAssertion(() => { Assert.DoesNotThrow(() => { @@ -103,17 +101,14 @@ namespace Content.IntegrationTests.Tests.Doors server.RunTicks(5); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task AirlockBlockTest() { - var options = new ServerContentIntegrationOption - { - ExtraPrototypes = Prototypes - }; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; await server.WaitIdleAsync(); @@ -127,7 +122,7 @@ namespace Content.IntegrationTests.Tests.Doors var physicsDummyStartingX = -1; - server.Assert(() => + await server.WaitAssertion(() => { var mapId = mapManager.CreateMap(); @@ -151,7 +146,7 @@ namespace Content.IntegrationTests.Tests.Doors for (var i = 0; i < 240; i += 10) { // Keep the airlock awake so they collide - server.Post(() => entityManager.GetComponent(airlock).WakeBody()); + await server.WaitPost(() => entityManager.GetComponent(airlock).WakeBody()); await server.WaitRunTicks(10); await server.WaitIdleAsync(); @@ -165,6 +160,7 @@ namespace Content.IntegrationTests.Tests.Doors // Blocked by the airlock await server.WaitAssertion(() => Assert.That(Math.Abs(entityManager.GetComponent(physicsDummy).MapPosition.X - 1) > 0.01f)); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/DummyIconTest.cs b/Content.IntegrationTests/Tests/DummyIconTest.cs index 2cc97cbe7b..8cc9d0fa2e 100644 --- a/Content.IntegrationTests/Tests/DummyIconTest.cs +++ b/Content.IntegrationTests/Tests/DummyIconTest.cs @@ -9,16 +9,17 @@ using Robust.Shared.Prototypes; namespace Content.IntegrationTests.Tests { [TestFixture] - public sealed class DummyIconTest : ContentIntegrationTest + public sealed class DummyIconTest { [Test] public async Task Test() { - var (client, _) = await StartConnectedServerClientPair(new ClientContentIntegrationOption(){ Pool = false }, new ServerContentIntegrationOption() { Pool = false }); + await using var pairTracker = await PoolManager.GetServerClient(); + var client = pairTracker.Pair.Client; var prototypeManager = client.ResolveDependency(); var resourceCache = client.ResolveDependency(); - + await client.WaitRunTicks(5); await client.WaitAssertion(() => { foreach (var proto in prototypeManager.EnumeratePrototypes()) @@ -32,6 +33,8 @@ namespace Content.IntegrationTests.Tests proto.ID); } }); + await client.WaitRunTicks(5); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/EntityTest.cs b/Content.IntegrationTests/Tests/EntityTest.cs index 07e4fcb082..fe0614aaea 100644 --- a/Content.IntegrationTests/Tests/EntityTest.cs +++ b/Content.IntegrationTests/Tests/EntityTest.cs @@ -15,18 +15,13 @@ namespace Content.IntegrationTests.Tests { [TestFixture] [TestOf(typeof(EntityUid))] - public sealed class EntityTest : ContentIntegrationTest + public sealed class EntityTest { [Test] public async Task SpawnTest() { - var options = new ServerContentIntegrationOption() - { - CVarOverrides = {{CCVars.NPCMaxUpdates.Name, int.MaxValue.ToString()}} - }; - - var server = StartServer(options); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, Dirty = true}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entityMan = server.ResolveDependency(); @@ -38,7 +33,7 @@ namespace Content.IntegrationTests.Tests EntityUid testEntity; //Build up test environment - server.Post(() => + await server.WaitPost(() => { // Create a one tile grid to stave off the grid 0 monsters var mapId = mapManager.CreateMap(); @@ -56,7 +51,9 @@ namespace Content.IntegrationTests.Tests mapManager.DoMapInitialize(mapId); }); - server.Assert(() => + await server.WaitRunTicks(5); + + await server.WaitAssertion(() => { var testLocation = grid.ToCoordinates(); @@ -80,7 +77,7 @@ namespace Content.IntegrationTests.Tests { Logger.LogS(LogLevel.Debug, "EntityTest", $"Testing: {prototype.ID}"); testEntity = entityMan.SpawnEntity(prototype.ID, testLocation); - server.RunTicks(2); + server.RunTicks(1); if(!entityMan.Deleted(testEntity)) entityMan.DeleteEntity(testEntity); }, "Entity '{0}' threw an exception.", @@ -89,7 +86,7 @@ namespace Content.IntegrationTests.Tests }); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] @@ -110,12 +107,8 @@ namespace Content.IntegrationTests.Tests - type: entity id: AllComponentsOneToOneDeleteTestEntity"; - var server = StartServer(new ServerContentIntegrationOption - { - ExtraPrototypes = testEntity, - FailureLogLevel = LogLevel.Error - }); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = testEntity}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); @@ -124,7 +117,7 @@ namespace Content.IntegrationTests.Tests IMapGrid grid = default; - server.Post(() => + await server.WaitPost(() => { // Create a one tile grid to stave off the grid 0 monsters var mapId = mapManager.CreateMap(); @@ -142,7 +135,9 @@ namespace Content.IntegrationTests.Tests mapManager.DoMapInitialize(mapId); }); - server.Assert(() => + await server.WaitRunTicks(5); + + await server.WaitAssertion(() => { Assert.Multiple(() => { @@ -179,14 +174,12 @@ namespace Content.IntegrationTests.Tests }, "Component '{0}' threw an exception.", component.Name); - server.RunTicks(2); - entityManager.DeleteEntity(entity); } }); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] @@ -207,13 +200,8 @@ namespace Content.IntegrationTests.Tests - type: entity id: AllComponentsOneEntityDeleteTestEntity"; - var server = StartServer(new ServerContentIntegrationOption - { - ExtraPrototypes = testEntity, - FailureLogLevel = LogLevel.Error, - Pool = false - }); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = testEntity}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); @@ -222,7 +210,7 @@ namespace Content.IntegrationTests.Tests IMapGrid grid = default; - server.Post(() => + await server.WaitPost(() => { // Create a one tile grid to stave off the grid 0 monsters var mapId = mapManager.CreateMap(); @@ -237,6 +225,7 @@ namespace Content.IntegrationTests.Tests grid.SetTile(Vector2i.Zero, tile); mapManager.DoMapInitialize(mapId); }); + await server.WaitRunTicks(5); var distinctComponents = new List<(List components, List references)> { @@ -272,7 +261,7 @@ namespace Content.IntegrationTests.Tests // Sanity check Assert.That(distinctComponents, Is.Not.Empty); - server.Assert(() => + await server.WaitAssertion(() => { Assert.Multiple(() => { @@ -313,14 +302,12 @@ namespace Content.IntegrationTests.Tests }, "Component '{0}' threw an exception.", component.Name); } - - server.RunTicks(2); entityManager.DeleteEntity(entity); } }); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs b/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs index ca4914f322..7069fcc7f6 100644 --- a/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs +++ b/Content.IntegrationTests/Tests/Fluids/FluidSpillTest.cs @@ -15,7 +15,7 @@ namespace Content.IntegrationTests.Tests.Fluids; [TestFixture] [TestOf(typeof(FluidSpreaderSystem))] -public sealed class FluidSpill : ContentIntegrationTest +public sealed class FluidSpill { private static PuddleComponent? GetPuddle(IEntityManager entityManager, IMapGrid mapGrid, Vector2i pos) { @@ -46,9 +46,8 @@ public sealed class FluidSpill : ContentIntegrationTest [Test] public async Task SpillEvenlyTest() { - // --- Setup - var server = StartServer(); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); @@ -85,7 +84,7 @@ public sealed class FluidSpill : ContentIntegrationTest var sTimeToWait = (int) Math.Ceiling(2f * gameTiming.TickRate); await server.WaitRunTicks(sTimeToWait); - server.Assert(() => + await server.WaitAssertion(() => { var grid = mapManager.GetGrid(gridId); var puddle = GetPuddle(entityManager, grid, _origin); @@ -102,16 +101,15 @@ public sealed class FluidSpill : ContentIntegrationTest } }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task SpillSmallOverflowTest() { - // --- Setup - var server = StartServer(); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); @@ -147,9 +145,9 @@ public sealed class FluidSpill : ContentIntegrationTest }); var sTimeToWait = (int) Math.Ceiling(2f * gameTiming.TickRate); - await server.WaitRunTicks(sTimeToWait); + await PoolManager.RunTicksSync(pairTracker.Pair, sTimeToWait); - server.Assert(() => + await server.WaitAssertion(() => { var grid = mapManager.GetGrid(gridId); var puddle = GetPuddle(entityManager, grid, _origin); @@ -178,6 +176,6 @@ public sealed class FluidSpill : ContentIntegrationTest Assert.That(fullField, Is.EqualTo(1)); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } diff --git a/Content.IntegrationTests/Tests/Fluids/PuddleTest.cs b/Content.IntegrationTests/Tests/Fluids/PuddleTest.cs index 71fd46ed68..217954df0f 100644 --- a/Content.IntegrationTests/Tests/Fluids/PuddleTest.cs +++ b/Content.IntegrationTests/Tests/Fluids/PuddleTest.cs @@ -14,39 +14,39 @@ namespace Content.IntegrationTests.Tests.Fluids { [TestFixture] [TestOf(typeof(PuddleComponent))] - public sealed class PuddleTest : ContentIntegrationTest + public sealed class PuddleTest { [Test] public async Task TilePuddleTest() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entitySystemManager = server.ResolveDependency(); var spillSystem = entitySystemManager.GetEntitySystem(); - server.Assert(() => + await server.WaitAssertion(() => { var solution = new Solution("Water", FixedPoint2.New(20)); - var grid = GetMainGrid(mapManager); - var (x, y) = GetMainTile(grid).GridIndices; - var coordinates = new EntityCoordinates(grid.GridEntityId, x, y); + var tile = PoolManager.GetMainTile(mapManager); + var gridUid = tile.GridUid; + var (x, y) = tile.GridIndices; + var coordinates = new EntityCoordinates(gridUid, x, y); var puddle = spillSystem.SpillAt(solution, coordinates, "PuddleSmear"); Assert.NotNull(puddle); }); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task SpaceNoPuddleTest() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entitySystemManager = server.ResolveDependency(); @@ -55,9 +55,9 @@ namespace Content.IntegrationTests.Tests.Fluids IMapGrid grid = null; // Remove all tiles - server.Post(() => + await server.WaitPost(() => { - grid = GetMainGrid(mapManager); + grid = PoolManager.GetMainGrid(mapManager); foreach (var tile in grid.GetAllTiles()) { @@ -65,9 +65,9 @@ namespace Content.IntegrationTests.Tests.Fluids } }); - await server.WaitIdleAsync(); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - server.Assert(() => + await server.WaitAssertion(() => { var coordinates = grid.ToCoordinates(); var solution = new Solution("Water", FixedPoint2.New(20)); @@ -75,15 +75,14 @@ namespace Content.IntegrationTests.Tests.Fluids Assert.Null(puddle); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task PuddlePauseTest() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var sMapManager = server.ResolveDependency(); var sTileDefinitionManager = server.ResolveDependency(); @@ -154,8 +153,8 @@ namespace Content.IntegrationTests.Tests.Fluids }); // Wait enough time for it to evaporate if it was unpaused - var sTimeToWait = (5 + (int)Math.Ceiling(amount * evaporateTime * sGameTiming.TickRate)); - await server.WaitRunTicks(sTimeToWait); + var sTimeToWait = 5 + (int)Math.Ceiling(amount * evaporateTime * sGameTiming.TickRate); + await PoolManager.RunTicksSync(pairTracker.Pair, sTimeToWait); // No evaporation due to being paused await server.WaitAssertion(() => @@ -181,7 +180,7 @@ namespace Content.IntegrationTests.Tests.Fluids }); // Wait enough time for it to evaporate - await server.WaitRunTicks(sTimeToWait); + await PoolManager.RunTicksSync(pairTracker.Pair, sTimeToWait); // Puddle evaporation should have ticked await server.WaitAssertion(() => @@ -189,6 +188,7 @@ namespace Content.IntegrationTests.Tests.Fluids // Check that puddle has been deleted Assert.True(puddle.Deleted); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/FollowerSystemTest.cs b/Content.IntegrationTests/Tests/FollowerSystemTest.cs index fa8c1968d0..b1449caf89 100644 --- a/Content.IntegrationTests/Tests/FollowerSystemTest.cs +++ b/Content.IntegrationTests/Tests/FollowerSystemTest.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using System.Threading.Tasks; using Content.Shared.Follower; @@ -10,7 +11,7 @@ using Robust.Shared.Map; namespace Content.IntegrationTests.Tests; [TestFixture, TestOf(typeof(FollowerSystem))] -public sealed class FollowerSystemTest : ContentIntegrationTest +public sealed class FollowerSystemTest { /// /// This test ensures that deleting a map while an entity follows another doesn't throw any exceptions. @@ -18,8 +19,8 @@ public sealed class FollowerSystemTest : ContentIntegrationTest [Test] public async Task FollowerMapDeleteTest() { - var server = StartServerDummyTicker(); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new (){NoClient = true}); + var server = pairTracker.Pair.Server; await server.WaitPost(() => { @@ -59,5 +60,6 @@ public sealed class FollowerSystemTest : ContentIntegrationTest entMan.DeleteEntity(ent); } }); + await pairTracker.CleanReturnAsync(); } } diff --git a/Content.IntegrationTests/Tests/GameObjects/Components/ActionBlocking/HandCuffTest.cs b/Content.IntegrationTests/Tests/GameObjects/Components/ActionBlocking/HandCuffTest.cs index 7c1ca0336a..2e62801318 100644 --- a/Content.IntegrationTests/Tests/GameObjects/Components/ActionBlocking/HandCuffTest.cs +++ b/Content.IntegrationTests/Tests/GameObjects/Components/ActionBlocking/HandCuffTest.cs @@ -16,7 +16,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking [TestFixture] [TestOf(typeof(CuffableComponent))] [TestOf(typeof(HandcuffComponent))] - public sealed class HandCuffTest : ContentIntegrationTest + public sealed class HandCuffTest { private const string Prototypes = @" - type: entity @@ -39,8 +39,8 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking [Test] public async Task Test() { - var options = new ServerIntegrationOptions{ExtraPrototypes = Prototypes}; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; EntityUid human; EntityUid otherHuman; @@ -49,7 +49,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking CuffableComponent cuffed; HandsComponent hands; - server.Assert(() => + await server.WaitAssertion(() => { var mapManager = IoCManager.Resolve(); var mapId = mapManager.CreateMap(); @@ -89,7 +89,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.ActionBlocking }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } private void AddHand(EntityUid to) diff --git a/Content.IntegrationTests/Tests/GameObjects/Components/EntityPrototypeComponentsTest.cs b/Content.IntegrationTests/Tests/GameObjects/Components/EntityPrototypeComponentsTest.cs index db3eaa9f2f..f50055774d 100644 --- a/Content.IntegrationTests/Tests/GameObjects/Components/EntityPrototypeComponentsTest.cs +++ b/Content.IntegrationTests/Tests/GameObjects/Components/EntityPrototypeComponentsTest.cs @@ -13,14 +13,14 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components { [TestFixture] [TestOf(typeof(Server.Entry.IgnoredComponents))] - public sealed class EntityPrototypeComponentsTest : ContentIntegrationTest + public sealed class EntityPrototypeComponentsTest { [Test] public async Task PrototypesHaveKnownComponents() { - var (client, server) = await StartConnectedServerDummyTickerClientPair(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; + var client = pairTracker.Pair.Client; var sResourceManager = server.ResolveDependency(); var prototypePath = new ResourcePath("/Prototypes/"); @@ -95,6 +95,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components if (unknownComponentsClient.Count + unknownComponentsServer.Count == 0) { + await pairTracker.CleanReturnAsync(); Assert.Pass($"Validated {entitiesValidated} entities with {componentsValidated} components in {paths.Length} files."); return; } @@ -119,7 +120,9 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components [Test] public async Task IgnoredComponentsExistInTheCorrectPlaces() { - var (client, server) = await StartConnectedServerClientPair(); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; + var client = pairTracker.Pair.Client; var serverComponents = server.ResolveDependency(); var ignoredServerNames = Server.Entry.IgnoredComponents.List; var clientComponents = client.ResolveDependency(); @@ -137,6 +140,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components } } Assert.IsEmpty(failureMessages); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/GameObjects/Components/Mobs/AlertsComponentTests.cs b/Content.IntegrationTests/Tests/GameObjects/Components/Mobs/AlertsComponentTests.cs index 4a44baabe9..73c531ea24 100644 --- a/Content.IntegrationTests/Tests/GameObjects/Components/Mobs/AlertsComponentTests.cs +++ b/Content.IntegrationTests/Tests/GameObjects/Components/Mobs/AlertsComponentTests.cs @@ -12,15 +12,14 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs { [TestFixture] [TestOf(typeof(AlertsComponent))] - public sealed class AlertsComponentTests : ContentIntegrationTest + public sealed class AlertsComponentTests { [Test] public async Task AlertsTest() { - var (client, server) = await StartConnectedServerClientPair(); - - await server.WaitIdleAsync(); - await client.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; + var client = pairTracker.Pair.Client; var serverPlayerManager = server.ResolveDependency(); var alertsSystem = server.ResolveDependency().GetEntitySystem(); @@ -39,7 +38,6 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs await server.WaitRunTicks(5); await client.WaitRunTicks(5); - var clientPlayerMgr = client.ResolveDependency(); var clientUIMgr = client.ResolveDependency(); await client.WaitAssertion(() => @@ -74,8 +72,8 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs alertsSystem.ClearAlert(alertsComponent.Owner, AlertType.Debug1); }); - await server.WaitRunTicks(5); - await client.WaitRunTicks(5); + + await PoolManager.RunTicksSync(pairTracker.Pair, 5); await client.WaitAssertion(() => { @@ -99,6 +97,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs var expectedIDs = new [] {AlertType.HumanHealth, AlertType.Debug2}; Assert.That(alertIDs, Is.SupersetOf(expectedIDs)); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/GameObjects/Components/Movement/ClimbUnitTest.cs b/Content.IntegrationTests/Tests/GameObjects/Components/Movement/ClimbUnitTest.cs index 25aae07b74..55db8be0b4 100644 --- a/Content.IntegrationTests/Tests/GameObjects/Components/Movement/ClimbUnitTest.cs +++ b/Content.IntegrationTests/Tests/GameObjects/Components/Movement/ClimbUnitTest.cs @@ -6,15 +6,13 @@ using NUnit.Framework; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; -using Robust.Shared.Physics; -using Content.Server.Climbing; namespace Content.IntegrationTests.Tests.GameObjects.Components.Movement { [TestFixture] [TestOf(typeof(ClimbableComponent))] [TestOf(typeof(ClimbingComponent))] - public sealed class ClimbUnitTest : ContentIntegrationTest + public sealed class ClimbUnitTest { private const string Prototypes = @" - type: entity @@ -35,14 +33,14 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Movement [Test] public async Task Test() { - var options = new ServerIntegrationOptions{ExtraPrototypes = Prototypes}; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; EntityUid human; EntityUid table; ClimbingComponent climbing; - server.Assert(() => + await server.WaitAssertion(() => { var mapManager = IoCManager.Resolve(); mapManager.CreateNewMapEntity(MapId.Nullspace); @@ -69,7 +67,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Movement // climbing.IsClimbing = false; }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/GameRules/RuleMaxTimeRestartTest.cs b/Content.IntegrationTests/Tests/GameRules/RuleMaxTimeRestartTest.cs index b564749c23..4b23af60b2 100644 --- a/Content.IntegrationTests/Tests/GameRules/RuleMaxTimeRestartTest.cs +++ b/Content.IntegrationTests/Tests/GameRules/RuleMaxTimeRestartTest.cs @@ -1,8 +1,11 @@ using System; using System.Threading.Tasks; using Content.Server.GameTicking; +using Content.Server.GameTicking.Commands; using Content.Server.GameTicking.Rules; +using Content.Shared.CCVar; using NUnit.Framework; +using Robust.Shared.Configuration; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Prototypes; @@ -12,23 +15,22 @@ namespace Content.IntegrationTests.Tests.GameRules { [TestFixture] [TestOf(typeof(MaxTimeRestartRuleSystem))] - public sealed class RuleMaxTimeRestartTest : ContentIntegrationTest + public sealed class RuleMaxTimeRestartTest { [Test] public async Task RestartTest() { - var options = new ServerContentIntegrationOption - { - CVarOverrides = - { - ["game.lobbyenabled"] = "true", - ["game.dummyticker"] = "false", - ["game.defaultpreset"] = "", // No preset. - } - }; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; + + var configManager = server.ResolveDependency(); + await server.WaitPost(() => + { + configManager.SetCVar(CCVars.GameLobbyEnabled, true); + var command = new RestartRoundNowCommand(); + command.Execute(null, string.Empty, Array.Empty()); + }); - await server.WaitIdleAsync(); var sGameTicker = server.ResolveDependency().GetEntitySystem(); var maxTimeMaxTimeRestartRuleSystem = server.ResolveDependency().GetEntitySystem(); @@ -50,7 +52,7 @@ namespace Content.IntegrationTests.Tests.GameRules }); var ticks = sGameTiming.TickRate * (int) Math.Ceiling(maxTimeMaxTimeRestartRuleSystem.RoundMaxTime.TotalSeconds * 1.1f); - await server.WaitRunTicks(ticks); + await PoolManager.RunTicksSync(pairTracker.Pair, ticks); await server.WaitAssertion(() => { @@ -58,12 +60,22 @@ namespace Content.IntegrationTests.Tests.GameRules }); ticks = sGameTiming.TickRate * (int) Math.Ceiling(maxTimeMaxTimeRestartRuleSystem.RoundEndDelay.TotalSeconds * 1.1f); - await server.WaitRunTicks(ticks); + await PoolManager.RunTicksSync(pairTracker.Pair, ticks); await server.WaitAssertion(() => { Assert.That(sGameTicker.RunLevel, Is.EqualTo(GameRunLevel.PreRoundLobby)); }); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); + await server.WaitPost(() => + { + configManager.SetCVar(CCVars.GameLobbyEnabled, false); + var command = new RestartRoundNowCommand(); + command.Execute(null, string.Empty, Array.Empty()); + }); + await PoolManager.RunTicksSync(pairTracker.Pair, 30); + + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs b/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs index ad92fbe06d..9ff9c8ed90 100644 --- a/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs +++ b/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs @@ -12,7 +12,7 @@ namespace Content.IntegrationTests.Tests.Gravity [TestFixture] [TestOf(typeof(WeightlessSystem))] [TestOf(typeof(GravityGeneratorComponent))] - public sealed class WeightlessStatusTests : ContentIntegrationTest + public sealed class WeightlessStatusTests { private const string Prototypes = @" - type: entity @@ -34,10 +34,8 @@ namespace Content.IntegrationTests.Tests.Gravity [Test] public async Task WeightlessStatusTest() { - var options = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes}; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var mapManager = server.ResolveDependency(); var entityManager = server.ResolveDependency(); @@ -47,45 +45,44 @@ namespace Content.IntegrationTests.Tests.Gravity await server.WaitAssertion(() => { - var grid = GetMainGrid(mapManager); - var coordinates = grid.ToCoordinates(); + var coordinates = PoolManager.GetMainEntityCoordinates(mapManager); human = entityManager.SpawnEntity("HumanDummy", coordinates); Assert.True(entityManager.TryGetComponent(human, out AlertsComponent alerts)); }); // Let WeightlessSystem and GravitySystem tick - await server.WaitRunTicks(1); - + await PoolManager.RunTicksSync(pairTracker.Pair, 10); + var generatorUid = EntityUid.Invalid; await server.WaitAssertion(() => { // No gravity without a gravity generator Assert.True(alertsSystem.IsShowingAlert(human, AlertType.Weightless)); - entityManager.SpawnEntity("GravityGeneratorDummy", entityManager.GetComponent(human).Coordinates); + generatorUid = entityManager.SpawnEntity("GravityGeneratorDummy", entityManager.GetComponent(human).Coordinates); }); // Let WeightlessSystem and GravitySystem tick - await server.WaitRunTicks(1); + await PoolManager.RunTicksSync(pairTracker.Pair, 10); await server.WaitAssertion(() => { Assert.False(alertsSystem.IsShowingAlert(human, AlertType.Weightless)); - // TODO: Re-add gravity generator breaking when Vera is done with construction stuff. - /* - // Disable the gravity generator - var args = new BreakageEventArgs {Owner = human}; - // gravityGenerator.OnBreak(args); - */ + // This should kill gravity + entityManager.DeleteEntity(generatorUid); }); - /*await server.WaitRunTicks(1); + await PoolManager.RunTicksSync(pairTracker.Pair, 10); await server.WaitAssertion(() => { - Assert.True(alerts.IsShowingAlert(AlertType.Weightless)); - });*/ + Assert.True(alertsSystem.IsShowingAlert(human, AlertType.Weightless)); + }); + + await PoolManager.RunTicksSync(pairTracker.Pair, 10); + + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/GravityGridTest.cs b/Content.IntegrationTests/Tests/GravityGridTest.cs index 3ad799beae..53c7ae2ca8 100644 --- a/Content.IntegrationTests/Tests/GravityGridTest.cs +++ b/Content.IntegrationTests/Tests/GravityGridTest.cs @@ -14,7 +14,7 @@ namespace Content.IntegrationTests.Tests /// making sure that gravity is applied to the correct grids. [TestFixture] [TestOf(typeof(GravityGeneratorComponent))] - public sealed class GravityGridTest : ContentIntegrationTest + public sealed class GravityGridTest { private const string Prototypes = @" - type: entity @@ -30,10 +30,8 @@ namespace Content.IntegrationTests.Tests [Test] public async Task Test() { - var options = new ServerIntegrationOptions{ExtraPrototypes = Prototypes}; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; EntityUid generator = default; var entityMan = server.ResolveDependency(); @@ -42,11 +40,11 @@ namespace Content.IntegrationTests.Tests IMapGrid grid2 = null; // Create grids - server.Assert(() => + await server.WaitAssertion(() => { var mapMan = IoCManager.Resolve(); - var mapId = GetMainMapId(mapMan); + var mapId = PoolManager.GetMainGrid(mapMan).ParentMapId; grid1 = mapMan.CreateGrid(mapId); grid2 = mapMan.CreateGrid(mapId); @@ -57,9 +55,10 @@ namespace Content.IntegrationTests.Tests var powerComponent = entityMan.GetComponent(generator); powerComponent.NeedsPower = false; }); - server.RunTicks(1); - server.Assert(() => + await server.WaitRunTicks(5); + + await server.WaitAssertion(() => { var generatorComponent = entityMan.GetComponent(generator); var powerComponent = entityMan.GetComponent(generator); @@ -76,8 +75,10 @@ namespace Content.IntegrationTests.Tests // Charge rate is ridiculously high so it finishes in one tick. powerComponent.NeedsPower = true; }); - server.RunTicks(1); - server.Assert(() => + + await server.WaitRunTicks(5); + + await server.WaitAssertion(() => { var generatorComponent = entityMan.GetComponent(generator); @@ -88,7 +89,7 @@ namespace Content.IntegrationTests.Tests Assert.That(entityMan.GetComponent(grid2Entity).Enabled, Is.False); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/HumanInventoryUniformSlotsTest.cs b/Content.IntegrationTests/Tests/HumanInventoryUniformSlotsTest.cs index b06f9364b7..4ebb5cd38c 100644 --- a/Content.IntegrationTests/Tests/HumanInventoryUniformSlotsTest.cs +++ b/Content.IntegrationTests/Tests/HumanInventoryUniformSlotsTest.cs @@ -11,7 +11,7 @@ namespace Content.IntegrationTests.Tests // i.e. the interaction between uniforms and the pocket/ID slots. // and also how big items don't fit in pockets. [TestFixture] - public sealed class HumanInventoryUniformSlotsTest : ContentIntegrationTest + public sealed class HumanInventoryUniformSlotsTest { private const string Prototypes = @" - type: entity @@ -56,8 +56,8 @@ namespace Content.IntegrationTests.Tests [Test] public async Task Test() { - var options = new ServerIntegrationOptions{ExtraPrototypes = Prototypes}; - var server = StartServer(options); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; EntityUid human = default; EntityUid uniform = default; @@ -66,7 +66,7 @@ namespace Content.IntegrationTests.Tests InventorySystem invSystem = default!; - server.Assert(() => + await server.WaitAssertion(() => { invSystem = IoCManager.Resolve().GetEntitySystem(); var mapMan = IoCManager.Resolve(); @@ -102,9 +102,9 @@ namespace Content.IntegrationTests.Tests Assert.That(invSystem.TryUnequip(human, "jumpsuit")); }); - server.RunTicks(2); + await server.WaitRunTicks(2); - server.Assert(() => + await server.WaitAssertion(() => { // Items have been dropped! Assert.That(IsDescendant(uniform, human), Is.False); @@ -117,7 +117,7 @@ namespace Content.IntegrationTests.Tests Assert.That(!invSystem.TryGetSlotEntity(human, "pocket1", out _)); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } private static bool IsDescendant(EntityUid descendant, EntityUid parent) diff --git a/Content.IntegrationTests/Tests/Interaction/Click/InteractionSystemTests.cs b/Content.IntegrationTests/Tests/Interaction/Click/InteractionSystemTests.cs index 316a859e4a..e216f7cce8 100644 --- a/Content.IntegrationTests/Tests/Interaction/Click/InteractionSystemTests.cs +++ b/Content.IntegrationTests/Tests/Interaction/Click/InteractionSystemTests.cs @@ -19,9 +19,9 @@ namespace Content.IntegrationTests.Tests.Interaction.Click { [TestFixture] [TestOf(typeof(InteractionSystem))] - public sealed class InteractionSystemTests : ContentIntegrationTest + public sealed class InteractionSystemTests { - const string PROTOTYPES = @" + private const string Prototypes = @" - type: entity id: DummyDebugWall components: @@ -41,15 +41,8 @@ namespace Content.IntegrationTests.Tests.Interaction.Click [Test] public async Task InteractionTest() { - var server = StartServer(new ServerContentIntegrationOption - { - ContentBeforeIoC = () => - { - IoCManager.Resolve().LoadExtraSystemType(); - } - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); @@ -58,7 +51,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click var mapId = MapId.Nullspace; var coords = MapCoordinates.Nullspace; - server.Assert(() => + await server.WaitAssertion(() => { mapId = mapManager.CreateMap(); coords = new MapCoordinates(Vector2.Zero, mapId); @@ -69,7 +62,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click EntityUid target = default; EntityUid item = default; - server.Assert(() => + await server.WaitAssertion(() => { user = sEntities.SpawnEntity(null, coords); user.EnsureComponent(); @@ -88,7 +81,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click var attack = false; var interactUsing = false; var interactHand = false; - server.Assert(() => + await server.WaitAssertion(() => { testInteractionSystem.AttackEvent = (_, _, ev) => { Assert.That(ev.Target, Is.EqualTo(target)); attack = true; }; testInteractionSystem.InteractUsingEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactUsing = true; }; @@ -106,22 +99,14 @@ namespace Content.IntegrationTests.Tests.Interaction.Click Assert.That(interactUsing); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task InteractionObstructionTest() { - var server = StartServer(new ServerContentIntegrationOption - { - ContentBeforeIoC = () => - { - IoCManager.Resolve().LoadExtraSystemType(); - }, - ExtraPrototypes = PROTOTYPES - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); @@ -130,7 +115,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click var mapId = MapId.Nullspace; var coords = MapCoordinates.Nullspace; - server.Assert(() => + await server.WaitAssertion(() => { mapId = mapManager.CreateMap(); coords = new MapCoordinates(Vector2.Zero, mapId); @@ -142,7 +127,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click EntityUid item = default; EntityUid wall = default; - server.Assert(() => + await server.WaitAssertion(() => { user = sEntities.SpawnEntity(null, coords); user.EnsureComponent(); @@ -162,7 +147,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click var attack = false; var interactUsing = false; var interactHand = false; - server.Assert(() => + await server.WaitAssertion(() => { testInteractionSystem.AttackEvent = (_, _, ev) => { Assert.That(ev.Target, Is.EqualTo(target)); attack = true; }; testInteractionSystem.InteractUsingEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactUsing = true; }; @@ -180,21 +165,14 @@ namespace Content.IntegrationTests.Tests.Interaction.Click Assert.That(interactUsing, Is.False); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task InteractionInRangeTest() { - var server = StartServer(new ServerContentIntegrationOption - { - ContentBeforeIoC = () => - { - IoCManager.Resolve().LoadExtraSystemType(); - } - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); @@ -203,7 +181,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click var mapId = MapId.Nullspace; var coords = MapCoordinates.Nullspace; - server.Assert(() => + await server.WaitAssertion(() => { mapId = mapManager.CreateMap(); coords = new MapCoordinates(Vector2.Zero, mapId); @@ -214,7 +192,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click EntityUid target = default; EntityUid item = default; - server.Assert(() => + await server.WaitAssertion(() => { user = sEntities.SpawnEntity(null, coords); user.EnsureComponent(); @@ -233,7 +211,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click var attack = false; var interactUsing = false; var interactHand = false; - server.Assert(() => + await server.WaitAssertion(() => { testInteractionSystem.AttackEvent = (_, _, ev) => { Assert.That(ev.Target, Is.EqualTo(target)); attack = true; }; testInteractionSystem.InteractUsingEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactUsing = true; }; @@ -251,22 +229,15 @@ namespace Content.IntegrationTests.Tests.Interaction.Click Assert.That(interactUsing); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task InteractionOutOfRangeTest() { - var server = StartServer(new ServerContentIntegrationOption - { - ContentBeforeIoC = () => - { - IoCManager.Resolve().LoadExtraSystemType(); - } - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); @@ -275,7 +246,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click var mapId = MapId.Nullspace; var coords = MapCoordinates.Nullspace; - server.Assert(() => + await server.WaitAssertion(() => { mapId = mapManager.CreateMap(); coords = new MapCoordinates(Vector2.Zero, mapId); @@ -286,7 +257,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click EntityUid target = default; EntityUid item = default; - server.Assert(() => + await server.WaitAssertion(() => { user = sEntities.SpawnEntity(null, coords); user.EnsureComponent(); @@ -305,7 +276,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click var attack = false; var interactUsing = false; var interactHand = false; - server.Assert(() => + await server.WaitAssertion(() => { testInteractionSystem.AttackEvent = (_, _, ev) => { Assert.That(ev.Target, Is.EqualTo(target)); attack = true; }; testInteractionSystem.InteractUsingEvent = (ev) => { Assert.That(ev.Target, Is.EqualTo(target)); interactUsing = true; }; @@ -323,22 +294,14 @@ namespace Content.IntegrationTests.Tests.Interaction.Click Assert.That(interactUsing, Is.False); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task InsideContainerInteractionBlockTest() { - var server = StartServer(new ServerContentIntegrationOption - { - ContentBeforeIoC = () => - { - IoCManager.Resolve().LoadExtraSystemType(); - }, - FailureLogLevel = Robust.Shared.Log.LogLevel.Error - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); @@ -347,7 +310,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click var mapId = MapId.Nullspace; var coords = MapCoordinates.Nullspace; - server.Assert(() => + await server.WaitAssertion(() => { mapId = mapManager.CreateMap(); coords = new MapCoordinates(Vector2.Zero, mapId); @@ -360,7 +323,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click EntityUid containerEntity = default; IContainer container = null; - server.Assert(() => + await server.WaitAssertion(() => { user = sEntities.SpawnEntity(null, coords); user.EnsureComponent(); @@ -383,7 +346,7 @@ namespace Content.IntegrationTests.Tests.Interaction.Click var attack = false; var interactUsing = false; var interactHand = false; - server.Assert(() => + await server.WaitAssertion(() => { Assert.That(container.Insert(user)); Assert.That(sEntities.GetComponent(user).Parent.Owner, Is.EqualTo(containerEntity)); @@ -413,11 +376,11 @@ namespace Content.IntegrationTests.Tests.Interaction.Click Assert.That(interactUsing, Is.True); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Reflect(false)] - private sealed class TestInteractionSystem : EntitySystem + public sealed class TestInteractionSystem : EntitySystem { public ComponentEventHandler? AttackEvent; public EntityEventHandler? InteractUsingEvent; diff --git a/Content.IntegrationTests/Tests/Interaction/InRangeUnobstructed.cs b/Content.IntegrationTests/Tests/Interaction/InRangeUnobstructed.cs index 449e58a128..e3a3befb8a 100644 --- a/Content.IntegrationTests/Tests/Interaction/InRangeUnobstructed.cs +++ b/Content.IntegrationTests/Tests/Interaction/InRangeUnobstructed.cs @@ -10,7 +10,7 @@ namespace Content.IntegrationTests.Tests.Interaction { [TestFixture] [TestOf(typeof(SharedInteractionSystem))] - public sealed class InRangeUnobstructed : ContentIntegrationTest + public sealed class InRangeUnobstructed { private const string HumanId = "MobHumanBase"; @@ -25,9 +25,8 @@ namespace Content.IntegrationTests.Tests.Interaction [Test] public async Task EntityEntityTest() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); var mapManager = server.ResolveDependency(); @@ -39,7 +38,7 @@ namespace Content.IntegrationTests.Tests.Interaction EntityCoordinates entityCoordinates = default; MapCoordinates mapCoordinates = default; - server.Assert(() => + await server.WaitAssertion(() => { var mapId = mapManager.CreateMap(); var coordinates = new MapCoordinates(Vector2.Zero, mapId); @@ -56,7 +55,7 @@ namespace Content.IntegrationTests.Tests.Interaction var interactionSys = server.ResolveDependency().GetEntitySystem(); - server.Assert(() => + await server.WaitAssertion(() => { // Entity <-> Entity Assert.True(interactionSys.InRangeUnobstructed(origin, other)); @@ -100,7 +99,7 @@ namespace Content.IntegrationTests.Tests.Interaction Assert.True(interactionSys.InRangeUnobstructed(mapCoordinates, origin, InteractionRangeDivided15Times3)); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/InventoryHelpersTest.cs b/Content.IntegrationTests/Tests/InventoryHelpersTest.cs index c585830480..54400ab61d 100644 --- a/Content.IntegrationTests/Tests/InventoryHelpersTest.cs +++ b/Content.IntegrationTests/Tests/InventoryHelpersTest.cs @@ -10,7 +10,7 @@ using Robust.Shared.Map; namespace Content.IntegrationTests.Tests { [TestFixture] - public sealed class InventoryHelpersTest : ContentIntegrationTest + public sealed class InventoryHelpersTest { private const string Prototypes = @" - type: entity @@ -43,10 +43,8 @@ namespace Content.IntegrationTests.Tests [Test] public async Task SpawnItemInSlotTest() { - var options = new ServerIntegrationOptions {ExtraPrototypes = Prototypes}; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var sEntities = server.ResolveDependency(); @@ -89,6 +87,7 @@ namespace Content.IntegrationTests.Tests ID: "InventoryIDCardDummy" }); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs b/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs index 991548b372..fc236c1896 100644 --- a/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs +++ b/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs @@ -1,15 +1,11 @@ +using System; using System.Threading.Tasks; using Content.Client.Lobby; using Content.Client.Preferences; -using Content.Server.GameTicking; using Content.Server.Preferences.Managers; -using Content.Shared.CCVar; using Content.Shared.Preferences; using NUnit.Framework; using Robust.Client.State; -using Robust.Shared; -using Robust.Shared.Configuration; -using Robust.Shared.GameObjects; using Robust.Shared.Network; namespace Content.IntegrationTests.Tests.Lobby @@ -17,47 +13,26 @@ namespace Content.IntegrationTests.Tests.Lobby [TestFixture] [TestOf(typeof(ClientPreferencesManager))] [TestOf(typeof(ServerPreferencesManager))] - public sealed class CharacterCreationTest : ContentIntegrationTest + public sealed class CharacterCreationTest { [Test] public async Task CreateDeleteCreateTest() { - var serverOptions = new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.GameDummyTicker.Name] = "false", - [CCVars.GameLobbyEnabled.Name] = "true", - [CVars.NetPVS.Name] = "false" - } - }; - - var (client, server) = await StartConnectedServerClientPair(serverOptions: serverOptions); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{InLobby = true}); + var server = pairTracker.Pair.Server; + var client = pairTracker.Pair.Client; var clientNetManager = client.ResolveDependency(); var clientStateManager = client.ResolveDependency(); var clientPrefManager = client.ResolveDependency(); - var serverConfig = server.ResolveDependency(); - var serverTicker = server.ResolveDependency().GetEntitySystem(); var serverPrefManager = server.ResolveDependency(); - await server.WaitIdleAsync(); - await client.WaitIdleAsync(); - - await server.WaitAssertion(() => - { - serverConfig.SetCVar(CCVars.GameDummyTicker, false); - serverConfig.SetCVar(CCVars.GameLobbyEnabled, true); - serverTicker.RestartRound(); - - Assert.That(serverTicker.RunLevel, Is.EqualTo(GameRunLevel.PreRoundLobby)); - }); // Need to run them in sync to receive the messages. - await RunTicksSync(client, server, 1); + await PoolManager.RunTicksSync(pairTracker.Pair, 1); - await WaitUntil(client, () => clientStateManager.CurrentState is LobbyState, 600); + await PoolManager.WaitUntil(client, () => clientStateManager.CurrentState is LobbyState, 600); Assert.NotNull(clientNetManager.ServerChannel); @@ -84,7 +59,7 @@ namespace Content.IntegrationTests.Tests.Lobby Assert.That(clientCharacters[1].MemberwiseEquals(profile)); }); - await WaitUntil(server, () => serverPrefManager.GetPreferences(clientNetId).Characters.Count == 2, maxTicks: 60); + await PoolManager.WaitUntil(server, () => serverPrefManager.GetPreferences(clientNetId).Characters.Count == 2, maxTicks: 60); await server.WaitAssertion(() => { @@ -102,7 +77,7 @@ namespace Content.IntegrationTests.Tests.Lobby Assert.That(clientCharacters, Is.EqualTo(1)); }); - await WaitUntil(server, () => serverPrefManager.GetPreferences(clientNetId).Characters.Count == 1, maxTicks: 60); + await PoolManager.WaitUntil(server, () => serverPrefManager.GetPreferences(clientNetId).Characters.Count == 1, maxTicks: 60); await server.WaitAssertion(() => { @@ -125,7 +100,7 @@ namespace Content.IntegrationTests.Tests.Lobby Assert.That(clientCharacters[1].MemberwiseEquals(profile)); }); - await WaitUntil(server, () => serverPrefManager.GetPreferences(clientNetId).Characters.Count == 2, maxTicks: 60); + await PoolManager.WaitUntil(server, () => serverPrefManager.GetPreferences(clientNetId).Characters.Count == 2, maxTicks: 60); await server.WaitAssertion(() => { @@ -134,6 +109,7 @@ namespace Content.IntegrationTests.Tests.Lobby Assert.That(serverCharacters.Count, Is.EqualTo(2)); Assert.That(serverCharacters[1].MemberwiseEquals(profile)); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/MindEntityDeletionTest.cs b/Content.IntegrationTests/Tests/MindEntityDeletionTest.cs index c4c3ad3e55..5c84e1ff2f 100644 --- a/Content.IntegrationTests/Tests/MindEntityDeletionTest.cs +++ b/Content.IntegrationTests/Tests/MindEntityDeletionTest.cs @@ -8,32 +8,35 @@ using Robust.Server.Player; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; +using Robust.Shared.Maths; namespace Content.IntegrationTests.Tests { // Tests various scenarios of deleting the entity that a player's mind is connected to. [TestFixture] - public sealed class MindEntityDeletionTest : ContentIntegrationTest + public sealed class MindEntityDeletionTest { [Test] public async Task TestDeleteVisiting() { - var (_, server) = await StartConnectedServerDummyTickerClientPair(); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; var entMan = server.ResolveDependency(); EntityUid playerEnt = default; EntityUid visitEnt = default; Mind mind = null; - server.Assert(() => + await server.WaitAssertion(() => { var player = IoCManager.Resolve().ServerSessions.Single(); var mapMan = IoCManager.Resolve(); - mapMan.CreateNewMapEntity(MapId.Nullspace); + var mapId = mapMan.GetAllMapIds().Last(); + var pos = new MapCoordinates(Vector2.Zero, mapId); - playerEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace); - visitEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace); + playerEnt = entMan.SpawnEntity(null, pos); + visitEnt = entMan.SpawnEntity(null, pos); mind = new Mind(player.UserId); mind.ChangeOwningPlayer(player.UserId); @@ -44,40 +47,52 @@ namespace Content.IntegrationTests.Tests Assert.That(player.AttachedEntity, Is.EqualTo(visitEnt)); Assert.That(mind.VisitingEntity, Is.EqualTo(visitEnt)); }); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - server.RunTicks(1); - - server.Assert(() => + await server.WaitAssertion(() => { entMan.DeleteEntity(visitEnt); + if (mind == null) + { + Assert.Fail("Mind was null"); + return; + } - Assert.That(mind.VisitingEntity, Is.EqualTo(default)); + if (mind.VisitingEntity != null) + { + Assert.Fail("Mind VisitingEntity was not null"); + return; + } // This used to throw so make sure it doesn't. entMan.DeleteEntity(playerEnt); }); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestGhostOnDelete() { // Has to be a non-dummy ticker so we have a proper map. - var (_, server) = await StartConnectedServerClientPair(); + + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; var entMan = server.ResolveDependency(); EntityUid playerEnt = default; Mind mind = null; - server.Assert(() => + await server.WaitAssertion(() => { var player = IoCManager.Resolve().ServerSessions.Single(); var mapMan = IoCManager.Resolve(); - mapMan.CreateNewMapEntity(MapId.Nullspace); + var mapId = mapMan.GetAllMapIds().Last(); + var pos = new MapCoordinates(Vector2.Zero, mapId); - playerEnt = entMan.SpawnEntity(null, MapCoordinates.Nullspace); + playerEnt = entMan.SpawnEntity(null, pos); mind = new Mind(player.UserId); mind.ChangeOwningPlayer(player.UserId); @@ -87,33 +102,33 @@ namespace Content.IntegrationTests.Tests Assert.That(mind.CurrentEntity, Is.EqualTo(playerEnt)); }); - server.RunTicks(1); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - server.Post(() => + await server.WaitPost(() => { entMan.DeleteEntity(playerEnt); }); - server.RunTicks(1); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - server.Assert(() => + await server.WaitAssertion(() => { Assert.That(entMan.EntityExists(mind.CurrentEntity!.Value), Is.True); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestGhostOnDeleteMap() { - // Has to be a non-dummy ticker so we have a proper map. - var (_, server) = await StartConnectedServerClientPair(); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; EntityUid playerEnt = default; Mind mind = null; MapId map = default; - server.Assert(() => + await server.WaitAssertion(() => { var player = IoCManager.Resolve().ServerSessions.Single(); @@ -136,24 +151,24 @@ namespace Content.IntegrationTests.Tests Assert.That(mind.CurrentEntity, Is.EqualTo(playerEnt)); }); - server.RunTicks(1); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - server.Post(() => + await server.WaitPost(() => { var mapMan = IoCManager.Resolve(); mapMan.DeleteMap(map); }); - server.RunTicks(1); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); - server.Assert(() => + await server.WaitAssertion(() => { Assert.That(IoCManager.Resolve().EntityExists(mind.CurrentEntity!.Value), Is.True); Assert.That(mind.CurrentEntity, Is.Not.EqualTo(playerEnt)); }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Networking/ConnectTest.cs b/Content.IntegrationTests/Tests/Networking/ConnectTest.cs index 7f83529bcb..5984336841 100644 --- a/Content.IntegrationTests/Tests/Networking/ConnectTest.cs +++ b/Content.IntegrationTests/Tests/Networking/ConnectTest.cs @@ -11,40 +11,14 @@ using Robust.Shared.Network; namespace Content.IntegrationTests.Tests.Networking { [TestFixture] - public sealed class ConnectTest : ContentIntegrationTest + public sealed class ConnectTest { [Test] public async Task TestConnect() { - var client = StartClient(); - var server = StartServer(new ServerContentIntegrationOption - { - Pool = false, - CVarOverrides = - { - {CVars.NetPVS.Name, "false"} - } - }); - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); - - // Connect. - - client.SetConnectTarget(server); - - client.Post(() => IoCManager.Resolve().ClientConnect(null, 0, null)); - - // Run some ticks for the handshake to complete and such. - - for (var i = 0; i < 10; i++) - { - server.RunTicks(1); - await server.WaitIdleAsync(); - client.RunTicks(1); - await client.WaitIdleAsync(); - } - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; + var client = pairTracker.Pair.Client; // Basic checks to ensure that they're connected and data got replicated. diff --git a/Content.IntegrationTests/Tests/Networking/NetworkIdsMatchTest.cs b/Content.IntegrationTests/Tests/Networking/NetworkIdsMatchTest.cs index e5c935c8e1..d848f7ca1c 100644 --- a/Content.IntegrationTests/Tests/Networking/NetworkIdsMatchTest.cs +++ b/Content.IntegrationTests/Tests/Networking/NetworkIdsMatchTest.cs @@ -7,15 +7,14 @@ using Robust.Shared.Network; namespace Content.IntegrationTests.Tests.Networking { [TestFixture] - sealed class NetworkIdsMatchTest : ContentIntegrationTest + sealed class NetworkIdsMatchTest { [Test] public async Task TestConnect() { - var client = StartClient(); - var server = StartServer(); - - await ConnectNetworking(client, server); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; + var client = pairTracker.Pair.Client; var clientCompFactory = client.ResolveDependency(); var serverCompFactory = server.ResolveDependency(); @@ -34,29 +33,7 @@ namespace Content.IntegrationTests.Tests.Networking { Assert.That(clientNetComps[netId].Name, Is.EqualTo(serverNetComps[netId].Name)); } - } - - private static async Task ConnectNetworking(ClientIntegrationInstance client, ServerIntegrationInstance server) - { - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); - - // Connect. - - client.SetConnectTarget(server); - - client.Post(() => IoCManager.Resolve().ClientConnect(null, 0, null)); - - // Run some ticks for the handshake to complete and such. - - for (var i = 0; i < 10; i++) - { - server.RunTicks(1); - await server.WaitIdleAsync(); - client.RunTicks(1); - await client.WaitIdleAsync(); - } - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Networking/ReconnectTest.cs b/Content.IntegrationTests/Tests/Networking/ReconnectTest.cs index 9e3974a68b..5f97339afd 100644 --- a/Content.IntegrationTests/Tests/Networking/ReconnectTest.cs +++ b/Content.IntegrationTests/Tests/Networking/ReconnectTest.cs @@ -7,30 +7,19 @@ using Robust.Shared.Network; namespace Content.IntegrationTests.Tests.Networking { [TestFixture] - public sealed class ReconnectTest : ContentIntegrationTest + public sealed class ReconnectTest { [Test] public async Task Test() { - var client = StartClient(); - var server = StartServer(); - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); - - // Connect. - client.SetConnectTarget(server); - - await client.WaitPost(() => IoCManager.Resolve().ClientConnect(null, 0, null)); - - // Run some ticks for the handshake to complete and such. - await RunTicksSync(client, server, 10); - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; + var client = pairTracker.Pair.Client; await client.WaitPost(() => IoCManager.Resolve().ExecuteCommand("disconnect")); // Run some ticks for the disconnect to complete and such. - await RunTicksSync(client, server, 5); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); @@ -40,9 +29,10 @@ namespace Content.IntegrationTests.Tests.Networking await client.WaitPost(() => IoCManager.Resolve().ClientConnect(null, 0, null)); // Run some ticks for the handshake to complete and such. - await RunTicksSync(client, server, 10); + await PoolManager.RunTicksSync(pairTracker.Pair, 10); await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Networking/SimplePredictReconcileTest.cs b/Content.IntegrationTests/Tests/Networking/SimplePredictReconcileTest.cs index c3400385a9..63a0d4d35d 100644 --- a/Content.IntegrationTests/Tests/Networking/SimplePredictReconcileTest.cs +++ b/Content.IntegrationTests/Tests/Networking/SimplePredictReconcileTest.cs @@ -6,8 +6,8 @@ using System.Threading.Tasks; using NUnit.Framework; using Robust.Client.GameObjects; using Robust.Client.GameStates; +using Robust.Server.GameStates; using Robust.Server.Player; -using Robust.Shared; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.IoC; @@ -30,42 +30,14 @@ namespace Content.IntegrationTests.Tests.Networking // the tick where the server *should* have, but did not, acknowledge the state change. // Finally, we run two events inside the prediction area to ensure reconciling does for incremental stuff. [TestFixture] - public sealed class SimplePredictReconcileTest : ContentIntegrationTest + public sealed class SimplePredictReconcileTest { [Test] public async Task Test() { - // Initialize client & server with text component and system registered. - // They can't be registered/detected automatically. - var (client, server) = await StartConnectedServerDummyTickerClientPair( - new ClientContentIntegrationOption - { - // This test is designed around specific timing values and when I wrote it interpolation was off. - // As such, I would have to update half this test to make sure it works with interpolation. - // I'm kinda lazy. - CVarOverrides = - { - {CVars.NetInterp.Name, "false"}, - {CVars.NetPVS.Name, "false"} - }, - ContentBeforeIoC = () => - { - IoCManager.Resolve().LoadExtraSystemType(); - IoCManager.Resolve().RegisterClass(); - } - }, - new ServerContentIntegrationOption - { - CVarOverrides = - { - {CVars.NetPVS.Name, "false"} - }, - ContentBeforeIoC = () => - { - IoCManager.Resolve().LoadExtraSystemType(); - IoCManager.Resolve().RegisterClass(); - } - }); + await using var pairTracker = await PoolManager.GetServerClient(new (){Fresh = true, DisableInterpolate = true, DummyTicker = true}); + var server = pairTracker.Pair.Server; + var client = pairTracker.Pair.Client; // Pull in all dependencies we need. var sPlayerManager = server.ResolveDependency(); @@ -85,7 +57,7 @@ namespace Content.IntegrationTests.Tests.Networking var clientSystem = client.ResolveDependency() .GetEntitySystem(); - server.Post(() => + await server.WaitPost(() => { // Spawn dummy component entity. var map = sMapManager.CreateMap(); @@ -98,7 +70,7 @@ namespace Content.IntegrationTests.Tests.Networking }); // Run some ticks so that - await RunTicksSync(client, server, 3); + await PoolManager.RunTicksSync(pairTracker.Pair, 3); // Due to technical things with the game state processor it has an extra state in the buffer here. // This burns through it real quick, but I'm not sure it should be there? @@ -387,10 +359,11 @@ namespace Content.IntegrationTests.Tests.Networking Assert.That(clientComponent.Foo, Is.True); } } + await pairTracker.CleanReturnAsync(); } [NetworkedComponent()] - private sealed class PredictionTestComponent : Component + public sealed class PredictionTestComponent : Component { private bool _foo; @@ -432,7 +405,7 @@ namespace Content.IntegrationTests.Tests.Networking } [Reflect(false)] - private sealed class PredictionTestEntitySystem : EntitySystem + public sealed class PredictionTestEntitySystem : EntitySystem { public bool Allow { get; set; } = true; diff --git a/Content.IntegrationTests/Tests/PostMapInitTest.cs b/Content.IntegrationTests/Tests/PostMapInitTest.cs index 7b53438f87..14003486eb 100644 --- a/Content.IntegrationTests/Tests/PostMapInitTest.cs +++ b/Content.IntegrationTests/Tests/PostMapInitTest.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; using NUnit.Framework; using Robust.Server.Maps; @@ -12,7 +14,7 @@ using YamlDotNet.RepresentationModel; namespace Content.IntegrationTests.Tests { [TestFixture] - public sealed class PostMapInitTest : ContentIntegrationTest + public sealed class PostMapInitTest { public const bool SkipTestMaps = true; public const string TestMapsPath = "/Maps/Test/"; @@ -20,9 +22,8 @@ namespace Content.IntegrationTests.Tests [Test] public async Task NoSavedPostMapInitTest() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var resourceManager = server.ResolveDependency(); var mapFolder = new ResourcePath("/Maps"); @@ -57,56 +58,80 @@ namespace Content.IntegrationTests.Tests Assert.False(postMapInit, $"Map {map.Filename} was saved postmapinit"); } + await pairTracker.CleanReturnAsync(); } - [Test] - public async Task MapsLoadableTest() + private static string[] GetMapNames() { - var server = StartServer(); + Task task = null; + using (ExecutionContext.SuppressFlow()) + { + task = Task.Run(static async () => + { + await Task.Yield(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{Disconnected = true}); + var server = pairTracker.Pair.Server; + var resourceManager = server.ResolveDependency(); + var mapFolder = new ResourcePath("/Maps"); + var maps = resourceManager + .ContentFindFiles(mapFolder) + .Where(filePath => filePath.Extension == "yml" && !filePath.Filename.StartsWith(".")) + .ToArray(); + var mapNames = new List(); + foreach (var map in maps) + { + var rootedPath = map.ToRootedPath(); - await server.WaitIdleAsync(); + // ReSharper disable once RedundantLogicalConditionalExpressionOperand + if (SkipTestMaps && rootedPath.ToString().StartsWith(TestMapsPath)) + { + continue; + } + mapNames.Add(rootedPath.ToString()); + } + + await pairTracker.CleanReturnAsync(); + return mapNames.ToArray(); + }); + Task.WaitAll(task); + } + + return task.GetAwaiter().GetResult(); + } + + [Test, TestCaseSource("GetMapNames")] + public async Task MapsLoadableTest(string mapName) + { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var mapLoader = server.ResolveDependency(); var mapManager = server.ResolveDependency(); - var resourceManager = server.ResolveDependency(); - var mapFolder = new ResourcePath("/Maps"); - var maps = resourceManager - .ContentFindFiles(mapFolder) - .Where(filePath => filePath.Extension == "yml" && !filePath.Filename.StartsWith(".")) - .ToArray(); - foreach (var map in maps) + await server.WaitPost(() => { - var rootedPath = map.ToRootedPath(); - - // ReSharper disable once RedundantLogicalConditionalExpressionOperand - if (SkipTestMaps && rootedPath.ToString().StartsWith(TestMapsPath)) + var mapId = mapManager.CreateMap(); + try { - continue; + mapLoader.LoadMap(mapId, mapName); + } + catch (Exception ex) + { + throw new Exception($"Failed to load map {mapName}", ex); } - server.Post(() => + try { - var mapId = mapManager.CreateMap(); - try - { - mapLoader.LoadMap(mapId, rootedPath.ToString()); - } - catch (Exception ex) - { - throw new Exception($"Failed to load map {rootedPath}", ex); - } - try - { - mapManager.DeleteMap(mapId); - } - catch (Exception ex) - { - throw new Exception($"Failed to delete map {rootedPath}", ex); - } - }); - await server.WaitIdleAsync(); - } + mapManager.DeleteMap(mapId); + } + catch (Exception ex) + { + throw new Exception($"Failed to delete map {mapName}", ex); + } + }); + await server.WaitRunTicks(1); + + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Power/PowerTest.cs b/Content.IntegrationTests/Tests/Power/PowerTest.cs index 7a33e2440d..0ce71302ce 100644 --- a/Content.IntegrationTests/Tests/Power/PowerTest.cs +++ b/Content.IntegrationTests/Tests/Power/PowerTest.cs @@ -14,9 +14,8 @@ using Robust.Shared.Timing; namespace Content.IntegrationTests.Tests.Power { - [Parallelizable(ParallelScope.Fixtures)] [TestFixture] - public sealed class PowerTest : ContentIntegrationTest + public sealed class PowerTest { private const string Prototypes = @" - type: entity @@ -157,56 +156,40 @@ namespace Content.IntegrationTests.Tests.Power - type: Transform anchored: true "; - - private ServerIntegrationInstance _server = default!; - private IMapManager _mapManager = default!; - private IEntityManager _entityManager = default!; - private IGameTiming _gameTiming = default!; - private ExtensionCableSystem _extensionCableSystem = default!; - - [OneTimeSetUp] - public async Task Setup() - { - var options = new ServerIntegrationOptions {ExtraPrototypes = Prototypes}; - _server = StartServer(options); - - await _server.WaitIdleAsync(); - _mapManager = _server.ResolveDependency(); - _entityManager = _server.ResolveDependency(); - _gameTiming = _server.ResolveDependency(); - _extensionCableSystem = _entityManager.EntitySysManager.GetEntitySystem(); - } - /// /// Test small power net with a simple surplus of power over the loads. /// [Test] public async Task TestSimpleSurplus() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); const float loadPower = 200; PowerSupplierComponent supplier = default!; PowerConsumerComponent consumer1 = default!; PowerConsumerComponent consumer2 = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 3; i++) { grid.SetTile(new Vector2i(0, i), new Tile(1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); } - var generatorEnt = _entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates()); - var consumerEnt1 = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 1)); - var consumerEnt2 = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 2)); + var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates()); + var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 1)); + var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 2)); - supplier = _entityManager.GetComponent(generatorEnt); - consumer1 = _entityManager.GetComponent(consumerEnt1); - consumer2 = _entityManager.GetComponent(consumerEnt2); + supplier = entityManager.GetComponent(generatorEnt); + consumer1 = entityManager.GetComponent(consumerEnt1); + consumer2 = entityManager.GetComponent(consumerEnt2); // Plenty of surplus and tolerance supplier.MaxSupply = loadPower * 4; @@ -215,9 +198,9 @@ namespace Content.IntegrationTests.Tests.Power consumer2.DrawRate = loadPower; }); - _server.RunTicks(1); //let run a tick for PowerNet to process power + server.RunTicks(1); //let run a tick for PowerNet to process power - _server.Assert(() => + await server.WaitAssertion(() => { // Assert both consumers fully powered Assert.That(consumer1.ReceivedPower, Is.EqualTo(consumer1.DrawRate).Within(0.1)); @@ -227,7 +210,7 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(supplier.CurrentSupply, Is.EqualTo(loadPower * 2).Within(0.1)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } @@ -237,30 +220,34 @@ namespace Content.IntegrationTests.Tests.Power [Test] public async Task TestSimpleDeficit() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); const float loadPower = 200; PowerSupplierComponent supplier = default!; PowerConsumerComponent consumer1 = default!; PowerConsumerComponent consumer2 = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 3; i++) { grid.SetTile(new Vector2i(0, i), new Tile(1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); } - var generatorEnt = _entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates()); - var consumerEnt1 = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 1)); - var consumerEnt2 = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 2)); + var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates()); + var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 1)); + var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 2)); - supplier = _entityManager.GetComponent(generatorEnt); - consumer1 = _entityManager.GetComponent(consumerEnt1); - consumer2 = _entityManager.GetComponent(consumerEnt2); + supplier = entityManager.GetComponent(generatorEnt); + consumer1 = entityManager.GetComponent(consumerEnt1); + consumer2 = entityManager.GetComponent(consumerEnt2); // Too little supply, both consumers should get 33% power. supplier.MaxSupply = loadPower; @@ -269,9 +256,9 @@ namespace Content.IntegrationTests.Tests.Power consumer2.DrawRate = loadPower * 2; }); - _server.RunTicks(1); //let run a tick for PowerNet to process power + server.RunTicks(1); //let run a tick for PowerNet to process power - _server.Assert(() => + await server.WaitAssertion(() => { // Assert both consumers get 33% power. Assert.That(consumer1.ReceivedPower, Is.EqualTo(consumer1.DrawRate / 3).Within(0.1)); @@ -281,32 +268,37 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(supplier.CurrentSupply, Is.EqualTo(supplier.MaxSupply).Within(0.1)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestSupplyRamp() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); + var gameTiming = server.ResolveDependency(); PowerSupplierComponent supplier = default!; PowerConsumerComponent consumer = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 3; i++) { grid.SetTile(new Vector2i(0, i), new Tile(1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); } - var generatorEnt = _entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates()); - var consumerEnt = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 2)); + var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates()); + var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 2)); - supplier = _entityManager.GetComponent(generatorEnt); - consumer = _entityManager.GetComponent(consumerEnt); + supplier = entityManager.GetComponent(generatorEnt); + consumer = entityManager.GetComponent(consumerEnt); // Supply has enough total power but needs to ramp up to match. supplier.MaxSupply = 400; @@ -316,21 +308,21 @@ namespace Content.IntegrationTests.Tests.Power }); // Exact values can/will be off by a tick, add tolerance for that. - var tickRate = (float) _gameTiming.TickPeriod.TotalSeconds; + var tickRate = (float) gameTiming.TickPeriod.TotalSeconds; var tickDev = 400 * tickRate * 1.1f; - _server.RunTicks(1); + server.RunTicks(1); - _server.Assert(() => + await server.WaitAssertion(() => { // First tick, supply should be delivering 100 W (max tolerance) and start ramping up. Assert.That(supplier.CurrentSupply, Is.EqualTo(100).Within(0.1)); Assert.That(consumer.ReceivedPower, Is.EqualTo(100).Within(0.1)); }); - _server.RunTicks(14); + server.RunTicks(14); - _server.Assert(() => + await server.WaitAssertion(() => { // After 15 ticks (0.25 seconds), supply ramp pos should be at 100 W and supply at 100, approx. Assert.That(supplier.CurrentSupply, Is.EqualTo(200).Within(tickDev)); @@ -338,9 +330,9 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(consumer.ReceivedPower, Is.EqualTo(200).Within(tickDev)); }); - _server.RunTicks(45); + server.RunTicks(45); - _server.Assert(() => + await server.WaitAssertion(() => { // After 1 second total, ramp should be at 400 and supply should be at 400, everybody happy. Assert.That(supplier.CurrentSupply, Is.EqualTo(400).Within(tickDev)); @@ -348,36 +340,41 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(consumer.ReceivedPower, Is.EqualTo(400).Within(tickDev)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestBatteryRamp() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); + var gameTiming = server.ResolveDependency(); const float startingCharge = 100_000; PowerNetworkBatteryComponent netBattery = default!; BatteryComponent battery = default!; PowerConsumerComponent consumer = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 3; i++) { grid.SetTile(new Vector2i(0, i), new Tile(1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); } - var generatorEnt = _entityManager.SpawnEntity("DischargingBatteryDummy", grid.ToCoordinates()); - var consumerEnt = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 2)); + var generatorEnt = entityManager.SpawnEntity("DischargingBatteryDummy", grid.ToCoordinates()); + var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 2)); - netBattery = _entityManager.GetComponent(generatorEnt); - battery = _entityManager.GetComponent(generatorEnt); - consumer = _entityManager.GetComponent(consumerEnt); + netBattery = entityManager.GetComponent(generatorEnt); + battery = entityManager.GetComponent(generatorEnt); + consumer = entityManager.GetComponent(consumerEnt); battery.MaxCharge = startingCharge; battery.CurrentCharge = startingCharge; @@ -388,21 +385,21 @@ namespace Content.IntegrationTests.Tests.Power }); // Exact values can/will be off by a tick, add tolerance for that. - var tickRate = (float) _gameTiming.TickPeriod.TotalSeconds; + var tickRate = (float) gameTiming.TickPeriod.TotalSeconds; var tickDev = 400 * tickRate * 1.1f; - _server.RunTicks(1); + server.RunTicks(1); - _server.Assert(() => + await server.WaitAssertion(() => { // First tick, supply should be delivering 100 W (max tolerance) and start ramping up. Assert.That(netBattery.CurrentSupply, Is.EqualTo(100).Within(0.1)); Assert.That(consumer.ReceivedPower, Is.EqualTo(100).Within(0.1)); }); - _server.RunTicks(14); + server.RunTicks(14); - _server.Assert(() => + await server.WaitAssertion(() => { // After 15 ticks (0.25 seconds), supply ramp pos should be at 100 W and supply at 100, approx. Assert.That(netBattery.CurrentSupply, Is.EqualTo(200).Within(tickDev)); @@ -414,9 +411,9 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(battery.CurrentCharge, Is.EqualTo(startingCharge - spentExpected).Within(tickDev)); }); - _server.RunTicks(45); + server.RunTicks(45); - _server.Assert(() => + await server.WaitAssertion(() => { // After 1 second total, ramp should be at 400 and supply should be at 400, everybody happy. Assert.That(netBattery.CurrentSupply, Is.EqualTo(400).Within(tickDev)); @@ -428,34 +425,38 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(battery.CurrentCharge, Is.EqualTo(startingCharge - spentExpected).Within(tickDev)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestSimpleBatteryChargeDeficit() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); PowerSupplierComponent supplier = default!; BatteryComponent battery = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 3; i++) { grid.SetTile(new Vector2i(0, i), new Tile(1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); } - var generatorEnt = _entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates()); - var batteryEnt = _entityManager.SpawnEntity("ChargingBatteryDummy", grid.ToCoordinates(0, 2)); + var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates()); + var batteryEnt = entityManager.SpawnEntity("ChargingBatteryDummy", grid.ToCoordinates(0, 2)); - supplier = _entityManager.GetComponent(generatorEnt); - var netBattery = _entityManager.GetComponent(batteryEnt); - battery = _entityManager.GetComponent(batteryEnt); + supplier = entityManager.GetComponent(generatorEnt); + var netBattery = entityManager.GetComponent(batteryEnt); + battery = entityManager.GetComponent(batteryEnt); supplier.MaxSupply = 500; supplier.SupplyRampTolerance = 500; @@ -464,9 +465,9 @@ namespace Content.IntegrationTests.Tests.Power netBattery.Efficiency = 0.5f; }); - _server.RunTicks(30); // 60 TPS, 0.5 seconds + server.RunTicks(30); // 60 TPS, 0.5 seconds - _server.Assert(() => + await server.WaitAssertion(() => { // half a second @ 500 W = 250 // 50% efficiency, so 125 J stored total. @@ -474,40 +475,45 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(supplier.CurrentSupply, Is.EqualTo(500).Within(0.1)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestFullBattery() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); + var gameTiming = server.ResolveDependency(); PowerConsumerComponent consumer = default!; PowerSupplierComponent supplier = default!; PowerNetworkBatteryComponent netBattery = default!; BatteryComponent battery = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 4; i++) { grid.SetTile(new Vector2i(0, i), new Tile(1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); } - var terminal = _entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1)); - _entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); + var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1)); + entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); - var batteryEnt = _entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 2)); - var supplyEnt = _entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 0)); - var consumerEnt = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 3)); + var batteryEnt = entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 2)); + var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 0)); + var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 3)); - consumer = _entityManager.GetComponent(consumerEnt); - supplier = _entityManager.GetComponent(supplyEnt); - netBattery = _entityManager.GetComponent(batteryEnt); - battery = _entityManager.GetComponent(batteryEnt); + consumer = entityManager.GetComponent(consumerEnt); + supplier = entityManager.GetComponent(supplyEnt); + netBattery = entityManager.GetComponent(batteryEnt); + battery = entityManager.GetComponent(batteryEnt); // Consumer needs 1000 W, supplier can only provide 800, battery fills in the remaining 200. consumer.DrawRate = 1000; @@ -522,13 +528,13 @@ namespace Content.IntegrationTests.Tests.Power }); // Run some ticks so everything is stable. - _server.RunTicks(60); + server.RunTicks(60); // Exact values can/will be off by a tick, add tolerance for that. - var tickRate = (float) _gameTiming.TickPeriod.TotalSeconds; + var tickRate = (float) gameTiming.TickPeriod.TotalSeconds; var tickDev = 400 * tickRate * 1.1f; - _server.Assert(() => + await server.WaitAssertion(() => { Assert.That(consumer.ReceivedPower, Is.EqualTo(consumer.DrawRate).Within(0.1)); Assert.That(supplier.CurrentSupply, Is.EqualTo(supplier.MaxSupply).Within(0.1)); @@ -542,40 +548,45 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(battery.CurrentCharge, Is.EqualTo(battery.MaxCharge - expectedSpent).Within(tickDev)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestFullBatteryEfficiencyPassThrough() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); + var gameTiming = server.ResolveDependency(); PowerConsumerComponent consumer = default!; PowerSupplierComponent supplier = default!; PowerNetworkBatteryComponent netBattery = default!; BatteryComponent battery = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 4; i++) { grid.SetTile(new Vector2i(0, i), new Tile(1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); } - var terminal = _entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1)); - _entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); + var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1)); + entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); - var batteryEnt = _entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 2)); - var supplyEnt = _entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 0)); - var consumerEnt = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 3)); + var batteryEnt = entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 2)); + var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 0)); + var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 3)); - consumer = _entityManager.GetComponent(consumerEnt); - supplier = _entityManager.GetComponent(supplyEnt); - netBattery = _entityManager.GetComponent(batteryEnt); - battery = _entityManager.GetComponent(batteryEnt); + consumer = entityManager.GetComponent(consumerEnt); + supplier = entityManager.GetComponent(supplyEnt); + netBattery = entityManager.GetComponent(batteryEnt); + battery = entityManager.GetComponent(batteryEnt); // Consumer needs 1000 W, supply and battery can only provide 400 each. // BUT the battery has 50% input efficiency, so 50% of the power of the supply gets lost. @@ -592,13 +603,13 @@ namespace Content.IntegrationTests.Tests.Power }); // Run some ticks so everything is stable. - _server.RunTicks(60); + server.RunTicks(60); // Exact values can/will be off by a tick, add tolerance for that. - var tickRate = (float) _gameTiming.TickPeriod.TotalSeconds; + var tickRate = (float) gameTiming.TickPeriod.TotalSeconds; var tickDev = 400 * tickRate * 1.1f; - _server.Assert(() => + await server.WaitAssertion(() => { Assert.That(consumer.ReceivedPower, Is.EqualTo(600).Within(0.1)); Assert.That(supplier.CurrentSupply, Is.EqualTo(supplier.MaxSupply).Within(0.1)); @@ -610,20 +621,24 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(battery.CurrentCharge, Is.EqualTo(battery.MaxCharge - expectedSpent).Within(tickDev)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestFullBatteryEfficiencyDemandPassThrough() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); PowerConsumerComponent consumer1 = default!; PowerConsumerComponent consumer2 = default!; PowerSupplierComponent supplier = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Map layout here is // C - consumer @@ -637,26 +652,26 @@ namespace Content.IntegrationTests.Tests.Power for (var i = 0; i < 5; i++) { grid.SetTile(new Vector2i(0, i), new Tile(1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); } - _entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2)); - var terminal = _entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2)); - _entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); + entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2)); + var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2)); + entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); - var batteryEnt1 = _entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 1)); - var batteryEnt2 = _entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 3)); - var supplyEnt = _entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 2)); - var consumerEnt1 = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 0)); - var consumerEnt2 = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 4)); + var batteryEnt1 = entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 1)); + var batteryEnt2 = entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 3)); + var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 2)); + var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 0)); + var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 4)); - consumer1 = _entityManager.GetComponent(consumerEnt1); - consumer2 = _entityManager.GetComponent(consumerEnt2); - supplier = _entityManager.GetComponent(supplyEnt); - var netBattery1 = _entityManager.GetComponent(batteryEnt1); - var netBattery2 = _entityManager.GetComponent(batteryEnt2); - var battery1 = _entityManager.GetComponent(batteryEnt1); - var battery2 = _entityManager.GetComponent(batteryEnt2); + consumer1 = entityManager.GetComponent(consumerEnt1); + consumer2 = entityManager.GetComponent(consumerEnt2); + supplier = entityManager.GetComponent(supplyEnt); + var netBattery1 = entityManager.GetComponent(batteryEnt1); + var netBattery2 = entityManager.GetComponent(batteryEnt2); + var battery1 = entityManager.GetComponent(batteryEnt1); + var battery2 = entityManager.GetComponent(batteryEnt2); // There are two loads, 500 W and 1000 W respectively. // The 500 W load is behind a 50% efficient battery, @@ -685,16 +700,16 @@ namespace Content.IntegrationTests.Tests.Power }); // Run some ticks so everything is stable. - _server.RunTicks(10); + server.RunTicks(10); - _server.Assert(() => + await server.WaitAssertion(() => { Assert.That(consumer1.ReceivedPower, Is.EqualTo(250).Within(0.1)); Assert.That(consumer2.ReceivedPower, Is.EqualTo(500).Within(0.1)); Assert.That(supplier.CurrentSupply, Is.EqualTo(supplier.MaxSupply).Within(0.1)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } /// @@ -703,14 +718,18 @@ namespace Content.IntegrationTests.Tests.Power [Test] public async Task TestBatteriesProportional() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); PowerConsumerComponent consumer1 = default!; PowerConsumerComponent consumer2 = default!; PowerSupplierComponent supplier = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Map layout here is // C - consumer @@ -724,26 +743,26 @@ namespace Content.IntegrationTests.Tests.Power for (var i = 0; i < 5; i++) { grid.SetTile(new Vector2i(0, i), new Tile(1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); } - _entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2)); - var terminal = _entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2)); - _entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); + entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2)); + var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2)); + entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); - var batteryEnt1 = _entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 1)); - var batteryEnt2 = _entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 3)); - var supplyEnt = _entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 2)); - var consumerEnt1 = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 0)); - var consumerEnt2 = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 4)); + var batteryEnt1 = entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 1)); + var batteryEnt2 = entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 3)); + var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 2)); + var consumerEnt1 = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 0)); + var consumerEnt2 = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 4)); - consumer1 = _entityManager.GetComponent(consumerEnt1); - consumer2 = _entityManager.GetComponent(consumerEnt2); - supplier = _entityManager.GetComponent(supplyEnt); - var netBattery1 = _entityManager.GetComponent(batteryEnt1); - var netBattery2 = _entityManager.GetComponent(batteryEnt2); - var battery1 = _entityManager.GetComponent(batteryEnt1); - var battery2 = _entityManager.GetComponent(batteryEnt2); + consumer1 = entityManager.GetComponent(consumerEnt1); + consumer2 = entityManager.GetComponent(consumerEnt2); + supplier = entityManager.GetComponent(supplyEnt); + var netBattery1 = entityManager.GetComponent(batteryEnt1); + var netBattery2 = entityManager.GetComponent(batteryEnt2); + var battery1 = entityManager.GetComponent(batteryEnt1); + var battery2 = entityManager.GetComponent(batteryEnt2); consumer1.DrawRate = 500; consumer2.DrawRate = 1000; @@ -764,9 +783,9 @@ namespace Content.IntegrationTests.Tests.Power }); // Run some ticks so everything is stable. - _server.RunTicks(60); + server.RunTicks(60); - _server.Assert(() => + await server.WaitAssertion(() => { // NOTE: MaxChargeRate on batteries actually skews the demand. // So that's why the tolerance is so high, the charge rate is so *low*, @@ -776,39 +795,43 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(supplier.CurrentSupply, Is.EqualTo(supplier.MaxSupply).Within(0.1)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task TestBatteryEngineCut() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); PowerConsumerComponent consumer = default!; PowerSupplierComponent supplier = default!; PowerNetworkBatteryComponent netBattery = default!; - _server.Post(() => + await server.WaitPost(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 4; i++) { grid.SetTile(new Vector2i(0, i), new Tile(1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, i)); } - var terminal = _entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1)); - _entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); + var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1)); + entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); - var batteryEnt = _entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 2)); - var supplyEnt = _entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 0)); - var consumerEnt = _entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 3)); + var batteryEnt = entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 2)); + var supplyEnt = entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 0)); + var consumerEnt = entityManager.SpawnEntity("ConsumerDummy", grid.ToCoordinates(0, 3)); - consumer = _entityManager.GetComponent(consumerEnt); - supplier = _entityManager.GetComponent(supplyEnt); - netBattery = _entityManager.GetComponent(batteryEnt); - var battery = _entityManager.GetComponent(batteryEnt); + consumer = entityManager.GetComponent(consumerEnt); + supplier = entityManager.GetComponent(supplyEnt); + netBattery = entityManager.GetComponent(batteryEnt); + var battery = entityManager.GetComponent(batteryEnt); // Consumer needs 1000 W, supplier can only provide 800, battery fills in the remaining 200. consumer.DrawRate = 1000; @@ -823,9 +846,9 @@ namespace Content.IntegrationTests.Tests.Power }); // Run some ticks so everything is stable. - _server.RunTicks(5); + server.RunTicks(5); - _server.Assert(() => + await server.WaitAssertion(() => { // Supply and consumer are fully loaded/supplied. Assert.That(consumer.ReceivedPower, Is.EqualTo(consumer.DrawRate).Within(0.5)); @@ -837,9 +860,9 @@ namespace Content.IntegrationTests.Tests.Power netBattery.SupplyRampTolerance = 5; }); - _server.RunTicks(3); + server.RunTicks(3); - _server.Assert(() => + await server.WaitAssertion(() => { // Assert that network drops to 0 power and starts ramping up Assert.That(consumer.ReceivedPower, Is.LessThan(50).And.GreaterThan(0)); @@ -847,7 +870,7 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(netBattery.CurrentSupply, Is.GreaterThan(0)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } /// @@ -856,15 +879,19 @@ namespace Content.IntegrationTests.Tests.Power [Test] public async Task TestTerminalNodeGroups() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); CableNode leftNode = default!; CableNode rightNode = default!; Node batteryInput = default!; Node batteryOutput = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 4; i++) @@ -872,28 +899,28 @@ namespace Content.IntegrationTests.Tests.Power grid.SetTile(new Vector2i(0, i), new Tile(1)); } - var leftEnt = _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 0)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 1)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 2)); - var rightEnt = _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 3)); + var leftEnt = entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 0)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 1)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 2)); + var rightEnt = entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 3)); - var terminal = _entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1)); - _entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); + var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1)); + entityManager.GetComponent(terminal).LocalRotation = Angle.FromDegrees(180); - var battery = _entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 2)); - var batteryNodeContainer = _entityManager.GetComponent(battery); + var battery = entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 2)); + var batteryNodeContainer = entityManager.GetComponent(battery); - leftNode = _entityManager.GetComponent(leftEnt).GetNode("power"); - rightNode = _entityManager.GetComponent(rightEnt).GetNode("power"); + leftNode = entityManager.GetComponent(leftEnt).GetNode("power"); + rightNode = entityManager.GetComponent(rightEnt).GetNode("power"); batteryInput = batteryNodeContainer.GetNode("input"); batteryOutput = batteryNodeContainer.GetNode("output"); }); // Run ticks to allow node groups to update. - _server.RunTicks(1); + server.RunTicks(1); - _server.Assert(() => + await server.WaitAssertion(() => { Assert.That(batteryInput.NodeGroup, Is.EqualTo(leftNode.NodeGroup)); Assert.That(batteryOutput.NodeGroup, Is.EqualTo(rightNode.NodeGroup)); @@ -901,19 +928,23 @@ namespace Content.IntegrationTests.Tests.Power Assert.That(leftNode.NodeGroup, Is.Not.EqualTo(rightNode.NodeGroup)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task ApcChargingTest() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); PowerNetworkBatteryComponent substationNetBattery = default!; BatteryComponent apcBattery = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 3; i++) @@ -921,18 +952,18 @@ namespace Content.IntegrationTests.Tests.Power grid.SetTile(new Vector2i(0, i), new Tile(1)); } - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 0)); - _entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 1)); - _entityManager.SpawnEntity("CableMV", grid.ToCoordinates(0, 1)); - _entityManager.SpawnEntity("CableMV", grid.ToCoordinates(0, 2)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 0)); + entityManager.SpawnEntity("CableHV", grid.ToCoordinates(0, 1)); + entityManager.SpawnEntity("CableMV", grid.ToCoordinates(0, 1)); + entityManager.SpawnEntity("CableMV", grid.ToCoordinates(0, 2)); - var generatorEnt = _entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 0)); - var substationEnt = _entityManager.SpawnEntity("SubstationDummy", grid.ToCoordinates(0, 1)); - var apcEnt = _entityManager.SpawnEntity("ApcDummy", grid.ToCoordinates(0, 2)); + var generatorEnt = entityManager.SpawnEntity("GeneratorDummy", grid.ToCoordinates(0, 0)); + var substationEnt = entityManager.SpawnEntity("SubstationDummy", grid.ToCoordinates(0, 1)); + var apcEnt = entityManager.SpawnEntity("ApcDummy", grid.ToCoordinates(0, 2)); - var generatorSupplier = _entityManager.GetComponent(generatorEnt); - substationNetBattery = _entityManager.GetComponent(substationEnt); - apcBattery = _entityManager.GetComponent(apcEnt); + var generatorSupplier = entityManager.GetComponent(generatorEnt); + substationNetBattery = entityManager.GetComponent(substationEnt); + apcBattery = entityManager.GetComponent(apcEnt); generatorSupplier.MaxSupply = 1000; generatorSupplier.SupplyRampTolerance = 1000; @@ -940,27 +971,32 @@ namespace Content.IntegrationTests.Tests.Power apcBattery.CurrentCharge = 0; }); - _server.RunTicks(5); //let run a few ticks for PowerNets to reevaluate and start charging apc + server.RunTicks(5); //let run a few ticks for PowerNets to reevaluate and start charging apc - _server.Assert(() => + await server.WaitAssertion(() => { Assert.That(substationNetBattery.CurrentSupply, Is.GreaterThan(0)); //substation should be providing power Assert.That(apcBattery.CurrentCharge, Is.GreaterThan(0)); //apc battery should have gained charge }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } [Test] public async Task ApcNetTest() { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; + var mapManager = server.ResolveDependency(); + var entityManager = server.ResolveDependency(); + var extensionCableSystem = entityManager.EntitySysManager.GetEntitySystem(); PowerNetworkBatteryComponent apcNetBattery = default!; ApcPowerReceiverComponent receiver = default!; - _server.Assert(() => + await server.WaitAssertion(() => { - var map = _mapManager.CreateMap(); - var grid = _mapManager.CreateGrid(map); + var map = mapManager.CreateMap(); + var grid = mapManager.CreateGrid(map); // Power only works when anchored for (var i = 0; i < 3; i++) @@ -968,16 +1004,16 @@ namespace Content.IntegrationTests.Tests.Power grid.SetTile(new Vector2i(0, i), new Tile(1)); } - var apcEnt = _entityManager.SpawnEntity("ApcDummy", grid.ToCoordinates(0, 0)); - var apcExtensionEnt = _entityManager.SpawnEntity("CableApcExtension", grid.ToCoordinates(0, 0)); - var powerReceiverEnt = _entityManager.SpawnEntity("ApcPowerReceiverDummy", grid.ToCoordinates(0, 2)); + var apcEnt = entityManager.SpawnEntity("ApcDummy", grid.ToCoordinates(0, 0)); + var apcExtensionEnt = entityManager.SpawnEntity("CableApcExtension", grid.ToCoordinates(0, 0)); + var powerReceiverEnt = entityManager.SpawnEntity("ApcPowerReceiverDummy", grid.ToCoordinates(0, 2)); - receiver = _entityManager.GetComponent(powerReceiverEnt); - var battery = _entityManager.GetComponent(apcEnt); - apcNetBattery = _entityManager.GetComponent(apcEnt); + receiver = entityManager.GetComponent(powerReceiverEnt); + var battery = entityManager.GetComponent(apcEnt); + apcNetBattery = entityManager.GetComponent(apcEnt); - _extensionCableSystem.SetProviderTransferRange(apcExtensionEnt, 5); - _extensionCableSystem.SetReceiverReceptionRange(powerReceiverEnt, 5); + extensionCableSystem.SetProviderTransferRange(apcExtensionEnt, 5); + extensionCableSystem.SetReceiverReceptionRange(powerReceiverEnt, 5); battery.MaxCharge = 10000; //arbitrary nonzero amount of charge battery.CurrentCharge = battery.MaxCharge; //fill battery @@ -985,15 +1021,15 @@ namespace Content.IntegrationTests.Tests.Power receiver.Load = 1; //arbitrary small amount of power }); - _server.RunTicks(1); //let run a tick for ApcNet to process power + server.RunTicks(1); //let run a tick for ApcNet to process power - _server.Assert(() => + await server.WaitAssertion(() => { Assert.That(receiver.Powered); Assert.That(apcNetBattery.CurrentSupply, Is.EqualTo(1).Within(0.1)); }); - await _server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/ResettingEntitySystemTests.cs b/Content.IntegrationTests/Tests/ResettingEntitySystemTests.cs index de751d843e..6da5acf549 100644 --- a/Content.IntegrationTests/Tests/ResettingEntitySystemTests.cs +++ b/Content.IntegrationTests/Tests/ResettingEntitySystemTests.cs @@ -10,10 +10,10 @@ namespace Content.IntegrationTests.Tests { [TestFixture] [TestOf(typeof(RoundRestartCleanupEvent))] - public sealed class ResettingEntitySystemTests : ContentIntegrationTest + public sealed class ResettingEntitySystemTests { [Reflect(false)] - private sealed class TestRoundRestartCleanupEvent : EntitySystem + public sealed class TestRoundRestartCleanupEvent : EntitySystem { public bool HasBeenReset { get; set; } @@ -33,15 +33,8 @@ namespace Content.IntegrationTests.Tests [Test] public async Task ResettingEntitySystemResetTest() { - var server = StartServer(new ServerContentIntegrationOption - { - ContentBeforeIoC = () => - { - IoCManager.Resolve().LoadExtraSystemType(); - } - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var entitySystemManager = server.ResolveDependency(); var gameTicker = entitySystemManager.GetEntitySystem(); @@ -60,6 +53,7 @@ namespace Content.IntegrationTests.Tests Assert.True(system.HasBeenReset); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/RestartRoundTest.cs b/Content.IntegrationTests/Tests/RestartRoundTest.cs index c15e82104d..6798700224 100644 --- a/Content.IntegrationTests/Tests/RestartRoundTest.cs +++ b/Content.IntegrationTests/Tests/RestartRoundTest.cs @@ -7,19 +7,21 @@ using Robust.Shared.IoC; namespace Content.IntegrationTests.Tests { [TestFixture] - public sealed class RestartRoundTest : ContentIntegrationTest + public sealed class RestartRoundTest { [Test] public async Task Test() { - var (client, server) = await StartConnectedServerClientPair(); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; - server.Post(() => + await server.WaitPost(() => { IoCManager.Resolve().GetEntitySystem().RestartRound(); }); - await RunTicksSync(client, server, 10); + await PoolManager.RunTicksSync(pairTracker.Pair, 10); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/RoundEndTest.cs b/Content.IntegrationTests/Tests/RoundEndTest.cs index 18a1ad271c..14ab3f5f8a 100644 --- a/Content.IntegrationTests/Tests/RoundEndTest.cs +++ b/Content.IntegrationTests/Tests/RoundEndTest.cs @@ -12,14 +12,15 @@ using Robust.Shared.IoC; namespace Content.IntegrationTests.Tests { [TestFixture] - public sealed class RoundEndTest : ContentIntegrationTest, IEntityEventSubscriber + public sealed class RoundEndTest : IEntityEventSubscriber { [Test] public async Task Test() { - var eventCount = 0; + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; - var (_, server) = await StartConnectedServerClientPair(); + var eventCount = 0; await server.WaitAssertion(() => { @@ -106,10 +107,12 @@ namespace Content.IntegrationTests.Tests var currentCount = Thread.VolatileRead(ref eventCount); while (currentCount == Thread.VolatileRead(ref eventCount) && !timeout.IsCompleted) { - await server.WaitRunTicks(1); + await PoolManager.RunTicksSync(pairTracker.Pair, 5); } if (timeout.IsCompleted) throw new TimeoutException("Event took too long to trigger"); } + + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/SaveLoadMapTest.cs b/Content.IntegrationTests/Tests/SaveLoadMapTest.cs index 12dde43968..480245f7d3 100644 --- a/Content.IntegrationTests/Tests/SaveLoadMapTest.cs +++ b/Content.IntegrationTests/Tests/SaveLoadMapTest.cs @@ -11,24 +11,21 @@ using Robust.Shared.Utility; namespace Content.IntegrationTests.Tests { [TestFixture] - sealed class SaveLoadMapTest : ContentIntegrationTest + sealed class SaveLoadMapTest { [Test] public async Task SaveLoadMultiGridMap() { const string mapPath = @"/Maps/Test/TestMap.yml"; - var server = StartServer(new ServerContentIntegrationOption - { - FailureLogLevel = LogLevel.Error - }); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var mapLoader = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var sEntities = server.ResolveDependency(); var resManager = server.ResolveDependency(); - server.Post(() => + await server.WaitPost(() => { var dir = new ResourcePath(mapPath).Directory; resManager.UserData.CreateDir(dir); @@ -54,7 +51,7 @@ namespace Content.IntegrationTests.Tests }); await server.WaitIdleAsync(); - server.Post(() => + await server.WaitPost(() => { mapLoader.LoadMap(new MapId(10), mapPath); }); @@ -77,7 +74,7 @@ namespace Content.IntegrationTests.Tests Assert.That(mapGrid.GetTileRef(new Vector2i(0, 0)).Tile, Is.EqualTo(new Tile(2, (TileRenderFlag)1, 254))); } }); - + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/SaveLoadSaveTest.cs b/Content.IntegrationTests/Tests/SaveLoadSaveTest.cs index 1563ab60ed..7a282dcd4e 100644 --- a/Content.IntegrationTests/Tests/SaveLoadSaveTest.cs +++ b/Content.IntegrationTests/Tests/SaveLoadSaveTest.cs @@ -14,16 +14,16 @@ namespace Content.IntegrationTests.Tests /// Tests that the /// [TestFixture] - public sealed class SaveLoadSaveTest : ContentIntegrationTest + public sealed class SaveLoadSaveTest { [Test] public async Task SaveLoadSave() { - var server = StartServer(new ServerContentIntegrationOption {Pool = false}); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new (){Fresh = true, Disconnected = true}); + var server = pairTracker.Pair.Server; var mapLoader = server.ResolveDependency(); var mapManager = server.ResolveDependency(); - server.Post(() => + await server.WaitPost(() => { // TODO: Properly find the "main" station grid. var grid0 = mapManager.GetAllGrids().First(); @@ -71,6 +71,7 @@ namespace Content.IntegrationTests.Tests TestContext.Error.WriteLine(twoTmp); } }); + await pairTracker.CleanReturnAsync(); } /// @@ -79,12 +80,8 @@ namespace Content.IntegrationTests.Tests [Test] public async Task LoadSaveTicksSaveSaltern() { - var server = StartServerDummyTicker(new ServerIntegrationOptions() - { - // Don't blame me look at SaveLoadMultiGridMap - FailureLogLevel = LogLevel.Error, - }); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var mapLoader = server.ResolveDependency(); var mapManager = server.ResolveDependency(); @@ -103,7 +100,7 @@ namespace Content.IntegrationTests.Tests // Run 5 ticks. server.RunTicks(5); - server.Post(() => + await server.WaitPost(() => { mapLoader.SaveMap(mapId, "/load save ticks save 2.yml"); }); @@ -144,6 +141,7 @@ namespace Content.IntegrationTests.Tests TestContext.Error.WriteLine(twoTmp); } }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/ShuttleTest.cs b/Content.IntegrationTests/Tests/ShuttleTest.cs index 330d896d58..e886257177 100644 --- a/Content.IntegrationTests/Tests/ShuttleTest.cs +++ b/Content.IntegrationTests/Tests/ShuttleTest.cs @@ -10,14 +10,13 @@ using Robust.Shared.Physics; namespace Content.IntegrationTests.Tests { [TestFixture] - public sealed class ShuttleTest : ContentIntegrationTest + public sealed class ShuttleTest { [Test] public async Task Test() { - var server = StartServer(); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; var mapMan = server.ResolveDependency(); var sEntities = server.ResolveDependency(); @@ -43,6 +42,7 @@ namespace Content.IntegrationTests.Tests { Assert.That(sEntities.GetComponent(gridEnt).LocalPosition, Is.Not.EqualTo(Vector2.Zero)); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/StartTest.cs b/Content.IntegrationTests/Tests/StartTest.cs index 415dca45cb..7b02bd22db 100644 --- a/Content.IntegrationTests/Tests/StartTest.cs +++ b/Content.IntegrationTests/Tests/StartTest.cs @@ -5,48 +5,32 @@ using Robust.Shared.Exceptions; namespace Content.IntegrationTests.Tests { [TestFixture] - public sealed class StartTest : ContentIntegrationTest + public sealed class StartTest { /// - /// Test that the server starts. - /// - [Test] - public async Task TestServerStart() - { - var server = StartServer(new ServerContentIntegrationOption - { - Pool = false - }); - server.RunTicks(5); - await server.WaitIdleAsync(); - Assert.That(server.IsAlive); - var runtimeLog = server.ResolveDependency(); - Assert.That(runtimeLog.ExceptionCount, Is.EqualTo(0), "No exceptions must be logged."); - server.Stop(); - await server.WaitIdleAsync(); - Assert.That(!server.IsAlive); - } - - /// - /// Test that the client starts. + /// Test that the server, and client start, and stop. /// [Test] public async Task TestClientStart() { - var client = StartClient(new ClientContentIntegrationOption - { - Pool = false - }); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{Disconnected = true}); + var client = pairTracker.Pair.Client; + Assert.That(client.IsAlive); + await client.WaitRunTicks(5); + Assert.That(client.IsAlive); + var cRuntimeLog = client.ResolveDependency(); + Assert.That(cRuntimeLog.ExceptionCount, Is.EqualTo(0), "No exceptions must be logged on client."); await client.WaitIdleAsync(); Assert.That(client.IsAlive); - client.RunTicks(5); - await client.WaitIdleAsync(); - Assert.That(client.IsAlive); - var runtimeLog = client.ResolveDependency(); - Assert.That(runtimeLog.ExceptionCount, Is.EqualTo(0), "No exceptions must be logged."); - client.Stop(); - await client.WaitIdleAsync(); - Assert.That(!client.IsAlive); + + var server = pairTracker.Pair.Server; + Assert.That(server.IsAlive); + var sRuntimeLog = server.ResolveDependency(); + Assert.That(sRuntimeLog.ExceptionCount, Is.EqualTo(0), "No exceptions must be logged on server."); + await server.WaitIdleAsync(); + Assert.That(server.IsAlive); + + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Station/StationJobsTest.cs b/Content.IntegrationTests/Tests/Station/StationJobsTest.cs index 476b4491a2..ac869002c2 100644 --- a/Content.IntegrationTests/Tests/Station/StationJobsTest.cs +++ b/Content.IntegrationTests/Tests/Station/StationJobsTest.cs @@ -6,7 +6,6 @@ using Content.Server.Maps; using Content.Server.Station.Systems; using Content.Shared.Preferences; using NUnit.Framework; -using Robust.Server; using Robust.Shared.GameObjects; using Robust.Shared.Log; using Robust.Shared.Map; @@ -18,7 +17,7 @@ namespace Content.IntegrationTests.Tests.Station; [TestFixture] [TestOf(typeof(StationJobsSystem))] -public sealed class StationJobsTest : ContentIntegrationTest +public sealed class StationJobsTest { private const string Prototypes = @" - type: gameMap @@ -64,13 +63,10 @@ public sealed class StationJobsTest : ContentIntegrationTest [Test] public async Task AssignJobsTest() { - var options = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes, Options = new ServerOptions() { LoadContentResources = false }}; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var prototypeManager = server.ResolveDependency(); - var mapManager = server.ResolveDependency(); var fooStationProto = prototypeManager.Index("FooStation"); var entSysMan = server.ResolveDependency().EntitySysManager; var stationJobs = entSysMan.GetEntitySystem(); @@ -79,7 +75,6 @@ public sealed class StationJobsTest : ContentIntegrationTest List stations = new(); await server.WaitPost(() => { - mapManager.CreateNewMapEntity(MapId.Nullspace); for (var i = 0; i < StationCount; i++) { stations.Add(stationSystem.InitializeNewStation(fooStationProto.Stations["Station"], null, $"Foo {StationCount}")); @@ -88,7 +83,6 @@ public sealed class StationJobsTest : ContentIntegrationTest await server.WaitAssertion(() => { - var fakePlayers = new Dictionary() .AddJob("TAssistant", JobPriority.Medium, PlayerCount) .AddPreference("TClown", JobPriority.Low) @@ -97,10 +91,12 @@ public sealed class StationJobsTest : ContentIntegrationTest new Dictionary() .AddJob("TCaptain", JobPriority.High, CaptainCount) ); + Assert.That(fakePlayers, Is.Not.Empty); var start = new Stopwatch(); start.Start(); var assigned = stationJobs.AssignJobs(fakePlayers, stations); + Assert.That(assigned, Is.Not.Empty); var time = start.Elapsed.TotalMilliseconds; Logger.Info($"Took {time} ms to distribute {TotalPlayers} players."); @@ -131,15 +127,14 @@ public sealed class StationJobsTest : ContentIntegrationTest // There must be captains present, too. Assert.That(assigned.Values.Select(x => x.Item1).ToList(), Does.Contain("TCaptain")); }); + await pairTracker.CleanReturnAsync(); } [Test] public async Task AdjustJobsTest() { - var options = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes, Options = new ServerOptions() { LoadContentResources = false }}; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var prototypeManager = server.ResolveDependency(); var mapManager = server.ResolveDependency(); @@ -155,6 +150,8 @@ public sealed class StationJobsTest : ContentIntegrationTest station = stationSystem.InitializeNewStation(fooStationProto.Stations["Station"], null, $"Foo Station"); }); + await server.WaitRunTicks(1); + await server.WaitAssertion(() => { // Verify jobs are/are not unlimited. @@ -182,6 +179,7 @@ public sealed class StationJobsTest : ContentIntegrationTest Assert.That(stationJobs.IsJobUnlimited(station, "TChaplain"), "Could not make TChaplain unlimited."); }); }); + await pairTracker.CleanReturnAsync(); } } diff --git a/Content.IntegrationTests/Tests/StationEvents/StationEventsSystemTest.cs b/Content.IntegrationTests/Tests/StationEvents/StationEventsSystemTest.cs index 7f58826680..ffd4e5f183 100644 --- a/Content.IntegrationTests/Tests/StationEvents/StationEventsSystemTest.cs +++ b/Content.IntegrationTests/Tests/StationEvents/StationEventsSystemTest.cs @@ -9,14 +9,15 @@ using Robust.Shared.Timing; namespace Content.IntegrationTests.Tests.StationEvents { [TestFixture] - public sealed class StationEventsSystemTest : ContentIntegrationTest + public sealed class StationEventsSystemTest { [Test] public async Task Test() { - var server = StartServer(); + await using var pairTracker = await PoolManager.GetServerClient(); + var server = pairTracker.Pair.Server; - server.Assert(() => + await server.WaitAssertion(() => { // Idle each event var stationEventsSystem = EntitySystem.Get(); @@ -42,7 +43,7 @@ namespace Content.IntegrationTests.Tests.StationEvents } }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/StorageFillTest.cs b/Content.IntegrationTests/Tests/StorageFillTest.cs index d0d22a2e57..1f2f4c4c60 100644 --- a/Content.IntegrationTests/Tests/StorageFillTest.cs +++ b/Content.IntegrationTests/Tests/StorageFillTest.cs @@ -7,13 +7,14 @@ using Robust.Shared.Prototypes; namespace Content.IntegrationTests.Tests { [TestFixture] - public sealed class StorageFillTest : ContentIntegrationTest + public sealed class StorageFillTest { [Test] public async Task TestStorageFillPrototypes() { - var server = StartServer(); - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; + var protoManager = server.ResolveDependency(); await server.WaitAssertion(() => @@ -29,6 +30,7 @@ namespace Content.IntegrationTests.Tests } } }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Tag/TagTest.cs b/Content.IntegrationTests/Tests/Tag/TagTest.cs index 36975ad62f..4a025f752c 100644 --- a/Content.IntegrationTests/Tests/Tag/TagTest.cs +++ b/Content.IntegrationTests/Tests/Tag/TagTest.cs @@ -11,7 +11,7 @@ namespace Content.IntegrationTests.Tests.Tag { [TestFixture] [TestOf(typeof(TagComponent))] - public sealed class TagTest : ContentIntegrationTest + public sealed class TagTest { private const string TagEntityId = "TagTestDummy"; @@ -44,15 +44,13 @@ namespace Content.IntegrationTests.Tests.Tag [Test] public async Task TagComponentTest() { - var options = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes}; - var server = StartServer(options); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var sMapManager = server.ResolveDependency(); var sEntityManager = server.ResolveDependency(); var sPrototypeManager = server.ResolveDependency(); - var tagSystem = server.ResolveDependency().GetEntitySystem(); + var entManager = server.ResolveDependency(); EntityUid sTagDummy = default; TagComponent sTagComponent = null!; @@ -66,6 +64,7 @@ namespace Content.IntegrationTests.Tests.Tag await server.WaitAssertion(() => { + var tagSystem = entManager.GetEntitySystem(); // Has one tag, the starting tag Assert.That(sTagComponent.Tags.Count, Is.EqualTo(1)); sPrototypeManager.Index(StartingTag); @@ -218,6 +217,7 @@ namespace Content.IntegrationTests.Tests.Tag // No tags left in the component Assert.That(sTagComponent.Tags, Is.Empty); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Utility/EntitySystemExtensionsTest.cs b/Content.IntegrationTests/Tests/Utility/EntitySystemExtensionsTest.cs index ac5e2589da..eb432c4c81 100644 --- a/Content.IntegrationTests/Tests/Utility/EntitySystemExtensionsTest.cs +++ b/Content.IntegrationTests/Tests/Utility/EntitySystemExtensionsTest.cs @@ -12,7 +12,7 @@ namespace Content.IntegrationTests.Tests.Utility { [TestFixture] [TestOf(typeof(EntitySystemExtensions))] - public sealed class EntitySystemExtensionsTest : ContentIntegrationTest + public sealed class EntitySystemExtensionsTest { private const string BlockerDummyId = "BlockerDummy"; @@ -34,10 +34,8 @@ namespace Content.IntegrationTests.Tests.Utility [Test] public async Task Test() { - var serverOptions = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes}; - var server = StartServer(serverOptions); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; var sMapManager = server.ResolveDependency(); var sEntityManager = server.ResolveDependency(); @@ -45,17 +43,17 @@ namespace Content.IntegrationTests.Tests.Utility await server.WaitAssertion(() => { - var grid = GetMainGrid(sMapManager); + var grid = PoolManager.GetMainGrid(sMapManager); var gridEnt = grid.GridEntityId; var gridPos = IoCManager.Resolve().GetComponent(gridEnt).WorldPosition; - var entityCoordinates = GetMainEntityCoordinates(sMapManager); + var entityCoordinates = PoolManager.GetMainEntityCoordinates(sMapManager); // Nothing blocking it, only entity is the grid Assert.NotNull(sEntityManager.SpawnIfUnobstructed(null, entityCoordinates, CollisionGroup.Impassable)); Assert.True(sEntityManager.TrySpawnIfUnobstructed(null, entityCoordinates, CollisionGroup.Impassable, out var entity)); Assert.NotNull(entity); - var mapId = GetMainMapId(sMapManager); + var mapId = PoolManager.GetMainGrid(sMapManager).ParentMapId; var mapCoordinates = new MapCoordinates(gridPos.X, gridPos.Y, mapId); // Nothing blocking it, only entity is the grid @@ -85,6 +83,7 @@ namespace Content.IntegrationTests.Tests.Utility Assert.True(sEntityManager.TrySpawnIfUnobstructed(null, mapCoordinates, CollisionGroup.MidImpassable, out entity)); Assert.NotNull(entity); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/Utility/EntityWhitelistTest.cs b/Content.IntegrationTests/Tests/Utility/EntityWhitelistTest.cs index f774caab9a..2003ecb336 100644 --- a/Content.IntegrationTests/Tests/Utility/EntityWhitelistTest.cs +++ b/Content.IntegrationTests/Tests/Utility/EntityWhitelistTest.cs @@ -10,7 +10,7 @@ namespace Content.IntegrationTests.Tests.Utility { [TestFixture] [TestOf(typeof(EntityWhitelist))] - public sealed class EntityWhitelistTest : ContentIntegrationTest + public sealed class EntityWhitelistTest { private const string InvalidComponent = "Sprite"; private const string ValidComponent = "Physics"; @@ -60,16 +60,15 @@ namespace Content.IntegrationTests.Tests.Utility [Test] public async Task Test() { - var serverOptions = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes}; - var server = StartServer(serverOptions); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, ExtraPrototypes = Prototypes}); + var server = pairTracker.Pair.Server; - await server.WaitIdleAsync(); var mapManager = server.ResolveDependency(); var sEntities = server.ResolveDependency(); await server.WaitAssertion(() => { - var mapId = GetMainMapId(mapManager); + var mapId = PoolManager.GetMainGrid(mapManager).ParentMapId; var mapCoordinates = new MapCoordinates(0, 0, mapId); var validComponent = sEntities.SpawnEntity("ValidComponentDummy", mapCoordinates); @@ -110,6 +109,7 @@ namespace Content.IntegrationTests.Tests.Utility Assert.That(whitelistSer.IsValid(invalidComponent), Is.False); Assert.That(whitelistSer.IsValid(invalidTag), Is.False); }); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.IntegrationTests/Tests/VendingMachineTest.cs b/Content.IntegrationTests/Tests/VendingMachineTest.cs index 877c024a7c..04f2e1be97 100644 --- a/Content.IntegrationTests/Tests/VendingMachineTest.cs +++ b/Content.IntegrationTests/Tests/VendingMachineTest.cs @@ -8,14 +8,15 @@ namespace Content.IntegrationTests.Tests { [TestFixture] [TestOf(typeof(VendingMachineInventoryPrototype))] - public sealed class VendingMachineTest : ContentIntegrationTest + public sealed class VendingMachineTest { [Test] public async Task Test() { - var server = StartServer(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; - server.Assert(() => + await server.WaitAssertion(() => { var prototypeManager = IoCManager.Resolve(); foreach (var vendorProto in prototypeManager.EnumeratePrototypes()) @@ -34,7 +35,7 @@ namespace Content.IntegrationTests.Tests } }); - await server.WaitIdleAsync(); + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.MapRenderer/Painters/MapPainter.cs b/Content.MapRenderer/Painters/MapPainter.cs index bd429ebb9c..fef117e5c8 100644 --- a/Content.MapRenderer/Painters/MapPainter.cs +++ b/Content.MapRenderer/Painters/MapPainter.cs @@ -20,39 +20,16 @@ using SpriteComponent = Robust.Server.GameObjects.SpriteComponent; namespace Content.MapRenderer.Painters { - public sealed class MapPainter : ContentIntegrationTest + public sealed class MapPainter { public async IAsyncEnumerable Paint(string map) { var stopwatch = new Stopwatch(); stopwatch.Start(); - var clientOptions = new ClientContentIntegrationOption - { - CVarOverrides = - { - [CVars.NetPVS.Name] = "false" - }, - Pool = false, - FailureLogLevel = LogLevel.Fatal - }; - - var serverOptions = new ServerContentIntegrationOption - { - CVarOverrides = - { - [CCVars.GameMap.Name] = map, - [CVars.NetPVS.Name] = "false" - }, - Pool = false, - FailureLogLevel = LogLevel.Fatal - }; - - var (client, server) = await StartConnectedServerClientPair(clientOptions, serverOptions); - - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); - await RunTicksSync(client, server, 10); - await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings(){ Map = map}); + var server = pairTracker.Pair.Server; + var client = pairTracker.Pair.Client; Console.WriteLine($"Loaded client and server in {(int) stopwatch.Elapsed.TotalMilliseconds} ms"); @@ -80,7 +57,7 @@ namespace Content.MapRenderer.Painters } }); - await RunTicksSync(client, server, 10); + await PoolManager.RunTicksSync(pairTracker.Pair, 10); await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); var sMapManager = server.ResolveDependency(); @@ -106,7 +83,7 @@ namespace Content.MapRenderer.Painters } }); - await RunTicksSync(client, server, 10); + await PoolManager.RunTicksSync(pairTracker.Pair, 10); await Task.WhenAll(client.WaitIdleAsync(), server.WaitIdleAsync()); foreach (var grid in grids) @@ -147,7 +124,7 @@ namespace Content.MapRenderer.Painters // We don't care if it fails as we have already saved the images. try { - await OneTimeTearDown(); + await pairTracker.CleanReturnAsync(); } catch { diff --git a/Content.Server/Station/Systems/StationJobsSystem.Roundstart.cs b/Content.Server/Station/Systems/StationJobsSystem.Roundstart.cs index ff78922267..554c40cece 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.Roundstart.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.Roundstart.cs @@ -53,6 +53,8 @@ public sealed partial class StationJobsSystem { DebugTools.Assert(stations.Count > 0); + InitializeRoundStart(); + if (profiles.Count == 0) return new Dictionary(); diff --git a/Content.Server/Station/Systems/StationJobsSystem.cs b/Content.Server/Station/Systems/StationJobsSystem.cs index bf582e0e37..bd48eb407d 100644 --- a/Content.Server/Station/Systems/StationJobsSystem.cs +++ b/Content.Server/Station/Systems/StationJobsSystem.cs @@ -32,8 +32,6 @@ public sealed partial class StationJobsSystem : EntitySystem SubscribeLocalEvent(OnStationDeletion); SubscribeLocalEvent(OnPlayerJoinedLobby); _configurationManager.OnValueChanged(CCVars.GameDisallowLateJoins, _ => UpdateJobsAvailable(), true); - - InitializeRoundStart(); } public override void Update(float _) diff --git a/Content.Server/StationEvents/Events/BureaucraticError.cs b/Content.Server/StationEvents/Events/BureaucraticError.cs index 525bab2aca..e9f9ed0b10 100644 --- a/Content.Server/StationEvents/Events/BureaucraticError.cs +++ b/Content.Server/StationEvents/Events/BureaucraticError.cs @@ -26,6 +26,7 @@ public sealed class BureaucraticError : StationEvent base.Startup(); var stationSystem = EntitySystem.Get(); var stationJobsSystem = EntitySystem.Get(); + if (stationSystem.Stations.Count == 0) return; // No stations var chosenStation = _random.Pick(stationSystem.Stations.ToList()); var jobList = stationJobsSystem.GetJobs(chosenStation).Keys.ToList(); diff --git a/Content.YAMLLinter/Program.cs b/Content.YAMLLinter/Program.cs index 289335f7cc..0a49e59517 100644 --- a/Content.YAMLLinter/Program.cs +++ b/Content.YAMLLinter/Program.cs @@ -11,7 +11,7 @@ using Robust.Shared.Utility; namespace Content.YAMLLinter { - internal class Program : ContentIntegrationTest + internal class Program { private static int Main(string[] args) { @@ -45,45 +45,36 @@ namespace Content.YAMLLinter private async Task>> ValidateClient() { - var client = StartClient(new ClientContentIntegrationOption() - { - FailureLogLevel = null, - }); - - await client.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{DummyTicker = true, Disconnected = true}); + var client = pairTracker.Pair.Client; var cPrototypeManager = client.ResolveDependency(); var clientErrors = new Dictionary>(); - await client.WaitAssertion(() => + await client.WaitPost(() => { clientErrors = cPrototypeManager.ValidateDirectory(new ResourcePath("/Prototypes")); }); - client.Stop(); + await pairTracker.CleanReturnAsync(); return clientErrors; } private async Task>> ValidateServer() { - var server = StartServer(new ServerContentIntegrationOption() - { - FailureLogLevel = null, - CVarOverrides = { {CCVars.GameDummyTicker.Name, "true"} } - }); - - await server.WaitIdleAsync(); + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{DummyTicker = true, Disconnected = true}); + var server = pairTracker.Pair.Server; var sPrototypeManager = server.ResolveDependency(); var serverErrors = new Dictionary>(); - await server.WaitAssertion(() => + await server.WaitPost(() => { serverErrors = sPrototypeManager.ValidateDirectory(new ResourcePath("/Prototypes")); }); - server.Stop(); + await pairTracker.CleanReturnAsync(); return serverErrors; } @@ -92,9 +83,8 @@ namespace Content.YAMLLinter { var allErrors = new Dictionary>(); - var tasks = await Task.WhenAll(ValidateClient(), ValidateServer()); - var clientErrors = tasks[0]; - var serverErrors = tasks[1]; + var serverErrors = await ValidateServer(); + var clientErrors = await ValidateClient(); foreach (var (key, val) in serverErrors) {