Improve test stability (#10913)
This commit is contained in:
@@ -766,6 +766,7 @@ public sealed class PairTracker : IAsyncDisposable
|
|||||||
{
|
{
|
||||||
Pair.Client.Dispose();
|
Pair.Client.Dispose();
|
||||||
Pair.Server.Dispose();
|
Pair.Server.Dispose();
|
||||||
|
await PoolManager.ReallyBeIdle(Pair);
|
||||||
var returnTime2 = cleanWatch.Elapsed;
|
var returnTime2 = cleanWatch.Elapsed;
|
||||||
await TestContext.Out.WriteLineAsync($"{nameof(CleanReturnAsync)}: Clean disposed in {returnTime2.TotalMilliseconds} ms");
|
await TestContext.Out.WriteLineAsync($"{nameof(CleanReturnAsync)}: Clean disposed in {returnTime2.TotalMilliseconds} ms");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Content.Shared.CCVar;
|
|||||||
using Content.Shared.Coordinates;
|
using Content.Shared.Coordinates;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Log;
|
using Robust.Shared.Log;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
@@ -18,79 +19,89 @@ namespace Content.IntegrationTests.Tests
|
|||||||
public sealed class EntityTest
|
public sealed class EntityTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public async Task SpawnTest()
|
public async Task SpawnAndDeleteAllEntitiesOnDifferentMaps()
|
||||||
{
|
{
|
||||||
//TODO: Run this test in a for loop, and figure out why garbage is ending up in the Entities list on cleanup.
|
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, Destructive = true});
|
||||||
//If this gets fixed, see also UninitializedSaveTest.
|
|
||||||
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, Dirty = true, Destructive = true});
|
|
||||||
var server = pairTracker.Pair.Server;
|
var server = pairTracker.Pair.Server;
|
||||||
|
|
||||||
var mapManager = server.ResolveDependency<IMapManager>();
|
IEntityManager entityMan = null;
|
||||||
var entityMan = server.ResolveDependency<IEntityManager>();
|
|
||||||
var prototypeMan = server.ResolveDependency<IPrototypeManager>();
|
|
||||||
var tileDefinitionManager = server.ResolveDependency<ITileDefinitionManager>();
|
|
||||||
|
|
||||||
var prototypes = new List<EntityPrototype>();
|
|
||||||
IMapGrid grid = default;
|
|
||||||
EntityUid testEntity;
|
|
||||||
|
|
||||||
//Build up test environment
|
|
||||||
await server.WaitPost(() =>
|
await server.WaitPost(() =>
|
||||||
{
|
{
|
||||||
// Create a one tile grid to stave off the grid 0 monsters
|
entityMan = IoCManager.Resolve<IEntityManager>();
|
||||||
var mapId = mapManager.CreateMap();
|
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||||
|
var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
|
||||||
mapManager.AddUninitializedMap(mapId);
|
var protoIds = prototypeMan
|
||||||
|
.EnumeratePrototypes<EntityPrototype>()
|
||||||
grid = mapManager.CreateGrid(mapId);
|
.Where(p=>!p.Abstract)
|
||||||
|
.Select(p => p.ID)
|
||||||
var tileDefinition = tileDefinitionManager["UnderPlating"];
|
.ToList();
|
||||||
var tile = new Tile(tileDefinition.TileId);
|
foreach (var protoId in protoIds)
|
||||||
var coordinates = grid.ToCoordinates();
|
{
|
||||||
|
var mapId = mapManager.CreateMap();
|
||||||
grid.SetTile(coordinates, tile);
|
var grid = mapManager.CreateGrid(mapId);
|
||||||
|
var coord = new EntityCoordinates(grid.GridEntityId, 0, 0);
|
||||||
mapManager.DoMapInitialize(mapId);
|
entityMan.SpawnEntity(protoId, coord);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await server.WaitRunTicks(5);
|
await server.WaitRunTicks(5);
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitPost(() =>
|
||||||
{
|
{
|
||||||
var testLocation = grid.ToCoordinates();
|
var entityMetas = entityMan.EntityQuery<MetaDataComponent>().ToList();
|
||||||
|
foreach (var meta in entityMetas)
|
||||||
//Generate list of non-abstract prototypes to test
|
|
||||||
foreach (var prototype in prototypeMan.EnumeratePrototypes<EntityPrototype>())
|
|
||||||
{
|
{
|
||||||
if (prototype.Abstract)
|
if(!entityMan.Deleted(meta.Owner))
|
||||||
{
|
entityMan.DeleteEntity(meta.Owner);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
prototypes.Add(prototype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
Assert.That(entityMan.EntityCount, Is.Zero);
|
||||||
{
|
|
||||||
//Iterate list of prototypes to spawn
|
|
||||||
foreach (var prototype in prototypes)
|
|
||||||
{
|
|
||||||
Assert.DoesNotThrow(() =>
|
|
||||||
{
|
|
||||||
Logger.LogS(LogLevel.Debug, "EntityTest", $"Testing: {prototype.ID}");
|
|
||||||
testEntity = entityMan.SpawnEntity(prototype.ID, testLocation);
|
|
||||||
server.RunTicks(1);
|
|
||||||
if(!entityMan.Deleted(testEntity))
|
|
||||||
entityMan.DeleteEntity(testEntity);
|
|
||||||
}, "Entity '{0}' threw an exception.",
|
|
||||||
prototype.ID);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await pairTracker.CleanReturnAsync();
|
await pairTracker.CleanReturnAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task SpawnAndDeleteAllEntitiesInTheSameSpot()
|
||||||
|
{
|
||||||
|
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true, Destructive = true});
|
||||||
|
var server = pairTracker.Pair.Server;
|
||||||
|
|
||||||
|
IEntityManager entityMan = null;
|
||||||
|
|
||||||
|
await server.WaitPost(() =>
|
||||||
|
{
|
||||||
|
entityMan = IoCManager.Resolve<IEntityManager>();
|
||||||
|
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||||
|
|
||||||
|
var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
var protoIds = prototypeMan
|
||||||
|
.EnumeratePrototypes<EntityPrototype>()
|
||||||
|
.Where(p=>!p.Abstract)
|
||||||
|
.Select(p => p.ID)
|
||||||
|
.ToList();
|
||||||
|
var mapId = mapManager.CreateMap();
|
||||||
|
var grid = mapManager.CreateGrid(mapId);
|
||||||
|
var coord = new EntityCoordinates(grid.GridEntityId, 0, 0);
|
||||||
|
foreach (var protoId in protoIds)
|
||||||
|
{
|
||||||
|
entityMan.SpawnEntity(protoId, coord);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await server.WaitRunTicks(5);
|
||||||
|
await server.WaitPost(() =>
|
||||||
|
{
|
||||||
|
var entityMetas = entityMan.EntityQuery<MetaDataComponent>().ToList();
|
||||||
|
foreach (var meta in entityMetas)
|
||||||
|
{
|
||||||
|
if(!entityMan.Deleted(meta.Owner))
|
||||||
|
entityMan.DeleteEntity(meta.Owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.That(entityMan.EntityCount, Is.Zero);
|
||||||
|
});
|
||||||
|
await pairTracker.CleanReturnAsync();
|
||||||
|
}
|
||||||
[Test]
|
[Test]
|
||||||
public async Task AllComponentsOneToOneDeleteTest()
|
public async Task AllComponentsOneToOneDeleteTest()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -445,10 +445,11 @@ namespace Content.Server.AI.Pathfinding.Accessible
|
|||||||
var parentChunk = node.ParentChunk;
|
var parentChunk = node.ParentChunk;
|
||||||
|
|
||||||
// No guarantee the node even has a region yet (if we're doing neighbor lookups)
|
// No guarantee the node even has a region yet (if we're doing neighbor lookups)
|
||||||
if (!_regions[parentChunk.GridId].TryGetValue(parentChunk, out var regions))
|
if (!_regions.TryGetValue(parentChunk.GridId, out var chunk))
|
||||||
{
|
return null;
|
||||||
|
|
||||||
|
if (!chunk.TryGetValue(parentChunk, out var regions))
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var region in regions)
|
foreach (var region in regions)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ public sealed partial class TriggerSystem
|
|||||||
//Ensures the entity trigger will have an active component
|
//Ensures the entity trigger will have an active component
|
||||||
EnsureComp<ActiveTriggerOnTimedCollideComponent>(uid);
|
EnsureComp<ActiveTriggerOnTimedCollideComponent>(uid);
|
||||||
var otherUID = args.OtherFixture.Body.Owner;
|
var otherUID = args.OtherFixture.Body.Owner;
|
||||||
|
if (component.Colliding.ContainsKey(otherUID))
|
||||||
|
return;
|
||||||
component.Colliding.Add(otherUID, 0);
|
component.Colliding.Add(otherUID, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,8 @@ public sealed class StationSystem : EntitySystem
|
|||||||
private void OnStationDeleted(EntityUid uid, StationDataComponent component, ComponentShutdown args)
|
private void OnStationDeleted(EntityUid uid, StationDataComponent component, ComponentShutdown args)
|
||||||
{
|
{
|
||||||
if (_stations.Contains(uid) && // Was not deleted via DeleteStation()
|
if (_stations.Contains(uid) && // Was not deleted via DeleteStation()
|
||||||
_gameTicker.RunLevel == GameRunLevel.InRound) // And not due to a round restart
|
_gameTicker.RunLevel == GameRunLevel.InRound && // And not due to a round restart
|
||||||
|
_gameTicker.LobbyEnabled) // If there isn't a lobby, this is probably sandbox, single player, or a test
|
||||||
{
|
{
|
||||||
// printing a stack trace, rather than throwing an exception so that entity deletion continues as normal.
|
// printing a stack trace, rather than throwing an exception so that entity deletion continues as normal.
|
||||||
Logger.Error($"Station entity {ToPrettyString(uid)} is getting deleted mid-round. Trace: {Environment.StackTrace}");
|
Logger.Error($"Station entity {ToPrettyString(uid)} is getting deleted mid-round. Trace: {Environment.StackTrace}");
|
||||||
|
|||||||
@@ -395,7 +395,8 @@ namespace Content.Shared.Body.Components
|
|||||||
var gibs = new HashSet<EntityUid>();
|
var gibs = new HashSet<EntityUid>();
|
||||||
foreach (var part in SlotParts.Keys)
|
foreach (var part in SlotParts.Keys)
|
||||||
{
|
{
|
||||||
if (!metaQuery.HasComponent(part.Owner))
|
if (!metaQuery.TryGetComponent(part.Owner, out var meta) ||
|
||||||
|
meta.EntityLifeStage >= EntityLifeStage.Terminating)
|
||||||
{
|
{
|
||||||
SlotParts.Remove(part);
|
SlotParts.Remove(part);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -94,6 +94,7 @@
|
|||||||
tags:
|
tags:
|
||||||
- Debug
|
- Debug
|
||||||
- type: Clickable
|
- type: Clickable
|
||||||
|
- type: PowerNetworkBattery
|
||||||
- type: InteractionOutline
|
- type: InteractionOutline
|
||||||
- type: Physics
|
- type: Physics
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
|
|||||||
Reference in New Issue
Block a user