using System.Diagnostics.CodeAnalysis; using Arch.Core; using GFramework.Core.Abstractions.rule; using GFramework.Core.architecture; using GFramework.Core.ecs; using GFramework.Core.ecs.components; using GFramework.Core.ecs.systems; using GFramework.Core.ioc; using NUnit.Framework; namespace GFramework.Core.Tests.ecs; /// /// ECS 高级功能测试类 - 使用 Arch 原生 API /// [TestFixture] [Experimental("GFrameworkECS")] public class EcsAdvancedTests { [SetUp] public void Setup() { _container = new MicrosoftDiContainer(); _context = new ArchitectureContext(_container); } [TearDown] public void TearDown() { if (_world != null) { World.Destroy(_world); _world = null; } _container?.Clear(); _context = null; _ecsModule = null; } private MicrosoftDiContainer? _container; private ArchitectureContext? _context; private World? _world; private ArchEcsModule? _ecsModule; private void InitializeEcsModule() { var movementSystem = new MovementSystem(); ((IContextAware)movementSystem).SetContext(_context!); _container!.RegisterPlurality(movementSystem); _ecsModule = new ArchEcsModule(enabled: true); _ecsModule.Register(_container); _ecsModule.Initialize(); _world = _container.Get(); } [Test] public void World_Destroy_Should_Be_Safe() { InitializeEcsModule(); _world!.Create(new Position(0, 0)); Assert.DoesNotThrow(() => { World.Destroy(_world); _world = null; }); } [Test] public void World_CreateEntity_WithNoComponents_Should_Work() { InitializeEcsModule(); var entity = _world!.Create(); Assert.That(_world.Size, Is.EqualTo(1)); Assert.That(_world.IsAlive(entity), Is.True); } [Test] public void World_CreateEntity_WithMultipleComponents_Should_Work() { InitializeEcsModule(); var entity = _world!.Create(new Position(0, 0), new Velocity(1, 1)); Assert.That(_world.Has(entity), Is.True); Assert.That(_world.Has(entity), Is.True); } [Test] public void World_IsAlive_AfterDestroy_Should_ReturnFalse() { InitializeEcsModule(); var entity = _world!.Create(new Position(0, 0)); Assert.That(_world.IsAlive(entity), Is.True); _world.Destroy(entity); Assert.That(_world.IsAlive(entity), Is.False); } [Test] public void ArchEcsModule_Update_Should_UpdateSystems() { InitializeEcsModule(); var entity = _world!.Create(new Position(0, 0), new Velocity(10, 5)); _ecsModule!.Update(1.0f); ref var pos = ref _world.Get(entity); Assert.That(pos.X, Is.EqualTo(10).Within(0.001f)); Assert.That(pos.Y, Is.EqualTo(5).Within(0.001f)); } [Test] public void ArchEcsModule_WithNoSystems_Should_NotThrow() { // 不注册任何系统 _ecsModule = new ArchEcsModule(enabled: true); _ecsModule.Register(_container!); _ecsModule.Initialize(); _world = _container!.Get(); Assert.DoesNotThrow(() => _ecsModule.Update(1.0f)); } [Test] public void ChainedUpdates_Should_AccumulateChanges() { InitializeEcsModule(); var entity = _world!.Create(new Position(0, 0), new Velocity(10, 0)); _ecsModule!.Update(1.0f); _ecsModule.Update(1.0f); ref var pos = ref _world.Get(entity); Assert.That(pos.X, Is.EqualTo(20).Within(0.001f), "Position should accumulate over multiple updates"); } [Test] public void Component_AddAfterCreation_Should_Work() { InitializeEcsModule(); var entity = _world!.Create(); _world.Add(entity, new Position(5, 10)); Assert.That(_world.Has(entity), Is.True); ref var pos = ref _world.Get(entity); Assert.That(pos.X, Is.EqualTo(5)); Assert.That(pos.Y, Is.EqualTo(10)); } [Test] public void Component_Remove_Should_Work() { InitializeEcsModule(); var entity = _world!.Create(new Position(0, 0), new Velocity(1, 1)); _world.Remove(entity); Assert.That(_world.Has(entity), Is.True); Assert.That(_world.Has(entity), Is.False); } [Test] public void Component_Replace_Should_Work() { InitializeEcsModule(); var entity = _world!.Create(new Position(1, 1)); _world.Set(entity, new Position(100, 200)); ref var pos = ref _world.Get(entity); Assert.That(pos.X, Is.EqualTo(100)); Assert.That(pos.Y, Is.EqualTo(200)); } [Test] public async Task ArchEcsModule_DestroyAsync_Should_CleanupResources() { InitializeEcsModule(); _world!.Create(new Position(0, 0)); Assert.That(_world.Size, Is.EqualTo(1)); await _ecsModule!.DestroyAsync(); // World 应该已经被销毁 _world = null; } [Test] public void MultipleEntities_WithDifferentComponents_Should_CoExist() { InitializeEcsModule(); var entity1 = _world!.Create(new Position(0, 0), new Velocity(1, 1)); var entity2 = _world.Create(new Position(10, 10)); var entity3 = _world.Create(new Velocity(5, 5)); Assert.That(_world.Size, Is.EqualTo(3)); Assert.That(_world.Has(entity1), Is.True); Assert.That(_world.Has(entity1), Is.True); Assert.That(_world.Has(entity2), Is.True); Assert.That(_world.Has(entity2), Is.False); Assert.That(_world.Has(entity3), Is.False); Assert.That(_world.Has(entity3), Is.True); } }