Files
RobustToolbox/Robust.Shared.IntegrationTests/GameObjects/DeferredEntityDeletionTest.cs

145 lines
5.8 KiB
C#

using System.Threading.Tasks;
using NUnit.Framework;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Reflection;
namespace Robust.UnitTesting.Shared.GameObjects;
internal sealed partial class DeferredEntityDeletionTest : RobustIntegrationTest
{
// This test ensures that deferred deletion can be used while handling events without issue, and that deleting an
// entity after deferring component removal doesn't cause any issues.
[Test]
public async Task TestDeferredEntityDeletion()
{
var options = new ServerIntegrationOptions();
options.Pool = false;
options.BeforeRegisterComponents += () =>
{
var fact = IoCManager.Resolve<IComponentFactory>();
fact.RegisterClass<DeferredDeletionTestComponent>();
fact.RegisterClass<OtherDeferredDeletionTestComponent>();
};
options.BeforeStart += () =>
{
var sysMan = IoCManager.Resolve<IEntitySystemManager>();
sysMan.LoadExtraSystemType<DeferredDeletionTestSystem>();
sysMan.LoadExtraSystemType<OtherDeferredDeletionTestSystem>();
};
var server = StartServer(options);
await server.WaitIdleAsync();
EntityUid uid1 = default, uid2 = default, uid3 = default, uid4 = default;
DeferredDeletionTestComponent comp1 = default!, comp2 = default!, comp3 = default!, comp4 = default!;
IEntityManager entMan = default!;
await server.WaitAssertion(() =>
{
entMan = IoCManager.Resolve<IEntityManager>();
var sys = entMan.EntitySysManager.GetEntitySystem<DeferredDeletionTestSystem>();
uid1 = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
uid2 = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
uid3 = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
uid4 = entMan.SpawnEntity(null, MapCoordinates.Nullspace);
comp1 = entMan.AddComponent<DeferredDeletionTestComponent>(uid1);
comp2 = entMan.AddComponent<DeferredDeletionTestComponent>(uid2);
comp3 = entMan.AddComponent<DeferredDeletionTestComponent>(uid3);
comp4 = entMan.AddComponent<DeferredDeletionTestComponent>(uid4);
entMan.AddComponent<OtherDeferredDeletionTestComponent>(uid1);
entMan.AddComponent<OtherDeferredDeletionTestComponent>(uid2);
entMan.AddComponent<OtherDeferredDeletionTestComponent>(uid3);
entMan.AddComponent<OtherDeferredDeletionTestComponent>(uid4);
});
await server.WaitRunTicks(1);
// first: test that deferring deletion while handling events doesn't cause issues
await server.WaitAssertion(() =>
{
Assert.That(comp1.Running);
var ev = new DeferredDeletionTestEvent();
entMan.EventBus.RaiseLocalEvent(uid1, ev);
Assert.That(comp1.LifeStage == ComponentLifeStage.Stopped);
});
await server.WaitRunTicks(1);
Assert.That(comp1.LifeStage == ComponentLifeStage.Deleted);
// next check that entity deletion doesn't cause issues:
await server.WaitAssertion(() =>
{
var ev = new DeferredDeletionTestEvent();
entMan.EventBus.RaiseLocalEvent(uid2, ev);
entMan.EventBus.RaiseLocalEvent(uid3, ev);
entMan.EventBus.RaiseLocalEvent(uid4, ev);
entMan.DeleteEntity(uid2);
entMan.QueueDeleteEntity(uid3);
entMan.TryQueueDeleteEntity(uid4);
Assert.That(entMan.Deleted(uid2));
Assert.That(!entMan.Deleted(uid3));
Assert.That(!entMan.Deleted(uid4));
Assert.That(comp2.LifeStage == ComponentLifeStage.Deleted);
Assert.That(comp3.LifeStage == ComponentLifeStage.Stopped);
Assert.That(comp4.LifeStage == ComponentLifeStage.Stopped);
});
await server.WaitRunTicks(1);
Assert.That(comp3.LifeStage == ComponentLifeStage.Deleted);
Assert.That(comp4.LifeStage == ComponentLifeStage.Deleted);
Assert.That(entMan.Deleted(uid3));
Assert.That(entMan.Deleted(uid4));
await server.WaitIdleAsync();
}
[Reflect(false)]
private sealed partial class DeferredDeletionTestSystem : EntitySystem
{
public override void Initialize()
{
SubscribeLocalEvent<DeferredDeletionTestComponent, DeferredDeletionTestEvent>(OnTestEvent);
}
private void OnTestEvent(EntityUid uid, DeferredDeletionTestComponent component, DeferredDeletionTestEvent args)
{
// remove both this component, and some other component that this entity has that also subscribes to this event.
RemCompDeferred<DeferredDeletionTestComponent>(uid);
RemCompDeferred<OtherDeferredDeletionTestComponent>(uid);
}
}
[Reflect(false)]
private sealed partial class OtherDeferredDeletionTestSystem : EntitySystem
{
public override void Initialize() => SubscribeLocalEvent<OtherDeferredDeletionTestComponent, DeferredDeletionTestEvent>(OnTestEvent);
private void OnTestEvent(EntityUid uid, OtherDeferredDeletionTestComponent component, DeferredDeletionTestEvent args)
{
// remove both this component, and some other component that this entity has that also subscribes to this event.
RemCompDeferred<DeferredDeletionTestComponent>(uid);
RemCompDeferred<OtherDeferredDeletionTestComponent>(uid);
}
}
[RegisterComponent]
[Reflect(false)]
private sealed partial class DeferredDeletionTestComponent : Component
{
}
[Reflect(false)]
private sealed partial class OtherDeferredDeletionTestComponent : Component
{
}
private sealed class DeferredDeletionTestEvent
{
}
}