Make tests faster (#8737)

* Test changes

* Make finding the test tile a little smarter
This commit is contained in:
wrexbe
2022-06-19 20:22:28 -07:00
committed by GitHub
parent bd54b8de25
commit 81e3b2da88
80 changed files with 1769 additions and 1788 deletions

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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<IModLoader>().SetModuleBaseCallbacks(new ClientModuleTestingCallbacks
{
ClientBeforeIoC = () =>
{
if (options is ClientContentIntegrationOption contentOptions)
{
contentOptions.ContentBeforeIoC?.Invoke();
}
IoCManager.Register<IParallaxManager, DummyParallaxManager>(true);
IoCManager.Resolve<ILogManager>().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<IModLoader>().SetModuleBaseCallbacks(new ServerModuleTestingCallbacks
{
ServerBeforeIoC = () =>
{
if (options is ServerContentIntegrationOption contentOptions)
{
contentOptions.ContentBeforeIoC?.Invoke();
}
}
});
IoCManager.Resolve<ILogManager>().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<IClientNetManager>();
var prototypes = client.ResolveDependency<IPrototypeManager>();
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<IEntitySystemManager>();
var prototypes = server.ResolveDependency<IPrototypeManager>();
var net = server.ResolveDependency<IServerNetManager>();
var players = server.ResolveDependency<IPlayerManager>();
var gameTicker = systems.GetEntitySystem<GameTicker>();
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<bool> func, int maxTicks = 600,
int tickStep = 1)
{
await WaitUntil(instance, async () => await Task.FromResult(func()), maxTicks, tickStep);
}
protected async Task WaitUntil(IntegrationInstance instance, Func<Task<bool>> 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<IClientNetManager>().ClientConnect(null!, 0, null!));
await RunTicksSync(client, server, 10);
}
/// <summary>
/// Runs <paramref name="ticks"/> ticks on both server and client while keeping their main loop in sync.
/// </summary>
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; }
}
}
}

View File

@@ -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();
}
}

View File

@@ -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<Pair> Pairs = new();
private static async Task ConfigurePrototypes(RobustIntegrationTest.IntegrationInstance instance,
PoolSettings settings)
{
await instance.WaitPost(() =>
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
var changes = new Dictionary<Type, HashSet<string>>();
prototypeManager.LoadString(settings.ExtraPrototypes.Trim(), true, changes);
prototypeManager.ReloadPrototypes(changes);
});
}
private static async Task<RobustIntegrationTest.ServerIntegrationInstance> 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<IEntitySystemManager>()
.LoadExtraSystemType<SimplePredictReconcileTest.PredictionTestEntitySystem>();
IoCManager.Resolve<IComponentFactory>().RegisterClass<SimplePredictReconcileTest.PredictionTestComponent>();
IoCManager.Register<ResettingEntitySystemTests.TestRoundRestartCleanupEvent>();
IoCManager.Register<InteractionSystemTests.TestInteractionSystem>();
IoCManager.Register<DeviceNetworkTestSystem>();
IoCManager.Resolve<IEntitySystemManager>()
.LoadExtraSystemType<ResettingEntitySystemTests.TestRoundRestartCleanupEvent>();
IoCManager.Resolve<IEntitySystemManager>()
.LoadExtraSystemType<InteractionSystemTests.TestInteractionSystem>();
IoCManager.Resolve<IEntitySystemManager>().LoadExtraSystemType<DeviceNetworkTestSystem>();
IoCManager.Resolve<ILogManager>().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<RobustIntegrationTest.ClientIntegrationInstance> 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<IModLoader>().SetModuleBaseCallbacks(new ClientModuleTestingCallbacks
{
ClientBeforeIoC = () =>
{
IoCManager.Resolve<IEntitySystemManager>()
.LoadExtraSystemType<SimplePredictReconcileTest.PredictionTestEntitySystem>();
IoCManager.Resolve<IComponentFactory>()
.RegisterClass<SimplePredictReconcileTest.PredictionTestComponent>();
IoCManager.Register<IParallaxManager, DummyParallaxManager>(true);
IoCManager.Resolve<ILogManager>().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<PairTracker> 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<PairTracker> 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<IMapManager>();
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;
}
}
/// <summary>
/// Used after checking pairs, Don't use this directly
/// </summary>
/// <param name="pair"></param>
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<IConfigurationManager>();
await pair.Server.WaitPost(() =>
{
configManager.SetCVar(CCVars.GameLobbyEnabled, poolSettings.InLobby);
});
var cNetMgr = pair.Client.ResolveDependency<IClientNetManager>();
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<GameTicker>().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<IPrototypeManager>();
await pair.Server.WaitPost(() =>
{
serverProtoManager.RemoveString(pair.Settings.ExtraPrototypes.Trim());
});
}
if(!pair.Settings.NoClient)
{
var clientProtoManager = pair.Client.ResolveDependency<IPrototypeManager>();
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<GameTicker>().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<IClientNetManager>();
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<Pair> 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<IClientNetManager>();
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<bool> 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<Task<bool>> 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;
/// <summary>
/// We are going to ruin this pair
/// </summary>
public bool Destructive { get; init; }
/// <summary>
/// We need a brand new pair
/// </summary>
public bool Fresh { get; init; }
/// <summary>
/// We need a pair that uses a dummy ticker
/// </summary>
public bool DummyTicker { get; init; }
/// <summary>
/// We need the client, and server to be disconnected
/// </summary>
public bool Disconnected { get; init; }
/// <summary>
/// We need the server to be in the lobby
/// </summary>
public bool InLobby { get; init; }
/// <summary>
/// We don't want content loaded
/// </summary>
public bool NoLoadContent { get; init; }
/// <summary>
/// We want to add some prototypes
/// </summary>
public string ExtraPrototypes { get; init; }
/// <summary>
/// Disables NetInterp
/// </summary>
public bool DisableInterpolate { get; init; }
/// <summary>
/// Tells the pool it has to clean up before the server/client can be used.
/// </summary>
public bool Dirty { get; init; }
/// <summary>
/// Sets the map Cvar, and loads the map
/// </summary>
public string Map { get; init; } // TODO for map painter
/// <summary>
/// The test won't use the client (so we can skip cleaning it)
/// </summary>
public bool NoClient { get; init; }
/// <summary>
/// The test won't use the client (so we can skip cleaning it)
/// </summary>
public bool NoServer { get; init; }
/// <summary>
/// Guess if skipping recycling is ok
/// </summary>
/// <param name="nextSettings">The next set of settings the old pair will be set to</param>
/// <returns></returns>
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<string> 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<IRuntimeLog>();
if (sRuntimeLog.ExceptionCount > 0) throw new Exception("Server logged exceptions");
var cRuntimeLog = Pair.Client.ResolveDependency<IRuntimeLog>();
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");
}
}

View File

@@ -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();
}
}

View File

@@ -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<IPrototypeManager>();
var reflectionManager = server.ResolveDependency<IReflectionManager>();
@@ -56,6 +56,7 @@ namespace Content.IntegrationTests.Tests.AI
}
}
});
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<AccessReaderSystem>();
@@ -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();
}
}

View File

@@ -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<IEntityManager>();
var sMaps = server.ResolveDependency<IMapManager>();
var sSystems = server.ResolveDependency<IEntitySystemManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
@@ -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<IServerDbManager>();
var sEntities = server.ResolveDependency<IEntityManager>();
@@ -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<IEntityManager>();
var sMaps = server.ResolveDependency<IMapManager>();
var sSystems = server.ResolveDependency<IEntitySystemManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
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<IPlayerManager>();
var sSystems = server.ResolveDependency<IEntitySystemManager>();
@@ -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<IConfigurationManager>();
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<string>());
});
await server.WaitIdleAsync();
var sDatabase = server.ResolveDependency<IServerDbManager>();
var sSystems = server.ResolveDependency<IEntitySystemManager>();
@@ -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<IPlayerManager>();
var sSystems = server.ResolveDependency<IEntitySystemManager>();
@@ -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<IPlayerManager>();
var sSystems = server.ResolveDependency<IEntitySystemManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
@@ -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();
}
}

View File

@@ -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<IEntityManager>();
var sMaps = server.ResolveDependency<IMapManager>();
var sSystems = server.ResolveDependency<IEntitySystemManager>();
var sAdminLogSystem = server.ResolveDependency<IAdminLogManager>();
@@ -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();
}
}

View File

@@ -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<IEntitySystemManager>();
var sPlayers = server.ResolveDependency<IPlayerManager>();
@@ -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();
}
}

View File

@@ -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<IPrototypeManager>();
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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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<IEntitySystemManager>().GetEntitySystem<AtmosphereSystem>();
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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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<IMapLoader>();
var mapManager = server.ResolveDependency<IMapManager>();
@@ -173,7 +171,7 @@ namespace Content.IntegrationTests.Tests.Body
});
}
await server.WaitIdleAsync();
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<ActionBlockerSystem>();
var standingState = EntitySystem.Get<StandingStateSystem>();
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<IMapManager>();
var entityManager = IoCManager.Resolve<IEntityManager>();
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<IMapManager>();
var entityManager = IoCManager.Resolve<IEntityManager>();
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<TransformComponent>(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();
}
}
}

View File

@@ -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<IEntityManager>();
var mapManager = server.ResolveDependency<IMapManager>();
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<IEntityManager>();
var mapManager = server.ResolveDependency<IMapManager>();
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<IEntityManager>();
var mapManager = server.ResolveDependency<IMapManager>();
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<IEntityManager>();
var mapManager = server.ResolveDependency<IMapManager>();
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();
}
}

View File

@@ -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<IEntityManager>();
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
var mapManager = server.ResolveDependency<IMapManager>();
var coordinates = GetMainEntityCoordinates(mapManager);
var coordinates = PoolManager.GetMainEntityCoordinates(mapManager);
foreach (var reactionPrototype in prototypeManager.EnumeratePrototypes<ReactionPrototype>())
{
@@ -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<SolutionContainerSystem>()
@@ -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();
}
}

View File

@@ -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<bool> 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<IEntityManager>();
var serverEntManager = _server.ResolveDependency<IEntityManager>();
var eyeManager = _client.ResolveDependency<IEyeManager>();
var mapManager = _server.ResolveDependency<IMapManager>();
var clientEntManager = client.ResolveDependency<IEntityManager>();
var serverEntManager = server.ResolveDependency<IEntityManager>();
var eyeManager = client.ResolveDependency<IEyeManager>();
var mapManager = server.ResolveDependency<IMapManager>();
await _server.WaitPost(() =>
await server.WaitPost(() =>
{
var ent = serverEntManager.SpawnEntity(prototype, GetMainEntityCoordinates(mapManager));
var ent = serverEntManager.SpawnEntity(prototype, PoolManager.GetMainEntityCoordinates(mapManager));
serverEntManager.GetComponent<TransformComponent>(ent).WorldRotation = angle;
serverEntManager.GetComponent<SpriteComponent>(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;
}
}

View File

@@ -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<IPlayerManager>();
var sConsole = server.ResolveDependency<IServerConsoleHost>();
@@ -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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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<IConfigurationManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var gameTicker = entityManager.EntitySysManager.GetEntitySystem<GameTicker>();
await server.WaitRunTicks(30);
await PoolManager.RunTicksSync(pairTracker.Pair, 5);
GameTick tickBeforeRestart = default;
server.Assert(() =>
await server.WaitAssertion(() =>
{
Assert.That(configManager.GetCVar<bool>(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();
}
}
}

View File

@@ -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<IPrototypeManager>();
@@ -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<IPrototypeManager>();
@@ -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<IPrototypeManager>();
@@ -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();
}
}
}

View File

@@ -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<IPrototypeManager>();
@@ -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<IPrototypeManager>();
@@ -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<IPrototypeManager>();
@@ -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();
}
}
}

View File

@@ -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<IPlayerManager>().ServerSessions.Single().JoinGame();
var mapMan = IoCManager.Resolve<IMapManager>();
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<IEntityManager>();
EntityUid dummy = default;
s.Post(() =>
var ent2 = s.ResolveDependency<IMapManager>();
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<IEntityManager>();
var container = ent.SpawnEntity("ContainerOcclusionA", pos);
dummy = ent.SpawnEntity("ContainerOcclusionDummy", pos);
@@ -89,9 +55,9 @@ namespace Content.IntegrationTests.Tests
ent.GetComponent<EntityStorageComponent>(container).Insert(dummy);
});
await RunTicksSync(c, s, 5);
await PoolManager.RunTicksSync(pairTracker.Pair, 5);
c.Assert(() =>
await c.WaitAssertion(() =>
{
var sprite = cEntities.GetComponent<SpriteComponent>(dummy);
var light = cEntities.GetComponent<PointLightComponent>(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<IEntityManager>();
var ent2 = s.ResolveDependency<IMapManager>();
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<IEntityManager>();
var container = ent.SpawnEntity("ContainerOcclusionB", pos);
dummy = ent.SpawnEntity("ContainerOcclusionDummy", pos);
@@ -122,9 +90,9 @@ namespace Content.IntegrationTests.Tests
ent.GetComponent<EntityStorageComponent>(container).Insert(dummy);
});
await RunTicksSync(c, s, 5);
await PoolManager.RunTicksSync(pairTracker.Pair, 5);
c.Assert(() =>
await c.WaitAssertion(() =>
{
var sprite = cEntities.GetComponent<SpriteComponent>(dummy);
var light = cEntities.GetComponent<PointLightComponent>(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<IMapManager>();
var cEntities = c.ResolveDependency<IEntityManager>();
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<IEntityManager>();
var containerA = ent.SpawnEntity("ContainerOcclusionA", pos);
var containerB = ent.SpawnEntity("ContainerOcclusionB", pos);
@@ -157,9 +127,9 @@ namespace Content.IntegrationTests.Tests
ent.GetComponent<EntityStorageComponent>(containerB).Insert(dummy);
});
await RunTicksSync(c, s, 5);
await PoolManager.RunTicksSync(pairTracker.Pair, 5);
c.Assert(() =>
await c.WaitAssertion(() =>
{
var sprite = cEntities.GetComponent<SpriteComponent>(dummy);
var light = cEntities.GetComponent<PointLightComponent>(dummy);
@@ -167,7 +137,7 @@ namespace Content.IntegrationTests.Tests
Assert.True(light.ContainerOccluded);
});
await Task.WhenAll(c.WaitIdleAsync(), s.WaitIdleAsync());
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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()

View File

@@ -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<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
var sEntitySystemManager = server.ResolveDependency<IEntitySystemManager>();
sEntityManager.EventBus.SubscribeLocalEvent<DamageableComponent, DamageChangedEvent>(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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
@@ -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<IEntityManager>().GetComponent<DamageableComponent>(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();
}
}
}

View File

@@ -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<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
@@ -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<IEntityManager>().GetComponent<DamageableComponent>(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();
}
}
}

View File

@@ -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<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
@@ -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<TestDestructibleListenerSystem>();
@@ -87,6 +82,7 @@ namespace Content.IntegrationTests.Tests.Destructible
Assert.That(found, Is.True);
});
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
@@ -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<IEntityManager>().GetComponent<DamageableComponent>(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();
}
}
}

View File

@@ -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<IEntitySystemManager>().LoadExtraSystemType<DeviceNetworkTestSystem>();
}
};
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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
@@ -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<IEntitySystemManager>().LoadExtraSystemType<DeviceNetworkTestSystem>();
}
};
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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
@@ -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<IEntitySystemManager>().LoadExtraSystemType<DeviceNetworkTestSystem>();
}
};
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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
@@ -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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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<DoAfterStatus> 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<IGameTiming>().TickRate;
var mapManager = IoCManager.Resolve<IMapManager>();
@@ -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<DoAfterStatus> 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<IGameTiming>().TickRate;
var mapManager = IoCManager.Resolve<IMapManager>();
@@ -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();
}
}
}

View File

@@ -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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
@@ -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<DoorSystem>().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<DoorSystem>().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<IPhysBody>(airlock).WakeBody());
await server.WaitPost(() => entityManager.GetComponent<IPhysBody>(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<TransformComponent>(physicsDummy).MapPosition.X - 1) > 0.01f));
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IPrototypeManager>();
var resourceCache = client.ResolveDependency<IResourceCache>();
await client.WaitRunTicks(5);
await client.WaitAssertion(() =>
{
foreach (var proto in prototypeManager.EnumeratePrototypes<EntityPrototype>())
@@ -32,6 +33,8 @@ namespace Content.IntegrationTests.Tests
proto.ID);
}
});
await client.WaitRunTicks(5);
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IMapManager>();
var entityMan = server.ResolveDependency<IEntityManager>();
@@ -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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
@@ -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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
@@ -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<CompIdx> components, List<CompIdx> 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();
}
}
}

View File

@@ -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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
@@ -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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
@@ -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();
}
}

View File

@@ -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<IMapManager>();
var entitySystemManager = server.ResolveDependency<IEntitySystemManager>();
var spillSystem = entitySystemManager.GetEntitySystem<SpillableSystem>();
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<IMapManager>();
var entitySystemManager = server.ResolveDependency<IEntitySystemManager>();
@@ -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<IMapManager>();
var sTileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>();
@@ -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();
}
}
}

View File

@@ -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
{
/// <summary>
/// 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();
}
}

View File

@@ -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<IMapManager>();
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)

View File

@@ -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<IResourceManager>();
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<IComponentFactory>();
var ignoredServerNames = Server.Entry.IgnoredComponents.List;
var clientComponents = client.ResolveDependency<IComponentFactory>();
@@ -137,6 +140,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components
}
}
Assert.IsEmpty(failureMessages);
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IPlayerManager>();
var alertsSystem = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<AlertsSystem>();
@@ -39,7 +38,6 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs
await server.WaitRunTicks(5);
await client.WaitRunTicks(5);
var clientPlayerMgr = client.ResolveDependency<Robust.Client.Player.IPlayerManager>();
var clientUIMgr = client.ResolveDependency<IUserInterfaceManager>();
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();
}
}
}

View File

@@ -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<IMapManager>();
mapManager.CreateNewMapEntity(MapId.Nullspace);
@@ -69,7 +67,7 @@ namespace Content.IntegrationTests.Tests.GameObjects.Components.Movement
// climbing.IsClimbing = false;
});
await server.WaitIdleAsync();
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IConfigurationManager>();
await server.WaitPost(() =>
{
configManager.SetCVar(CCVars.GameLobbyEnabled, true);
var command = new RestartRoundNowCommand();
command.Execute(null, string.Empty, Array.Empty<string>());
});
await server.WaitIdleAsync();
var sGameTicker = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<GameTicker>();
var maxTimeMaxTimeRestartRuleSystem = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<MaxTimeRestartRuleSystem>();
@@ -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<string>());
});
await PoolManager.RunTicksSync(pairTracker.Pair, 30);
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
@@ -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<TransformComponent>(human).Coordinates);
generatorUid = entityManager.SpawnEntity("GravityGeneratorDummy", entityManager.GetComponent<TransformComponent>(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();
}
}
}

View File

@@ -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<IEntityManager>();
@@ -42,11 +40,11 @@ namespace Content.IntegrationTests.Tests
IMapGrid grid2 = null;
// Create grids
server.Assert(() =>
await server.WaitAssertion(() =>
{
var mapMan = IoCManager.Resolve<IMapManager>();
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<ApcPowerReceiverComponent>(generator);
powerComponent.NeedsPower = false;
});
server.RunTicks(1);
server.Assert(() =>
await server.WaitRunTicks(5);
await server.WaitAssertion(() =>
{
var generatorComponent = entityMan.GetComponent<GravityGeneratorComponent>(generator);
var powerComponent = entityMan.GetComponent<ApcPowerReceiverComponent>(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<GravityGeneratorComponent>(generator);
@@ -88,7 +89,7 @@ namespace Content.IntegrationTests.Tests
Assert.That(entityMan.GetComponent<GravityComponent>(grid2Entity).Enabled, Is.False);
});
await server.WaitIdleAsync();
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IEntitySystemManager>().GetEntitySystem<InventorySystem>();
var mapMan = IoCManager.Resolve<IMapManager>();
@@ -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)

View File

@@ -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<IEntitySystemManager>().LoadExtraSystemType<TestInteractionSystem>();
}
});
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<IEntityManager>();
var mapManager = server.ResolveDependency<IMapManager>();
@@ -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<HandsComponent>();
@@ -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<IEntitySystemManager>().LoadExtraSystemType<TestInteractionSystem>();
},
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<IEntityManager>();
var mapManager = server.ResolveDependency<IMapManager>();
@@ -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<HandsComponent>();
@@ -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<IEntitySystemManager>().LoadExtraSystemType<TestInteractionSystem>();
}
});
await server.WaitIdleAsync();
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true});
var server = pairTracker.Pair.Server;
var sEntities = server.ResolveDependency<IEntityManager>();
var mapManager = server.ResolveDependency<IMapManager>();
@@ -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<HandsComponent>();
@@ -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<IEntitySystemManager>().LoadExtraSystemType<TestInteractionSystem>();
}
});
await server.WaitIdleAsync();
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true});
var server = pairTracker.Pair.Server;
var sEntities = server.ResolveDependency<IEntityManager>();
var mapManager = server.ResolveDependency<IMapManager>();
@@ -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<HandsComponent>();
@@ -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<IEntitySystemManager>().LoadExtraSystemType<TestInteractionSystem>();
},
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<IEntityManager>();
var mapManager = server.ResolveDependency<IMapManager>();
@@ -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<HandsComponent>();
@@ -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<TransformComponent>(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<HandsComponent, ClickAttackEvent>? AttackEvent;
public EntityEventHandler<InteractUsingEvent>? InteractUsingEvent;

View File

@@ -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<IEntityManager>();
var mapManager = server.ResolveDependency<IMapManager>();
@@ -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<IEntitySystemManager>().GetEntitySystem<SharedInteractionSystem>();
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();
}
}
}

View File

@@ -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<IEntityManager>();
@@ -89,6 +87,7 @@ namespace Content.IntegrationTests.Tests
ID: "InventoryIDCardDummy"
});
});
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IClientNetManager>();
var clientStateManager = client.ResolveDependency<IStateManager>();
var clientPrefManager = client.ResolveDependency<IClientPreferencesManager>();
var serverConfig = server.ResolveDependency<IConfigurationManager>();
var serverTicker = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<GameTicker>();
var serverPrefManager = server.ResolveDependency<IServerPreferencesManager>();
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();
}
}
}

View File

@@ -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<IServerEntityManager>();
EntityUid playerEnt = default;
EntityUid visitEnt = default;
Mind mind = null;
server.Assert(() =>
await server.WaitAssertion(() =>
{
var player = IoCManager.Resolve<IPlayerManager>().ServerSessions.Single();
var mapMan = IoCManager.Resolve<IMapManager>();
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<IServerEntityManager>();
EntityUid playerEnt = default;
Mind mind = null;
server.Assert(() =>
await server.WaitAssertion(() =>
{
var player = IoCManager.Resolve<IPlayerManager>().ServerSessions.Single();
var mapMan = IoCManager.Resolve<IMapManager>();
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<IPlayerManager>().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<IMapManager>();
mapMan.DeleteMap(map);
});
server.RunTicks(1);
await PoolManager.RunTicksSync(pairTracker.Pair, 5);
server.Assert(() =>
await server.WaitAssertion(() =>
{
Assert.That(IoCManager.Resolve<IEntityManager>().EntityExists(mind.CurrentEntity!.Value), Is.True);
Assert.That(mind.CurrentEntity, Is.Not.EqualTo(playerEnt));
});
await server.WaitIdleAsync();
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IClientNetManager>().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.

View File

@@ -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<IComponentFactory>();
var serverCompFactory = server.ResolveDependency<IComponentFactory>();
@@ -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<IClientNetManager>().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();
}
}
}

View File

@@ -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<IClientNetManager>().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<IClientConsoleHost>().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<IClientNetManager>().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();
}
}
}

View File

@@ -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<IEntitySystemManager>().LoadExtraSystemType<PredictionTestEntitySystem>();
IoCManager.Resolve<IComponentFactory>().RegisterClass<PredictionTestComponent>();
}
},
new ServerContentIntegrationOption
{
CVarOverrides =
{
{CVars.NetPVS.Name, "false"}
},
ContentBeforeIoC = () =>
{
IoCManager.Resolve<IEntitySystemManager>().LoadExtraSystemType<PredictionTestEntitySystem>();
IoCManager.Resolve<IComponentFactory>().RegisterClass<PredictionTestComponent>();
}
});
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<IPlayerManager>();
@@ -85,7 +57,7 @@ namespace Content.IntegrationTests.Tests.Networking
var clientSystem = client.ResolveDependency<IEntitySystemManager>()
.GetEntitySystem<PredictionTestEntitySystem>();
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;

View File

@@ -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<IResourceManager>();
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<string[]> 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<IResourceManager>();
var mapFolder = new ResourcePath("/Maps");
var maps = resourceManager
.ContentFindFiles(mapFolder)
.Where(filePath => filePath.Extension == "yml" && !filePath.Filename.StartsWith("."))
.ToArray();
var mapNames = new List<string>();
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<IMapLoader>();
var mapManager = server.ResolveDependency<IMapManager>();
var resourceManager = server.ResolveDependency<IResourceManager>();
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();
}
}
}

View File

@@ -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<IMapManager>();
_entityManager = _server.ResolveDependency<IEntityManager>();
_gameTiming = _server.ResolveDependency<IGameTiming>();
_extensionCableSystem = _entityManager.EntitySysManager.GetEntitySystem<ExtensionCableSystem>();
}
/// <summary>
/// Test small power net with a simple surplus of power over the loads.
/// </summary>
[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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
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<PowerSupplierComponent>(generatorEnt);
consumer1 = _entityManager.GetComponent<PowerConsumerComponent>(consumerEnt1);
consumer2 = _entityManager.GetComponent<PowerConsumerComponent>(consumerEnt2);
supplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
consumer1 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt1);
consumer2 = entityManager.GetComponent<PowerConsumerComponent>(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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
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<PowerSupplierComponent>(generatorEnt);
consumer1 = _entityManager.GetComponent<PowerConsumerComponent>(consumerEnt1);
consumer2 = _entityManager.GetComponent<PowerConsumerComponent>(consumerEnt2);
supplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
consumer1 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt1);
consumer2 = entityManager.GetComponent<PowerConsumerComponent>(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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var gameTiming = server.ResolveDependency<IGameTiming>();
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<PowerSupplierComponent>(generatorEnt);
consumer = _entityManager.GetComponent<PowerConsumerComponent>(consumerEnt);
supplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
consumer = entityManager.GetComponent<PowerConsumerComponent>(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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var gameTiming = server.ResolveDependency<IGameTiming>();
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<PowerNetworkBatteryComponent>(generatorEnt);
battery = _entityManager.GetComponent<BatteryComponent>(generatorEnt);
consumer = _entityManager.GetComponent<PowerConsumerComponent>(consumerEnt);
netBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(generatorEnt);
battery = entityManager.GetComponent<BatteryComponent>(generatorEnt);
consumer = entityManager.GetComponent<PowerConsumerComponent>(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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
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<PowerSupplierComponent>(generatorEnt);
var netBattery = _entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt);
battery = _entityManager.GetComponent<BatteryComponent>(batteryEnt);
supplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
var netBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt);
battery = entityManager.GetComponent<BatteryComponent>(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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var gameTiming = server.ResolveDependency<IGameTiming>();
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<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1));
entityManager.GetComponent<TransformComponent>(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<PowerConsumerComponent>(consumerEnt);
supplier = _entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
netBattery = _entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt);
battery = _entityManager.GetComponent<BatteryComponent>(batteryEnt);
consumer = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt);
supplier = entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
netBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt);
battery = entityManager.GetComponent<BatteryComponent>(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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var gameTiming = server.ResolveDependency<IGameTiming>();
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<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1));
entityManager.GetComponent<TransformComponent>(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<PowerConsumerComponent>(consumerEnt);
supplier = _entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
netBattery = _entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt);
battery = _entityManager.GetComponent<BatteryComponent>(batteryEnt);
consumer = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt);
supplier = entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
netBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt);
battery = entityManager.GetComponent<BatteryComponent>(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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
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<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2));
var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2));
entityManager.GetComponent<TransformComponent>(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<PowerConsumerComponent>(consumerEnt1);
consumer2 = _entityManager.GetComponent<PowerConsumerComponent>(consumerEnt2);
supplier = _entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
var netBattery1 = _entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt1);
var netBattery2 = _entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt2);
var battery1 = _entityManager.GetComponent<BatteryComponent>(batteryEnt1);
var battery2 = _entityManager.GetComponent<BatteryComponent>(batteryEnt2);
consumer1 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt1);
consumer2 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt2);
supplier = entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
var netBattery1 = entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt1);
var netBattery2 = entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt2);
var battery1 = entityManager.GetComponent<BatteryComponent>(batteryEnt1);
var battery2 = entityManager.GetComponent<BatteryComponent>(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();
}
/// <summary>
@@ -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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
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<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2));
var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 2));
entityManager.GetComponent<TransformComponent>(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<PowerConsumerComponent>(consumerEnt1);
consumer2 = _entityManager.GetComponent<PowerConsumerComponent>(consumerEnt2);
supplier = _entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
var netBattery1 = _entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt1);
var netBattery2 = _entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt2);
var battery1 = _entityManager.GetComponent<BatteryComponent>(batteryEnt1);
var battery2 = _entityManager.GetComponent<BatteryComponent>(batteryEnt2);
consumer1 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt1);
consumer2 = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt2);
supplier = entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
var netBattery1 = entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt1);
var netBattery2 = entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt2);
var battery1 = entityManager.GetComponent<BatteryComponent>(batteryEnt1);
var battery2 = entityManager.GetComponent<BatteryComponent>(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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
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<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1));
entityManager.GetComponent<TransformComponent>(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<PowerConsumerComponent>(consumerEnt);
supplier = _entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
netBattery = _entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt);
var battery = _entityManager.GetComponent<BatteryComponent>(batteryEnt);
consumer = entityManager.GetComponent<PowerConsumerComponent>(consumerEnt);
supplier = entityManager.GetComponent<PowerSupplierComponent>(supplyEnt);
netBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(batteryEnt);
var battery = entityManager.GetComponent<BatteryComponent>(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();
}
/// <summary>
@@ -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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
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<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var terminal = entityManager.SpawnEntity("CableTerminal", grid.ToCoordinates(0, 1));
entityManager.GetComponent<TransformComponent>(terminal).LocalRotation = Angle.FromDegrees(180);
var battery = _entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 2));
var batteryNodeContainer = _entityManager.GetComponent<NodeContainerComponent>(battery);
var battery = entityManager.SpawnEntity("FullBatteryDummy", grid.ToCoordinates(0, 2));
var batteryNodeContainer = entityManager.GetComponent<NodeContainerComponent>(battery);
leftNode = _entityManager.GetComponent<NodeContainerComponent>(leftEnt).GetNode<CableNode>("power");
rightNode = _entityManager.GetComponent<NodeContainerComponent>(rightEnt).GetNode<CableNode>("power");
leftNode = entityManager.GetComponent<NodeContainerComponent>(leftEnt).GetNode<CableNode>("power");
rightNode = entityManager.GetComponent<NodeContainerComponent>(rightEnt).GetNode<CableNode>("power");
batteryInput = batteryNodeContainer.GetNode<Node>("input");
batteryOutput = batteryNodeContainer.GetNode<Node>("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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
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<PowerSupplierComponent>(generatorEnt);
substationNetBattery = _entityManager.GetComponent<PowerNetworkBatteryComponent>(substationEnt);
apcBattery = _entityManager.GetComponent<BatteryComponent>(apcEnt);
var generatorSupplier = entityManager.GetComponent<PowerSupplierComponent>(generatorEnt);
substationNetBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(substationEnt);
apcBattery = entityManager.GetComponent<BatteryComponent>(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<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var extensionCableSystem = entityManager.EntitySysManager.GetEntitySystem<ExtensionCableSystem>();
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<ApcPowerReceiverComponent>(powerReceiverEnt);
var battery = _entityManager.GetComponent<BatteryComponent>(apcEnt);
apcNetBattery = _entityManager.GetComponent<PowerNetworkBatteryComponent>(apcEnt);
receiver = entityManager.GetComponent<ApcPowerReceiverComponent>(powerReceiverEnt);
var battery = entityManager.GetComponent<BatteryComponent>(apcEnt);
apcNetBattery = entityManager.GetComponent<PowerNetworkBatteryComponent>(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();
}
}
}

View File

@@ -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<IEntitySystemManager>().LoadExtraSystemType<TestRoundRestartCleanupEvent>();
}
});
await server.WaitIdleAsync();
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true});
var server = pairTracker.Pair.Server;
var entitySystemManager = server.ResolveDependency<IEntitySystemManager>();
var gameTicker = entitySystemManager.GetEntitySystem<GameTicker>();
@@ -60,6 +53,7 @@ namespace Content.IntegrationTests.Tests
Assert.True(system.HasBeenReset);
});
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IEntitySystemManager>().GetEntitySystem<GameTicker>().RestartRound();
});
await RunTicksSync(client, server, 10);
await PoolManager.RunTicksSync(pairTracker.Pair, 10);
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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<IMapLoader>();
var mapManager = server.ResolveDependency<IMapManager>();
var sEntities = server.ResolveDependency<IEntityManager>();
var resManager = server.ResolveDependency<IResourceManager>();
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();
}
}
}

View File

@@ -14,16 +14,16 @@ namespace Content.IntegrationTests.Tests
/// Tests that the
/// </summary>
[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<IMapLoader>();
var mapManager = server.ResolveDependency<IMapManager>();
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();
}
/// <summary>
@@ -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<IMapLoader>();
var mapManager = server.ResolveDependency<IMapManager>();
@@ -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();
}
}
}

View File

@@ -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<IMapManager>();
var sEntities = server.ResolveDependency<IEntityManager>();
@@ -43,6 +42,7 @@ namespace Content.IntegrationTests.Tests
{
Assert.That<Vector2?>(sEntities.GetComponent<TransformComponent>(gridEnt).LocalPosition, Is.Not.EqualTo(Vector2.Zero));
});
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -5,48 +5,32 @@ using Robust.Shared.Exceptions;
namespace Content.IntegrationTests.Tests
{
[TestFixture]
public sealed class StartTest : ContentIntegrationTest
public sealed class StartTest
{
/// <summary>
/// Test that the server starts.
/// </summary>
[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<IRuntimeLog>();
Assert.That(runtimeLog.ExceptionCount, Is.EqualTo(0), "No exceptions must be logged.");
server.Stop();
await server.WaitIdleAsync();
Assert.That(!server.IsAlive);
}
/// <summary>
/// Test that the client starts.
/// Test that the server, and client start, and stop.
/// </summary>
[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<IRuntimeLog>();
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<IRuntimeLog>();
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<IRuntimeLog>();
Assert.That(sRuntimeLog.ExceptionCount, Is.EqualTo(0), "No exceptions must be logged on server.");
await server.WaitIdleAsync();
Assert.That(server.IsAlive);
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IPrototypeManager>();
var mapManager = server.ResolveDependency<IMapManager>();
var fooStationProto = prototypeManager.Index<GameMapPrototype>("FooStation");
var entSysMan = server.ResolveDependency<IEntityManager>().EntitySysManager;
var stationJobs = entSysMan.GetEntitySystem<StationJobsSystem>();
@@ -79,7 +75,6 @@ public sealed class StationJobsTest : ContentIntegrationTest
List<EntityUid> 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<NetUserId, HumanoidCharacterProfile>()
.AddJob("TAssistant", JobPriority.Medium, PlayerCount)
.AddPreference("TClown", JobPriority.Low)
@@ -97,10 +91,12 @@ public sealed class StationJobsTest : ContentIntegrationTest
new Dictionary<NetUserId, HumanoidCharacterProfile>()
.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<IPrototypeManager>();
var mapManager = server.ResolveDependency<IMapManager>();
@@ -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();
}
}

View File

@@ -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<StationEventSystem>();
@@ -42,7 +43,7 @@ namespace Content.IntegrationTests.Tests.StationEvents
}
});
await server.WaitIdleAsync();
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IPrototypeManager>();
await server.WaitAssertion(() =>
@@ -29,6 +30,7 @@ namespace Content.IntegrationTests.Tests
}
}
});
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<IMapManager>();
var sEntityManager = server.ResolveDependency<IEntityManager>();
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
var tagSystem = server.ResolveDependency<IEntitySystemManager>().GetEntitySystem<TagSystem>();
var entManager = server.ResolveDependency<IEntitySystemManager>();
EntityUid sTagDummy = default;
TagComponent sTagComponent = null!;
@@ -66,6 +64,7 @@ namespace Content.IntegrationTests.Tests.Tag
await server.WaitAssertion(() =>
{
var tagSystem = entManager.GetEntitySystem<TagSystem>();
// Has one tag, the starting tag
Assert.That(sTagComponent.Tags.Count, Is.EqualTo(1));
sPrototypeManager.Index<TagPrototype>(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();
}
}
}

View File

@@ -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<IMapManager>();
var sEntityManager = server.ResolveDependency<IEntityManager>();
@@ -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<IEntityManager>().GetComponent<TransformComponent>(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();
}
}
}

View File

@@ -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<IMapManager>();
var sEntities = server.ResolveDependency<IEntityManager>();
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();
}
}
}

View File

@@ -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<IPrototypeManager>();
foreach (var vendorProto in prototypeManager.EnumeratePrototypes<VendingMachineInventoryPrototype>())
@@ -34,7 +35,7 @@ namespace Content.IntegrationTests.Tests
}
});
await server.WaitIdleAsync();
await pairTracker.CleanReturnAsync();
}
}
}

View File

@@ -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<Image> 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<IMapManager>();
@@ -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
{

View File

@@ -53,6 +53,8 @@ public sealed partial class StationJobsSystem
{
DebugTools.Assert(stations.Count > 0);
InitializeRoundStart();
if (profiles.Count == 0)
return new Dictionary<NetUserId, (string, EntityUid)>();

View File

@@ -32,8 +32,6 @@ public sealed partial class StationJobsSystem : EntitySystem
SubscribeLocalEvent<StationJobsComponent, ComponentShutdown>(OnStationDeletion);
SubscribeLocalEvent<PlayerJoinedLobbyEvent>(OnPlayerJoinedLobby);
_configurationManager.OnValueChanged(CCVars.GameDisallowLateJoins, _ => UpdateJobsAvailable(), true);
InitializeRoundStart();
}
public override void Update(float _)

View File

@@ -26,6 +26,7 @@ public sealed class BureaucraticError : StationEvent
base.Startup();
var stationSystem = EntitySystem.Get<StationSystem>();
var stationJobsSystem = EntitySystem.Get<StationJobsSystem>();
if (stationSystem.Stations.Count == 0) return; // No stations
var chosenStation = _random.Pick(stationSystem.Stations.ToList());
var jobList = stationJobsSystem.GetJobs(chosenStation).Keys.ToList();

View File

@@ -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<Dictionary<string, HashSet<ErrorNode>>> 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<IPrototypeManager>();
var clientErrors = new Dictionary<string, HashSet<ErrorNode>>();
await client.WaitAssertion(() =>
await client.WaitPost(() =>
{
clientErrors = cPrototypeManager.ValidateDirectory(new ResourcePath("/Prototypes"));
});
client.Stop();
await pairTracker.CleanReturnAsync();
return clientErrors;
}
private async Task<Dictionary<string, HashSet<ErrorNode>>> 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<IPrototypeManager>();
var serverErrors = new Dictionary<string, HashSet<ErrorNode>>();
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<string, HashSet<ErrorNode>>();
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)
{