diff --git a/GFramework.Core.Tests/ecs/EcsBasicTests.cs b/GFramework.Core.Tests/ecs/EcsBasicTests.cs
new file mode 100644
index 0000000..ca7d030
--- /dev/null
+++ b/GFramework.Core.Tests/ecs/EcsBasicTests.cs
@@ -0,0 +1,223 @@
+using System.Reflection;
+using Arch.Core;
+using GFramework.Core.Abstractions.ecs;
+using GFramework.Core.architecture;
+using GFramework.Core.ecs;
+using GFramework.Core.ecs.components;
+using GFramework.Core.ecs.systems;
+using GFramework.Core.ioc;
+using GFramework.Core.logging;
+using NUnit.Framework;
+
+namespace GFramework.Core.Tests.ecs;
+
+///
+/// ECS基础功能测试类,用于验证ECS系统的核心功能。
+/// 包括实体创建、组件设置、系统更新、实体销毁等基本操作。
+///
+[TestFixture]
+public class EcsBasicTests
+{
+ ///
+ /// 测试初始化方法,在每个测试方法执行前运行。
+ /// 负责初始化日志工厂、依赖注入容器和架构上下文。
+ ///
+ [SetUp]
+ public void Setup()
+ {
+ LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
+
+ _container = new MicrosoftDiContainer();
+ var loggerField = typeof(MicrosoftDiContainer).GetField("_logger",
+ BindingFlags.NonPublic | BindingFlags.Instance);
+ loggerField?.SetValue(_container,
+ LoggerFactoryResolver.Provider.CreateLogger(nameof(EcsBasicTests)));
+
+ _context = new ArchitectureContext(_container);
+ }
+
+ ///
+ /// 测试清理方法,在每个测试方法执行后运行。
+ /// 负责释放ECS世界资源并清空容器和上下文。
+ ///
+ [TearDown]
+ public void TearDown()
+ {
+ _ecsWorld?.Dispose();
+ _ecsWorld = null;
+ _container?.Clear();
+ _context = null;
+ }
+
+ private MicrosoftDiContainer? _container;
+ private ArchitectureContext? _context;
+ private EcsWorld? _ecsWorld;
+
+ ///
+ /// 初始化ECS系统并注册指定类型的系统实例。
+ ///
+ /// 需要注册的系统类型数组
+ private void InitializeEcsWithSystems(params Type[] systemTypes)
+ {
+ _ecsWorld = new EcsWorld();
+ _container!.Register(_ecsWorld);
+ _container.Register(_ecsWorld as IEcsWorld);
+
+ var systems = new List();
+ foreach (var systemType in systemTypes)
+ {
+ var system = (IEcsSystem)Activator.CreateInstance(systemType)!;
+ system.SetContext(_context!);
+ system.Init();
+ systems.Add(system);
+ _container.RegisterPlurality(system);
+ }
+
+ _container.Register(systems as IReadOnlyList);
+ }
+
+ ///
+ /// 测试ECS初始化功能,验证是否能正确创建EcsWorld实例。
+ ///
+ [Test]
+ public void Test_01_InitializeEcs_Should_Create_EcsWorld()
+ {
+ _context!.InitializeEcs();
+ var ecsWorld = _context.GetEcsWorld();
+
+ Assert.That(ecsWorld, Is.Not.Null, "EcsWorld should be created");
+ Assert.That(ecsWorld.EntityCount, Is.EqualTo(0), "Initial entity count should be 0");
+ }
+
+ ///
+ /// 测试实体创建功能,验证能否成功创建带有指定组件的实体。
+ ///
+ [Test]
+ public void Test_02_CreateEntity_Should_Work()
+ {
+ _ecsWorld = new EcsWorld();
+ var entity = _ecsWorld.CreateEntity(typeof(Position), typeof(Velocity));
+
+ Assert.That(_ecsWorld.EntityCount, Is.EqualTo(1), "Entity count should be 1");
+ Assert.That(_ecsWorld.IsAlive(entity), Is.True, "Entity should be alive");
+ }
+
+ ///
+ /// 测试组件设置功能,验证能否正确存储和获取组件数据。
+ ///
+ [Test]
+ public void Test_03_SetComponent_Should_Store_Data()
+ {
+ _ecsWorld = new EcsWorld();
+ var entity = _ecsWorld.CreateEntity(typeof(Position));
+ var world = _ecsWorld.InternalWorld;
+
+ world.Set(entity, 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()
+ {
+ InitializeEcsWithSystems(typeof(MovementSystem));
+
+ var entity = _ecsWorld!.CreateEntity(typeof(Position), typeof(Velocity));
+
+ var world = _ecsWorld.InternalWorld;
+ world.Set(entity, new Position(0, 0));
+ world.Set(entity, new Velocity(10, 5));
+
+ var systems = _container!.Get>();
+ Assert.That(systems, Is.Not.Null);
+ Assert.That(systems!.Count, Is.GreaterThan(0));
+
+ var movementSystem = systems.First(s => s is MovementSystem) as MovementSystem;
+ Assert.That(movementSystem, Is.Not.Null);
+
+ movementSystem!.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()
+ {
+ _ecsWorld = new EcsWorld();
+ var entity = _ecsWorld.CreateEntity(typeof(Position));
+
+ _ecsWorld.DestroyEntity(entity);
+
+ Assert.That(_ecsWorld.EntityCount, Is.EqualTo(0), "Entity count should be 0");
+ Assert.That(_ecsWorld.IsAlive(entity), Is.False, "Entity should not be alive");
+ }
+
+ ///
+ /// 测试世界清理功能,验证能否清除所有实体。
+ ///
+ [Test]
+ public void Test_06_ClearWorld_Should_Remove_All_Entities()
+ {
+ _ecsWorld = new EcsWorld();
+ for (int i = 0; i < 10; i++)
+ {
+ _ecsWorld.CreateEntity(typeof(Position));
+ }
+
+ _ecsWorld.Clear();
+
+ Assert.That(_ecsWorld.EntityCount, Is.EqualTo(0), "Entity count should be 0 after clear");
+ }
+
+ ///
+ /// 测试多个实体的批量更新功能,验证系统能否正确处理多个实体的更新。
+ ///
+ [Test]
+ public void Test_07_Multiple_Entities_Should_Update_Correctly()
+ {
+ InitializeEcsWithSystems(typeof(MovementSystem));
+
+ var world = _ecsWorld!.InternalWorld;
+ var entities = new Entity[10];
+
+ for (var i = 0; i < 10; i++)
+ {
+ entities[i] = _ecsWorld.CreateEntity(typeof(Position), typeof(Velocity));
+ world.Set(entities[i], new Position(0, 0));
+ world.Set(entities[i], new Velocity(i, i * 2));
+ }
+
+ var systems = _container!.Get>();
+ var movementSystem = systems!.First(s => s is MovementSystem) as MovementSystem;
+
+ movementSystem!.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}");
+ }
+ }
+
+ ///
+ /// 测试未初始化情况下获取ECS世界的异常处理。
+ ///
+ [Test]
+ public void Test_08_GetEcsWorld_Without_Initialize_Should_Throw()
+ {
+ Assert.Throws(() => { _context!.GetEcsWorld(); },
+ "Getting EcsWorld without initialization should throw");
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/ecs/EcsIntegrationTests.cs b/GFramework.Core.Tests/ecs/EcsIntegrationTests.cs
new file mode 100644
index 0000000..dde6c2d
--- /dev/null
+++ b/GFramework.Core.Tests/ecs/EcsIntegrationTests.cs
@@ -0,0 +1,352 @@
+using System.Reflection;
+using Arch.Core;
+using GFramework.Core.Abstractions.ecs;
+using GFramework.Core.architecture;
+using GFramework.Core.ecs;
+using GFramework.Core.ecs.components;
+using GFramework.Core.ecs.systems;
+using GFramework.Core.ioc;
+using GFramework.Core.logging;
+using NUnit.Framework;
+
+namespace GFramework.Core.Tests.ecs;
+
+///
+/// ECS集成测试类,用于验证ECS系统的整体功能和性能表现。
+/// 包括实体管理、组件操作、系统调度、优先级控制以及性能基准测试。
+///
+[TestFixture]
+public class EcsIntegrationTests
+{
+ ///
+ /// 测试初始化方法,在每个测试方法执行前运行。
+ /// 负责初始化日志工厂、依赖注入容器和架构上下文。
+ ///
+ [SetUp]
+ public void Setup()
+ {
+ LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
+
+ _container = new MicrosoftDiContainer();
+ var loggerField = typeof(MicrosoftDiContainer).GetField("_logger",
+ BindingFlags.NonPublic | BindingFlags.Instance);
+ loggerField?.SetValue(_container,
+ LoggerFactoryResolver.Provider.CreateLogger(nameof(EcsIntegrationTests)));
+
+ _context = new ArchitectureContext(_container);
+ }
+
+ ///
+ /// 测试清理方法,在每个测试方法执行后运行。
+ /// 负责释放ECS世界资源并清空容器和上下文。
+ ///
+ [TearDown]
+ public void TearDown()
+ {
+ _ecsWorld?.Dispose();
+ _ecsWorld = null;
+ _container?.Clear();
+ _context = null;
+ }
+
+ private MicrosoftDiContainer? _container;
+ private ArchitectureContext? _context;
+ private EcsWorld? _ecsWorld;
+
+ ///
+ /// 初始化ECS系统并注册指定类型的系统实例。
+ ///
+ /// 需要注册的系统类型数组
+ private void InitializeEcsWithSystems(params Type[] systemTypes)
+ {
+ _ecsWorld = new EcsWorld();
+ _container!.Register(_ecsWorld);
+ _container.Register(_ecsWorld as IEcsWorld);
+
+ var systems = new List();
+ foreach (var systemType in systemTypes)
+ {
+ var system = (IEcsSystem)Activator.CreateInstance(systemType)!;
+ system.SetContext(_context!);
+ system.Init();
+ systems.Add(system);
+ _container.RegisterPlurality(system);
+ }
+
+ _container.Register(systems as IReadOnlyList);
+ }
+
+ ///
+ /// 测试ECS初始化功能,验证是否能正确创建EcsWorld实例。
+ ///
+ [Test]
+ public void InitializeEcs_Should_Create_EcsWorld()
+ {
+ _context!.InitializeEcs();
+ var ecsWorld = _context.GetEcsWorld();
+
+ Assert.That(ecsWorld, Is.Not.Null);
+ Assert.That(ecsWorld.EntityCount, Is.EqualTo(0));
+ }
+
+ ///
+ /// 测试实体创建功能,验证创建实体后实体计数是否正确增加。
+ ///
+ [Test]
+ public void CreateEntity_Should_Increase_EntityCount()
+ {
+ _ecsWorld = new EcsWorld();
+ var entity = _ecsWorld.CreateEntity(typeof(Position), typeof(Velocity));
+
+ Assert.That(_ecsWorld.EntityCount, Is.EqualTo(1));
+ Assert.That(_ecsWorld.IsAlive(entity), Is.True);
+ }
+
+ ///
+ /// 测试实体销毁功能,验证销毁实体后实体计数是否正确减少。
+ ///
+ [Test]
+ public void DestroyEntity_Should_Decrease_EntityCount()
+ {
+ _ecsWorld = new EcsWorld();
+ var entity = _ecsWorld.CreateEntity(typeof(Position));
+
+ _ecsWorld.DestroyEntity(entity);
+
+ Assert.That(_ecsWorld.EntityCount, Is.EqualTo(0));
+ Assert.That(_ecsWorld.IsAlive(entity), Is.False);
+ }
+
+ ///
+ /// 测试组件设置功能,验证能否正确存储和获取组件数据。
+ ///
+ [Test]
+ public void SetComponent_Should_Store_ComponentData()
+ {
+ _ecsWorld = new EcsWorld();
+ var entity = _ecsWorld.CreateEntity(typeof(Position));
+
+ var world = _ecsWorld.InternalWorld;
+ world.Set(entity, new Position(10, 20));
+
+ Assert.That(world.Has(entity), Is.True);
+ ref var pos = ref world.Get(entity);
+ Assert.That(pos.X, Is.EqualTo(10));
+ Assert.That(pos.Y, Is.EqualTo(20));
+ }
+
+ ///
+ /// 测试世界清理功能,验证能否清除所有实体。
+ ///
+ [Test]
+ public void ClearWorld_Should_Remove_All_Entities()
+ {
+ _ecsWorld = new EcsWorld();
+ for (int i = 0; i < 10; i++)
+ {
+ _ecsWorld.CreateEntity(typeof(Position));
+ }
+
+ _ecsWorld.Clear();
+
+ Assert.That(_ecsWorld.EntityCount, Is.EqualTo(0));
+ }
+
+ ///
+ /// 测试ECS系统注册功能,验证系统能否正确添加到运行器中。
+ ///
+ [Test]
+ public void RegisterEcsSystem_Should_Add_System_To_Runner()
+ {
+ InitializeEcsWithSystems(typeof(MovementSystem));
+
+ var systems = _container!.Get>();
+ Assert.That(systems, Is.Not.Null);
+ Assert.That(systems!.Count, Is.EqualTo(1));
+ Assert.That(systems[0], Is.InstanceOf());
+ }
+
+ ///
+ /// 测试移动系统功能,验证系统能否正确更新单个实体的位置。
+ ///
+ [Test]
+ public void MovementSystem_Should_Update_Position()
+ {
+ InitializeEcsWithSystems(typeof(MovementSystem));
+
+ var entity = _ecsWorld!.CreateEntity(typeof(Position), typeof(Velocity));
+
+ var world = _ecsWorld.InternalWorld;
+ world.Set(entity, new Position(0, 0));
+ world.Set(entity, new Velocity(10, 5));
+
+ var systems = _container!.Get>();
+ var movementSystem = systems!.First(s => s is MovementSystem) as MovementSystem;
+
+ movementSystem!.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 MovementSystem_Should_Update_Multiple_Entities()
+ {
+ InitializeEcsWithSystems(typeof(MovementSystem));
+
+ var world = _ecsWorld!.InternalWorld;
+ var entities = new Entity[100];
+
+ for (var i = 0; i < 100; i++)
+ {
+ entities[i] = _ecsWorld.CreateEntity(typeof(Position), typeof(Velocity));
+ world.Set(entities[i], new Position(0, 0));
+ world.Set(entities[i], new Velocity(i, i * 2));
+ }
+
+ var systems = _container!.Get>();
+ var movementSystem = systems!.First(s => s is MovementSystem) as MovementSystem;
+
+ movementSystem!.Update(0.5f);
+
+ for (var i = 0; i < 100; i++)
+ {
+ ref var pos = ref world.Get(entities[i]);
+ Assert.That(pos.X, Is.EqualTo(i * 0.5f).Within(0.001f));
+ Assert.That(pos.Y, Is.EqualTo(i * 2 * 0.5f).Within(0.001f));
+ }
+ }
+
+ ///
+ /// 测试ECS系统运行器的优先级调度功能,验证系统是否按优先级顺序执行。
+ ///
+ [Test]
+ public void EcsSystemRunner_Should_Respect_Priority()
+ {
+ InitializeEcsWithSystems(typeof(LowPrioritySystem), typeof(HighPrioritySystem));
+
+ var systems = _container!.Get>();
+ Assert.That(systems, Is.Not.Null);
+ Assert.That(systems!.Count, Is.EqualTo(2));
+
+ var sortedSystems = systems.OrderBy(s => s.Priority).ToList();
+ Assert.That(sortedSystems[0], Is.InstanceOf());
+ Assert.That(sortedSystems[1], Is.InstanceOf());
+ }
+
+ ///
+ /// 测试未初始化情况下获取ECS世界的异常处理。
+ ///
+ [Test]
+ public void GetEcsWorld_Without_Initialize_Should_Throw()
+ {
+ Assert.Throws(() => { _context!.GetEcsWorld(); });
+ }
+
+ ///
+ /// 性能基准测试:验证更新10000个实体的性能表现。
+ ///
+ [Test]
+ public void Performance_Test_10000_Entities()
+ {
+ InitializeEcsWithSystems(typeof(MovementSystem));
+
+ var world = _ecsWorld!.InternalWorld;
+
+ for (int i = 0; i < 10000; i++)
+ {
+ var entity = _ecsWorld.CreateEntity(typeof(Position), typeof(Velocity));
+ world.Set(entity, new Position(0, 0));
+ world.Set(entity, new Velocity(1, 1));
+ }
+
+ var systems = _container!.Get>();
+ var movementSystem = systems!.First(s => s is MovementSystem) as MovementSystem;
+
+ var startTime = DateTime.UtcNow;
+ movementSystem!.Update(0.016f);
+ var elapsed = (DateTime.UtcNow - startTime).TotalMilliseconds;
+
+ Assert.That(_ecsWorld.EntityCount, Is.EqualTo(10000));
+ Assert.That(elapsed, Is.LessThan(100), $"Updating 10000 entities took: {elapsed}ms");
+ }
+
+ ///
+ /// 性能基准测试:验证创建1000个实体的性能表现。
+ ///
+ [Test]
+ public void Performance_Test_1000_Entities_Creation()
+ {
+ _ecsWorld = new EcsWorld();
+ var world = _ecsWorld.InternalWorld;
+
+ var startTime = DateTime.UtcNow;
+ for (int i = 0; i < 1000; i++)
+ {
+ var entity = _ecsWorld.CreateEntity(typeof(Position), typeof(Velocity));
+ world.Set(entity, new Position(0, 0));
+ world.Set(entity, new Velocity(1, 1));
+ }
+
+ var elapsed = (DateTime.UtcNow - startTime).TotalMilliseconds;
+
+ Assert.That(_ecsWorld.EntityCount, Is.EqualTo(1000));
+ Assert.That(elapsed, Is.LessThan(50), $"Creating 1000 entities took: {elapsed}ms");
+ }
+}
+
+///
+/// 高优先级系统示例,用于测试系统调度优先级功能。
+///
+public class HighPrioritySystem : EcsSystemBase
+{
+ ///
+ /// 获取系统优先级,数值越小优先级越高。
+ ///
+ public override int Priority => -100;
+
+ ///
+ /// ECS初始化回调方法。
+ ///
+ protected override void OnEcsInit()
+ {
+ }
+
+ ///
+ /// 系统更新方法。
+ ///
+ /// 帧间隔时间
+ public override void Update(float deltaTime)
+ {
+ }
+}
+
+///
+/// 低优先级系统示例,用于测试系统调度优先级功能。
+///
+public class LowPrioritySystem : EcsSystemBase
+{
+ ///
+ /// 获取系统优先级,数值越大优先级越低。
+ ///
+ public override int Priority => 100;
+
+ ///
+ /// ECS初始化回调方法。
+ ///
+ protected override void OnEcsInit()
+ {
+ }
+
+ ///
+ /// 系统更新方法。
+ ///
+ /// 帧间隔时间
+ public override void Update(float deltaTime)
+ {
+ }
+}
\ No newline at end of file
diff --git a/GFramework.Core.Tests/mediator/MediatorComprehensiveTests.cs b/GFramework.Core.Tests/mediator/MediatorComprehensiveTests.cs
index 771334a..bf09075 100644
--- a/GFramework.Core.Tests/mediator/MediatorComprehensiveTests.cs
+++ b/GFramework.Core.Tests/mediator/MediatorComprehensiveTests.cs
@@ -214,9 +214,9 @@ public class MediatorComprehensiveTests
var results = new List();
// 流应该在100ms后被取消(TaskCanceledException 继承自 OperationCanceledException)
- Assert.ThrowsAsync(async () =>
+ Assert.ThrowsAsync(async () =>
{
- await foreach (var item in stream.WithCancellation(cts.Token))
+ await foreach (var item in stream)
{
results.Add(item);
}
@@ -531,7 +531,7 @@ public sealed class TestValidatedCommandHandler : IRequestHandler