using System.Diagnostics.CodeAnalysis;
using Arch.Core;
using GFramework.Core.Abstractions.Rule;
using GFramework.Core.Architectures;
using GFramework.Core.Ioc;
using GFramework.Ecs.Arch.Components;
using GFramework.Ecs.Arch.Systems;
namespace GFramework.Ecs.Arch.Tests.Ecs;
///
/// ECS 基础功能测试类 - 使用 Arch 原生 API
///
[TestFixture]
[Experimental("GFrameworkECS")]
public class EcsBasicTests
{
[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;
///
/// 初始化 ECS 模块
///
private void InitializeEcsModule()
{
// 注册系统(直接继承 ArchSystemAdapter,它继承自 AbstractSystem)
var movementSystem = new MovementSystem();
((IContextAware)movementSystem).SetContext(_context!);
_container!.RegisterPlurality(movementSystem);
// 创建并注册 ArchEcsModule
_ecsModule = new ArchEcsModule(enabled: true);
_ecsModule.Register(_container);
_ecsModule.Initialize();
// 获取 World
_world = _container.Get();
}
[Test]
public void Test_01_InitializeEcs_Should_Create_World()
{
InitializeEcsModule();
Assert.That(_world, Is.Not.Null, "World should be created");
Assert.That(_world!.Size, Is.EqualTo(0), "Initial entity count should be 0");
}
[Test]
public void Test_02_CreateEntity_Should_Work()
{
InitializeEcsModule();
var entity = _world!.Create(new Position(0, 0), new Velocity(1, 1));
Assert.That(_world.Size, Is.EqualTo(1), "Entity count should be 1");
Assert.That(_world.IsAlive(entity), Is.True, "Entity should be alive");
}
[Test]
public void Test_03_SetComponent_Should_Store_Data()
{
InitializeEcsModule();
var entity = _world!.Create(new Position(10, 20));
Assert.That(_world.Has(entity), Is.True, "Entity should have Position component");
ref var pos = ref _world.Get(entity);
Assert.That(pos.X, Is.EqualTo(10), "Position.X should be 10");
Assert.That(pos.Y, Is.EqualTo(20), "Position.Y should be 20");
}
[Test]
public void Test_04_MovementSystem_Should_Update_Position()
{
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), "X position should be 10");
Assert.That(pos.Y, Is.EqualTo(5).Within(0.001f), "Y position should be 5");
}
[Test]
public void Test_05_DestroyEntity_Should_Work()
{
InitializeEcsModule();
var entity = _world!.Create(new Position(0, 0));
_world.Destroy(entity);
Assert.That(_world.Size, Is.EqualTo(0), "Entity count should be 0");
Assert.That(_world.IsAlive(entity), Is.False, "Entity should not be alive");
}
[Test]
public void Test_06_ClearWorld_Should_Remove_All_Entities()
{
InitializeEcsModule();
for (int i = 0; i < 10; i++)
{
_world!.Create(new Position(0, 0));
}
_world!.Clear();
Assert.That(_world.Size, Is.EqualTo(0), "Entity count should be 0 after clear");
}
[Test]
public void Test_07_Multiple_Entities_Should_Update_Correctly()
{
InitializeEcsModule();
var entities = new Entity[10];
for (var i = 0; i < 10; i++)
{
entities[i] = _world!.Create(new Position(0, 0), new Velocity(i, i * 2));
}
// 更新系统
_ecsModule!.Update(1.0f);
for (int i = 0; i < 10; i++)
{
ref var pos = ref _world!.Get(entities[i]);
Assert.That(pos.X, Is.EqualTo(i).Within(0.001f), $"Entity {i} X position should be {i}");
Assert.That(pos.Y, Is.EqualTo(i * 2).Within(0.001f), $"Entity {i} Y position should be {i * 2}");
}
}
}